【得捷电子Follow me第4期】任务综合帖(从入门任务到终极任务)
[复制链接]
本期的主角——W5500-EVB-Pico。然后又购买了一片四色墨水屏(2.66" EPD, SPECTRA B/W/R/Y, W.IT)+墨水屏驱动板(EXT3 - EPD EXTENSION BOARD)
演示视频:https://training.eeworld.com.cn/video/39538
入门任务:环境搭建、点灯与 helloworld
墨水屏没有找到mpy的驱动包,所以使用Arduino驱动墨水屏。编程工具使用VScode+platformio。安装墨水屏驱动包PDLS_EXT3_Basic_BWRY
驱动板与pico之间接线方法参考官方提供说明
接下来就是照着例程写个hello Word的代码了!墨水屏显示内容确实非常清晰,颜色也挺不错的。就是显示速度太慢了。
#include <Arduino.h>
// Screen
#include "PDLS_EXT3_Basic_BWRY.h"
// SDK
// #include <Arduino.h>
#include "hV_HAL_Peripherals.h"
#include "hV_Configuration.h"
// Define structures and classes
Screen_EPD_EXT3 myScreen(eScreen_EPD_EXT3_266_BWRY, boardRaspberryPiPico_RP2040);
void displayPaletteBWRY()
{
uint16_t y = 10;
myScreen.setOrientation(ORIENTATION_LANDSCAPE);
myScreen.selectFont(Font_Terminal16x24);
myScreen.gText(10, y, "Hell World!", myColours.red);
y += myScreen.characterSizeY()+20;
myScreen.selectFont(Font_Terminal12x16);
myScreen.gText(10, y, "This is Follow me 4.", myColours.yellow);
y += myScreen.characterSizeY()+12;
y += myScreen.characterSizeY();
myScreen.selectFont(Font_Terminal8x12);
myScreen.gText(10, y, "Thank EEWORLD,Thank DigiKey!");
y += myScreen.characterSizeY();
myScreen.flush();
}
void setup()
{
Serial.begin(115200);
delay(500);
pinMode(LED_BUILTIN, OUTPUT);
myScreen.begin();
Serial.println("DISPLAY_PALETTE_BWRY... ");
myScreen.clear();
displayPaletteBWRY();
}
void loop()
{
digitalWrite(LED_BUILTIN, HIGH); // turn the LED on (HIGH is the voltage level)
delay(1000); // wait for a second
digitalWrite(LED_BUILTIN, LOW); // turn the LED off by making the voltage LOW
delay(1000); // wait for a second
}
f171f5bff1ee0672429fa703749d14ea
基础任务一:完成主控板W5500初始化(静态IP配置),并能使用局域网电脑ping通,同时W5500可以ping通互联网站点;通过抓包软件(Wireshark、Sniffer等)抓取本地PC的ping报文,展示并分析。
找了手头的一个pico底板,板子上有128X64的OLED,4线spi驱动。用来做显示使用。墨水屏显示实在是太慢了。这个底板的GPIO18口,外接了ws2812LED灯,但是GPIO18管脚W5500需要使用,所以拔掉了GPIO18的排针。
使用ethernet库,参考例程,配置静态IP地址。并且在oled上显示。
#include <SPI.h>
#include <Ethernet.h>
#include <U8x8lib.h>
#include <SPI.h>
#define U8LOG_WIDTH 16
#define U8LOG_HEIGHT 8
uint8_t u8log_buffer[U8LOG_WIDTH * U8LOG_HEIGHT];
U8X8LOG u8x8log;
U8X8_SSD1306_128X64_NONAME_4W_SW_SPI u8x8(/* clock=*/10, /* data=*/11, /* cs=*/40, /* dc=*/9, /* reset=*/8);
byte mac[] = {0x00, 0xAA, 0xBB, 0xCC, 0xDE, 0x02};
IPAddress staticIP(192, 168, 2, 102);
IPAddress myDns(192, 168, 2, 1);
IPAddress gateway(192, 168, 2, 1);
IPAddress subnet(255, 255, 255, 0);
void printConnectionInformation()
{
Serial.print("[INFO] IP Address: ");
Serial.println(Ethernet.localIP());
Serial.print("[INFO] Subnet Mask: ");
Serial.println(Ethernet.subnetMask());
Serial.print("[INFO] Gateway: ");
Serial.println(Ethernet.gatewayIP());
Serial.print("[INFO] DNS: ");
Serial.println(Ethernet.dnsServerIP());
u8x8log.print("ip=");
u8x8log.print(Ethernet.localIP());
u8x8log.print("\n");
u8x8log.print("Mask=");
u8x8log.print(Ethernet.subnetMask());
u8x8log.print("\n");
u8x8log.print("DNS=");
u8x8log.print(Ethernet.dnsServerIP());
u8x8log.print("\n");
}
void setup()
{
Serial.begin(115200);
u8x8.begin();
u8x8.setFont(u8x8_font_chroma48medium8_r);
u8x8log.begin(u8x8, U8LOG_WIDTH, U8LOG_HEIGHT, u8log_buffer);
u8x8log.setRedrawMode(1); // 0: Update screen with newline, 1: Update screen for every char
//if (Ethernet.begin(mac) == 0) // 看看DHCP是否能动态分配ip给Arduino
//{
// Serial.println("[ERROR] Failed to Configure Ethernet using DHCP");
Ethernet.begin(mac, staticIP, myDns, gateway, subnet); // DHCP不能动态分配,就静态设置ip给Arduino
//}
// Check for Ethernet hardware present
if (Ethernet.hardwareStatus() == EthernetNoHardware)
{
Serial.println("Ethernet shield was not found. Sorry, can't run without hardware. :(");
while (true)
{
delay(1); // do nothing, no point running without Ethernet hardware
}
}
while (Ethernet.linkStatus() == LinkOFF)
{
Serial.println("Ethernet cable is not connected.");
delay(500);
}
// give the Ethernet shield a second to initialize:
delay(1000);
printConnectionInformation();
}
void loop()
{
}
从 上下载库,然后参考例程(ping.ino)改写上边的代码。这里遇到个奇怪的问题,似乎和OLED屏幕部分有冲突,只能将oled部分屏蔽。这里是ping网易(www.163.com )网站。
#include <SPI.h>
#include <Ethernet.h>
#include <EthernetICMP.h>
#include <U8x8lib.h>
#define U8LOG_WIDTH 16
#define U8LOG_HEIGHT 8
uint8_t u8log_buffer[U8LOG_WIDTH * U8LOG_HEIGHT];
U8X8LOG u8x8log;
// U8X8_SSD1306_128X64_NONAME_4W_SW_SPI u8x8(10, 11,40, 9, 8);
byte mac[] = {0x00, 0xAA, 0xBB, 0xCC, 0xDE, 0x02};
IPAddress staticIP(192, 168, 2, 103);
IPAddress myDns(192, 168, 2, 1);
IPAddress gateway(192, 168, 2, 1);
IPAddress subnet(255, 255, 255, 0);
IPAddress pingAddr(183,240,1,21); // ip address to ping
SOCKET pingSocket = 0;
char buffer [256];
EthernetICMPPing ping(pingSocket, (uint16_t)random(0, 255));
void printConnectionInformation()
{
Serial.print("[INFO] IP Address: ");
Serial.println(Ethernet.localIP());
Serial.print("[INFO] Subnet Mask: ");
Serial.println(Ethernet.subnetMask());
Serial.print("[INFO] Gateway: ");
Serial.println(Ethernet.gatewayIP());
Serial.print("[INFO] DNS: ");
Serial.println(Ethernet.dnsServerIP());
}
void setup()
{
Serial.begin(115200);
if (Ethernet.begin(mac) == 0) // 看看DHCP是否能动态分配ip给Arduino
{
Ethernet.begin(mac, staticIP, myDns, gateway, subnet); // DHCP不能动态分配,就静态设置ip给Arduino
}
// Check for Ethernet hardware present
if (Ethernet.hardwareStatus() == EthernetNoHardware)
{
Serial.println("Ethernet shield was not found. Sorry, can't run without hardware. :(");
while (true)
{
delay(1); // do nothing, no point running without Ethernet hardware
}
}
while (Ethernet.linkStatus() == LinkOFF)
{
Serial.println("Ethernet cable is not connected.");
delay(500);
}
// give the Ethernet shield a second to initialize:
delay(1000);
printConnectionInformation();
}
void loop()
{
EthernetICMPEchoReply echoReply = ping(pingAddr, 4);
if (echoReply.status == SUCCESS)
{
sprintf(buffer,
"Reply[%d] from: %d.%d.%d.%d: bytes=%d time=%ldms TTL=%d",
echoReply.data.seq,
echoReply.addr[0],
echoReply.addr[1],
echoReply.addr[2],
echoReply.addr[3],
REQ_DATASIZE,
millis() - echoReply.data.time,
echoReply.ttl);
}
else
{
sprintf(buffer, "Echo request failed; %d", echoReply.status);
}
Serial.println(buffer);
delay(500);
}
基础任务二:主控板建立TCPIP或UDP服务器,局域网PC使用TCPIP或UDP客户端进行连接并发送数据,主控板接收到数据后,送液晶屏显示(没有则通过串口打印显示);通过抓包软件抓取交互报文,展示并分析。(TCP和UDP二选一,或者全都操作)
这里我使用TCP协议,在W5500上建立了socker服务,使用的端口是8888.开发板监听着8888端口,当有客户端连接上来后,读取客户端发来的消息,在首次收到消息时,返回“Hello, client!”字符串给客户端。并且将客户端发来的消息通过串口输出,并在OLED上显示。
#include <SPI.h>
#include <Ethernet.h>
#include <U8x8lib.h>
#define U8LOG_WIDTH 16
#define U8LOG_HEIGHT 8
uint8_t u8log_buffer[U8LOG_WIDTH * U8LOG_HEIGHT];
U8X8LOG u8x8log;
U8X8_SSD1306_128X64_NONAME_4W_SW_SPI u8x8(10, 11, 40, 9, 8);
byte mac[] = {0x00, 0xAA, 0xBB, 0xCC, 0xDE, 0x02};
IPAddress staticIP(192, 168, 2, 104);
IPAddress myDns(192, 168, 2, 1);
IPAddress gateway(192, 168, 2, 1);
IPAddress subnet(255, 255, 255, 0);
EthernetServer server(8888);
bool alreadyConnected = false; // whether or not the client was connected previously
void printConnectionInformation()
{
Serial.print("[INFO] IP Address: ");
Serial.println(Ethernet.localIP());
Serial.print("[INFO] Subnet Mask: ");
Serial.println(Ethernet.subnetMask());
Serial.print("[INFO] Gateway: ");
Serial.println(Ethernet.gatewayIP());
Serial.print("[INFO] DNS: ");
Serial.println(Ethernet.dnsServerIP());
u8x8log.print("ip=");
u8x8log.println(Ethernet.localIP());
u8x8log.print("Mask=");
u8x8log.println(Ethernet.subnetMask());
u8x8log.print("DNS=");
u8x8log.println(Ethernet.dnsServerIP());
}
void setup()
{
Serial.begin(115200);
u8x8.begin();
u8x8.setFont(u8x8_font_chroma48medium8_r);
u8x8log.begin(u8x8, U8LOG_WIDTH, U8LOG_HEIGHT, u8log_buffer);
u8x8log.setRedrawMode(1); // 0: Update screen with newline, 1: Update screen for every char
if (Ethernet.begin(mac) == 0) // 看看DHCP是否能动态分配ip给Arduino
{
Ethernet.begin(mac, staticIP, myDns, gateway, subnet); // DHCP不能动态分配,就静态设置ip给Arduino
}
// Check for Ethernet hardware present
if (Ethernet.hardwareStatus() == EthernetNoHardware)
{
Serial.println("Ethernet shield was not found. Sorry, can't run without hardware. :(");
while (true)
{
delay(1); // do nothing, no point running without Ethernet hardware
}
}
while (Ethernet.linkStatus() == LinkOFF)
{
Serial.println("Ethernet cable is not connected.");
delay(500);
}
// give the Ethernet shield a second to initialize:
delay(1000);
printConnectionInformation();
server.begin();
}
void loop()
{
EthernetClient client = server.available();
// when the client sends the first byte, say hello:
if (client) {
if (!alreadyConnected) {
// clear out the input buffer:
client.flush();
Serial.println("We have a new client");
client.println("Hello, client!");
alreadyConnected = true;
}
if (client.available() > 0) {
// read the bytes incoming from the client:
char thisChar = client.read();
// echo the bytes back to the client:
server.write(thisChar);
// echo the bytes to the server as well:
Serial.write(thisChar);
u8x8log.print(thisChar);
}
}
}
进阶任务:从NTP服务器(注意数据交互格式的解析)同步时间,获取时间送显示屏(串口)显示。
参考Ethernet例程,使用udp方式与NTP服务器"time.nist.gov"进行校时。服务器获得的是UTC时间,转换为本地时间需要+8小时。
#include <SPI.h>
#include <Ethernet.h>
#include <U8x8lib.h>
#define U8LOG_WIDTH 16
#define U8LOG_HEIGHT 8
uint8_t u8log_buffer[U8LOG_WIDTH * U8LOG_HEIGHT];
U8X8LOG u8x8log;
U8X8_SSD1306_128X64_NONAME_4W_SW_SPI u8x8(10, 11, 40, 9, 8);
byte mac[] = {0x00, 0xAA, 0xBB, 0xCC, 0xDE, 0x02};
IPAddress staticIP(192, 168, 2, 104);
IPAddress myDns(192, 168, 2, 1);
IPAddress gateway(192, 168, 2, 1);
IPAddress subnet(255, 255, 255, 0);
unsigned int localPort = 8888; // local port to listen for UDP packets
const char timeServer[] = "time.nist.gov"; // time.nist.gov NTP server
const int NTP_PACKET_SIZE = 48; // NTP time stamp is in the first 48 bytes of the message
byte packetBuffer[NTP_PACKET_SIZE]; // buffer to hold incoming and outgoing packets
EthernetUDP Udp;
void printConnectionInformation()
{
Serial.print("[INFO] IP Address: ");
Serial.println(Ethernet.localIP());
Serial.print("[INFO] Subnet Mask: ");
Serial.println(Ethernet.subnetMask());
Serial.print("[INFO] Gateway: ");
Serial.println(Ethernet.gatewayIP());
Serial.print("[INFO] DNS: ");
Serial.println(Ethernet.dnsServerIP());
u8x8log.print("ip=");
u8x8log.println(Ethernet.localIP());
u8x8log.print("Mask=");
u8x8log.println(Ethernet.subnetMask());
u8x8log.print("DNS=");
u8x8log.println(Ethernet.dnsServerIP());
}
void setup()
{
Serial.begin(115200);
u8x8.begin();
u8x8.setFont(u8x8_font_chroma48medium8_r);
u8x8log.begin(u8x8, U8LOG_WIDTH, U8LOG_HEIGHT, u8log_buffer);
u8x8log.setRedrawMode(1); // 0: Update screen with newline, 1: Update screen for every char
if (Ethernet.begin(mac) == 0) // 看看DHCP是否能动态分配ip给Arduino
{
Ethernet.begin(mac, staticIP, myDns, gateway, subnet); // DHCP不能动态分配,就静态设置ip给Arduino
}
// Check for Ethernet hardware present
if (Ethernet.hardwareStatus() == EthernetNoHardware)
{
Serial.println("Ethernet shield was not found. Sorry, can't run without hardware. :(");
while (true)
{
delay(1); // do nothing, no point running without Ethernet hardware
}
}
while (Ethernet.linkStatus() == LinkOFF)
{
Serial.println("Ethernet cable is not connected.");
delay(500);
}
// give the Ethernet shield a second to initialize:
delay(1000);
printConnectionInformation();
Udp.begin(localPort);
}
// send an NTP request to the time server at the given address
void sendNTPpacket(const char *address)
{
// set all bytes in the buffer to 0
memset(packetBuffer, 0, NTP_PACKET_SIZE);
// Initialize values needed to form NTP request
// (see URL above for details on the packets)
packetBuffer[0] = 0b11100011; // LI, Version, Mode
packetBuffer[1] = 0; // Stratum, or type of clock
packetBuffer[2] = 6; // Polling Interval
packetBuffer[3] = 0xEC; // Peer Clock Precision
// 8 bytes of zero for Root Delay & Root Dispersion
packetBuffer[12] = 49;
packetBuffer[13] = 0x4E;
packetBuffer[14] = 49;
packetBuffer[15] = 52;
// all NTP fields have been given values, now
// you can send a packet requesting a timestamp:
Udp.beginPacket(address, 123); // NTP requests are to port 123
Udp.write(packetBuffer, NTP_PACKET_SIZE);
Udp.endPacket();
}
void loop()
{
int hour, min, sec;
char cur_time[9];
sendNTPpacket(timeServer); // send an NTP packet to a time server
// wait to see if a reply is available
delay(1000);
if (Udp.parsePacket())
{
// We've received a packet, read the data from it
Udp.read(packetBuffer, NTP_PACKET_SIZE); // read the packet into the buffer
// the timestamp starts at byte 40 of the received packet and is four bytes,
// or two words, long. First, extract the two words:
unsigned long highWord = word(packetBuffer[40], packetBuffer[41]);
unsigned long lowWord = word(packetBuffer[42], packetBuffer[43]);
// combine the four bytes (two words) into a long integer
// this is NTP time (seconds since Jan 1 1900):
unsigned long secsSince1900 = highWord << 16 | lowWord;
Serial.print("Seconds since Jan 1 1900 = ");
Serial.println(secsSince1900);
// now convert NTP time into everyday time:
Serial.print("Unix time = ");
// Unix time starts on Jan 1 1970. In seconds, that's 2208988800:
const unsigned long seventyYears = 2208988800UL;
// subtract seventy years:
unsigned long epoch = secsSince1900 - seventyYears;
// print Unix time:
Serial.println(epoch);
// print the hour, minute and second:
hour = (epoch % 86400L) / 3600+8;
min = (epoch % 3600) / 60;
sec = epoch % 60;
sprintf(cur_time, "%02d:%02d:%02d", hour, min, sec);
Serial.println(cur_time);
u8x8log.print("Time=");
u8x8log.println(cur_time);
delay(10000);
Ethernet.maintain();
}
}
1d4e245a60bc4d4f57adafb9c1fc52e3
终极任务二:使用外部存储器,组建简易FTP文件服务器,并能正常上传下载文件。
最后一个任务,是二选一的任务。德捷的官网访问总是有各种问题,经常让验证是否机器人。所以选择了任务2,建立ftp服务器。
使用Arduino编程,找到了一个SimpleFTPServer的库,但是看了一下,基本都需要挂载一个文件系统,用来做ftp的存储,手头没有SD卡模块。后来想到在使用MicroPython时,系统会为mpy划出一部分空间作为代码的存储区,使用这部分存储区域作为ftp的存储。于是按着这个思路,使用MicroPython来完成终极任务。
import socket
import network
import uos
import gc
from time import localtime
from machine import Pin,SPI
import time
def w5x00_init():
#spi init
spi=SPI(0,2_000_000, mosi=Pin(19),miso=Pin(16),sck=Pin(18))
nic = network.WIZNET5K(spi,Pin(17),Pin(20)) #spi,cs,reset pin
nic.active(True)#network active
nic.ifconfig(('192.168.2.104','255.255.255.0','192.168.2.1','8.8.8.8'))#Set static network address information
while not nic.isconnected():
time.sleep(1)
print(nic.regs())#Print register information
#Print network address information
print("IP Address:",nic.ifconfig()[0])
print("Subnet Mask:",nic.ifconfig()[1])
print("Gateway:",nic.ifconfig()[2])
print("DNS:",nic.ifconfig()[3])
return nic
month_name = ["", "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]
def send_list_data(path, dataclient, full):
try: # whether path is a directory name
for fname in uos.listdir(path):
dataclient.sendall(make_description(path, fname, full))
except: # path may be a file name or pattern
pattern = path.split("/")[-1]
path = path[:-(len(pattern) + 1)]
if path == "": path = "/"
for fname in uos.listdir(path):
if fncmp(fname, pattern) == True:
dataclient.sendall(make_description(path, fname, full))
def make_description(path, fname, full):
if full:
stat = uos.stat(get_absolute_path(path,fname))
file_permissions = "drwxr-xr-x" if (stat[0] & 0o170000 == 0o040000) else "-rw-r--r--"
file_size = stat[6]
tm = localtime(stat[7])
if tm[0] != localtime()[0]:
description = "{} 1 owner group {:>10} {} {:2} {:>5} {}\r\n".format(
file_permissions, file_size, month_name[tm[1]], tm[2], tm[0], fname)
else:
description = "{} 1 owner group {:>10} {} {:2} {:02}:{:02} {}\r\n".format(
file_permissions, file_size, month_name[tm[1]], tm[2], tm[3], tm[4], fname)
else:
description = fname + "\r\n"
return description
def send_file_data(path, dataclient):
with open(path, "r") as file:
chunk = file.read(512)
while len(chunk) > 0:
dataclient.sendall(chunk)
chunk = file.read(512)
def save_file_data(path, dataclient, mode):
with open(path, mode) as file:
chunk = dataclient.read(512)
while len(chunk) > 0:
file.write(chunk)
chunk = dataclient.read(512)
def get_absolute_path(cwd, payload):
# Just a few special cases "..", "." and ""
# If payload start's with /, set cwd to /
# and consider the remainder a relative path
if payload.startswith('/'):
cwd = "/"
for token in payload.split("/"):
if token == '..':
if cwd != '/':
cwd = '/'.join(cwd.split('/')[:-1])
if cwd == '':
cwd = '/'
elif token != '.' and token != '':
if cwd == '/':
cwd += token
else:
cwd = cwd + '/' + token
return cwd
# compare fname against pattern. Pattern may contain
# wildcards ? and *.
def fncmp(fname, pattern):
pi = 0
si = 0
while pi < len(pattern) and si < len(fname):
if (fname[si] == pattern[pi]) or (pattern[pi] == '?'):
si += 1
pi += 1
else:
if pattern[pi] == '*': # recurse
if (pi + 1) == len(pattern):
return True
while si < len(fname):
if fncmp(fname[si:], pattern[pi+1:]) == True:
return True
else:
si += 1
return False
else:
return False
if pi == len(pattern.rstrip("*")) and si == len(fname):
return True
else:
return False
def ftpserver():
DATA_PORT = 13333
ftpsocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
datasocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
ftpsocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
datasocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
ftpsocket.bind(socket.getaddrinfo("0.0.0.0", 21)[0][4])
datasocket.bind(socket.getaddrinfo("0.0.0.0", DATA_PORT)[0][4])
ftpsocket.listen(1)
datasocket.listen(1)
datasocket.settimeout(10)
msg_250_OK = '250 OK\r\n'
msg_550_fail = '550 Failed\r\n'
try:
dataclient = None
fromname = None
while True:
cl, remote_addr = ftpsocket.accept()
cl.settimeout(300)
cwd = '/'
try:
# print("FTP connection from:", remote_addr)
cl.sendall("220 Hello, this is the ESP8266.\r\n")
while True:
gc.collect()
data = cl.readline().decode("utf-8").rstrip("\r\n")
if len(data) <= 0:
print("Client disappeared")
break
command = data.split(" ")[0].upper()
payload = data[len(command):].lstrip()
path = get_absolute_path(cwd, payload)
print("Command={}, Payload={}, Path={}".format(command, payload, path))
if command == "USER":
cl.sendall("230 Logged in.\r\n")
elif command == "SYST":
cl.sendall("215 UNIX Type: L8\r\n")
elif command == "NOOP":
cl.sendall("200 OK\r\n")
elif command == "FEAT":
cl.sendall("211 no-features\r\n")
elif command == "PWD":
cl.sendall('257 "{}"\r\n'.format(cwd))
elif command == "CWD":
try:
files = uos.listdir(path)
cwd = path
cl.sendall(msg_250_OK)
except:
cl.sendall(msg_550_fail)
elif command == "CDUP":
cwd = get_absolute_path(cwd, "..")
cl.sendall(msg_250_OK)
elif command == "TYPE":
# probably should switch between binary and not
cl.sendall('200 Transfer mode set\r\n')
elif command == "SIZE":
try:
size = uos.stat(path)[6]
cl.sendall('213 {}\r\n'.format(size))
except:
cl.sendall(msg_550_fail)
elif command == "QUIT":
cl.sendall('221 Bye.\r\n')
break
elif command == "PASV":
addr = nic.ifconfig()[0]
cl.sendall('227 Entering Passive Mode ({},{},{}).\r\n'.format(
addr.replace('.',','), DATA_PORT>>8, DATA_PORT%256))
dataclient, data_addr = datasocket.accept()
# print("FTP Data connection from:", data_addr)
elif command == "LIST" or command == "NLST":
if not payload.startswith("-"):
place = path
else:
place = cwd
try:
send_list_data(place, dataclient, command == "LIST" or payload == "-l")
cl.sendall("150 Here comes the directory listing.\r\n")
cl.sendall("226 Listed.\r\n")
except:
cl.sendall(msg_550_fail)
if dataclient is not None:
dataclient.close()
dataclient = None
elif command == "RETR":
try:
send_file_data(path, dataclient)
cl.sendall("150 Opening data connection.\r\n")
cl.sendall("226 Transfer complete.\r\n")
except:
cl.sendall(msg_550_fail)
if dataclient is not None:
dataclient.close()
dataclient = None
elif command == "STOR":
try:
cl.sendall("150 Ok to send data.\r\n")
save_file_data(path, dataclient, "w")
cl.sendall("226 Transfer complete.\r\n")
except:
cl.sendall(msg_550_fail)
if dataclient is not None:
dataclient.close()
dataclient = None
elif command == "APPE":
try:
cl.sendall("150 Ok to send data.\r\n")
save_file_data(path, dataclient, "a")
cl.sendall("226 Transfer complete.\r\n")
except:
cl.sendall(msg_550_fail)
if dataclient is not None:
dataclient.close()
dataclient = None
elif command == "DELE":
try:
uos.remove(path)
cl.sendall(msg_250_OK)
except:
cl.sendall(msg_550_fail)
elif command == "RMD":
try:
uos.rmdir(path)
cl.sendall(msg_250_OK)
except:
cl.sendall(msg_550_fail)
elif command == "MKD":
try:
uos.mkdir(path)
cl.sendall(msg_250_OK)
except:
cl.sendall(msg_550_fail)
elif command == "RNFR":
fromname = path
cl.sendall("350 Rename from\r\n")
elif command == "RNTO":
if fromname is not None:
try:
uos.rename(fromname, path)
cl.sendall(msg_250_OK)
except:
cl.sendall(msg_550_fail)
else:
cl.sendall(msg_550_fail)
fromname = None
else:
cl.sendall("502 Unsupported command.\r\n")
# print("Unsupported command {} with payload {}".format(command, payload))
except Exception as err:
print(err)
finally:
cl.close()
cl = None
finally:
datasocket.close()
ftpsocket.close()
if dataclient is not None:
dataclient.close()
nic = w5x00_init()
ftpserver() #直接跑这个就成功建立服务器了
心得体会:感谢电子工程世界与得捷电子举办的活动。这次任务非常有意思,很有挑战难度。在rp2040上,使用了arduino和micropython折腾了几天终于搞定了任务,非常开心,感觉自己水平又提高啦!
|