686|2

81

帖子

1

TA的资源

一粒金砂(高级)

楼主
 

【得捷电子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折腾了几天终于搞定了任务,非常开心,感觉自己水平又提高啦!

终极任务ftpserver.py (11.62 KB, 下载次数: 2)

W5500_EVB_PICO-20240105-v1.22.1.uf2 (927.5 KB, 下载次数: 4)

fm4.zip (724.97 KB, 下载次数: 5)

 

最新回复

牛牛牛     详情 回复 发表于 2024-1-21 12:23
点赞 关注
 
 

回复
举报

6861

帖子

0

TA的资源

五彩晶圆(高级)

沙发
 

服务器获得的是UTC时间,转换为本地时间需要+8小时,,,

时间不短啊

 
 
 

回复

83

帖子

0

TA的资源

一粒金砂(中级)

板凳
 

牛牛牛

 

 
 
 

回复
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/9 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表