1360|5

57

帖子

4

TA的资源

一粒金砂(中级)

楼主
 

得捷电子Follow me第4期】成果展示帖 [复制链接]

 

前言

作为一个多次参加活动的老鸟,感谢DigiKey得捷和电子工程世界EEWorld 举办的Follow me活动,这么多电子类网站活动,感觉还是Follow me最实在了!

任务说明

本期指定任务说明:活动参与者需要搭配必购板子W5500-EVB-Pico,完成下方任务(全部为必做任务)。

入门任务:开发环境搭建,BLINK,驱动液晶显示器进行显示(没有则串口HelloWorld)

搭配器件: W5500-EVB-Pico、 Adafruit Sharp Memory Display Breakout

 

基础任务一:完成主控板W5500初始化(静态IP配置),并能使用局域网电脑ping通,同时W5500可以ping通互联网站点;通过抓包软件(Wireshark、Sniffer等)抓取本地PC的ping报文,展示并分析。

搭配器件: W5500-EVB-Pico、 Adafruit Sharp Memory Display Breakout

 

基础任务二:主控板建立TCPIP或UDP服务器,局域网PC使用TCPIP或UDP客户端进行连接并发送数据,主控板接收到数据后,送液晶屏显示(没有则通过串口打印显示);通过抓包软件抓取交互报文,展示并分析。(TCP和UDP二选一,或者全都操作)

搭配器件: W5500-EVB-Pico、 Adafruit Sharp Memory Display Breakout

 

进阶任务:从NTP服务器(注意数据交互格式的解析)同步时间,获取时间送显示屏(串口)显示。

搭配器件: W5500-EVB-Pico、 Adafruit Sharp Memory Display Breakout

 

终极任务(二选一)

■  终极任务一:访问 https://www.digikey.cn/zh/resources/api-solutions,以了解得捷(DigiKey)数字化解决方案及其API操作,设计一款DigiKey电子元器件价格及库存监视器,能实时同步并显示指定,电子元器件的价格、库存等信息。

■  终极任务二:使用外部存储器,组建简易FTP文件服务器,并能正常上传下载文件。

搭配器件: W5500-EVB-Pico、 Adafruit Sharp Memory Display Breakout

开箱展示

本次购买的器件除了必须的W5500-EVB-Pico外,还额外买了Adafruit的EINK FEATHER FRIEND 电纸书驱动板和Pervasive Displays的4.2" EPD彩色电纸书屏。

 

任务成果展示

演示视频合集:https://training.eeworld.com.cn/video/39556

 

任务代码包:>>点击下载  

 

入门任务:


开发环境搭建,BLINK,驱动液晶显示器进行显示(没有则串口HelloWorld)

一、硬件

  • 实物照片
  • 技术参数

 

  • 外观尺寸

 

  • 原理图

W5500-EVB-Pico_SCH_V100.pdf (870.76 KB, 下载次数: 0)

 

  • 引脚定义

 

二、开发环境搭建

1、固件下载

到官网MicroPython官网下载开发板对应的固件,链接如下:

https://micropython.org/download/W5500_EVB_PICO/

 

毫无疑问下载最新版本V1.22.1

2、固件烧录

按住板子上BOOTSEL按键(靠近usb接口那个)别松手,用micro-usb数据线连接到电脑上,我的电脑弹出下面移动磁盘

 

把刚才下载的固件拖进去(复制粘贴也行)

 

拷贝完成后pico会自动重启,升级就完成了。

 

3、IDE下载安装

这里开发环境搭建与Follow me第一期的一样,参照我之前的帖子即可,这里用的是Thonny

https://bbs.eeworld.com.cn/thread-1244983-1-1.html

IDE下部shell窗口出现下面截图就证明你pico和IDE建立了通讯

 

三、软件代码
from machine import Pin
import time

led = Pin(25,Pin.OUT)

def main():
    while True:
        time.sleep(1)
        led.value(1)
        time.sleep(1)
        led.value(0)
        print('HelloWorld!')
if __name__ == "__main__":
    main()

四、视频演示

FM4入门

 

基础任务一:


完成主控板W5500初始化(静态IP配置),并能使用局域网电脑ping通,同时W5500可以ping通互联网站点;通过抓包软件(Wireshark、Sniffer等)抓取本地PC的ping报文,展示并分析。

一、工具下载准备

  • Wireshark是啥

        wireshark是非常流行的网络封包分析软件,简称小鲨鱼,功能十分强大。可以截取各种网络封包,显示网络封包的详细信息。

        wireshark是开源软件,可以放心使用。可以运行在Windows和Mac OS上。

  • 常见应用场景

        网管使用wireshark来检查网络问题

        软件测试工程师使用wireshark抓包,来分析软件

        从事socket编程的工程师会用wireshark来调试

        运维人员用于日常工作,应急响应等等

        跟网络相关的东西,都可能会用到wireshark

  • 下载安装

        https://www.wireshark.org/download.html

 

目前最新版本有如上可以下载,选择自己对应的下载好了,具体安装过程不再赘述,想简单点下载Portable版本,只需要选择解压目录就可以实现自解压。

二、软件代码

这里为了省事,直接从官网下载例程,简单修改下就可以驱动起来W5500

链接已隐藏,如需查看请登录或者注册

from usocket import socket
from machine import Pin,SPI
import network
import time

led = Pin(25, Pin.OUT)

#W5x00 chip init
def w5x00_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)
    nic.ifconfig(('192.168.199.200','255.255.255.0','192.168.199.1','8.8.8.8'))
    while not nic.isconnected():
        time.sleep(1)
        print(nic.regs())
    print(nic.ifconfig())
        
def main():
    w5x00_init()

    while True:
        led.value(1)
        time.sleep(1)
        led.value(0)
        time.sleep(1)

if __name__ == "__main__":
    main()

 

 

需要根据自己网络实际情况,修改下上面静态地址信息。简单点方法是先查下自己电脑的ip信息,参照修改下就行了。

桌面任务栏搜索那里输入cmd,然后点左边命令提示符

 

在打开的窗口里输入ipconfig,并回车

 

根据上面的信息,我只需要把静态地址那里ip地址修改成192.168.199.200即可,家里网络设备不多,基本不会冲突。

Thonny里下载运行,shell可以显示结果,这里已经联网成功。

 

继续使用cmd里ping一下开发板试试,看看网络是否能联通。

 

启动Wireshark,如果你打开之后类似我这个界面,看不到你自己的网卡,请参照后面的教程。

 

 

按上面教程操作后顺利出线网卡接口

 

双击以太网位置,软件图标编程绿色鲨鱼鳍就代表开始捕获消息了,为了避免太多信息干扰,需要设置下过滤条件,只查看开发板相关信息就行。为避免其他无用的数据包影响分析,可以通过在过滤栏设置过滤条件进行数据包列表过滤,获取结果如下。说明:ip.addr == 183.232.231.172 and icmp 表示只显示ICPM协议且主机IP为192.168.199.200的数据包。说明:协议名称icmp要小写。

 

选中一条消息,左下角可以看到数据包详情

 

TCP包的具体内容

从下图可以看到wireshark捕获到的TCP包中的每个字段。

 

在数据链路层可以看到,本机网卡mac地址,目标是路由器的mac地址

 

 

基础任务二:


主控板建立TCPIP或UDP服务器,局域网PC使用TCPIP或UDP客户端进行连接并发送数据,主控板接收到数据后,送液晶屏显示(没有则通过串口打印显示);通过抓包软件抓取交互报文,展示并分析。(TCP和UDP二选一,或者全都操作)

一、工具准备

调试比较方便的是用网络助手,这个软件使用的挺多,我直接上传上来。

NetAssist.exe (634.49 KB, 下载次数: 1)

 

二、软件代码

参考Wiznet官网的示例进行修改,具体下载链接如下:

链接已隐藏,如需查看请登录或者注册

主要修改的是IP地址部分,需要根据自己网络情况进行修改,这里配置的开发板IP地址为192.168.199.200,端口5000,这里开发板作为客户端。

from usocket import socket
from machine import Pin,SPI
import network
import time

#W5x00 chip init
def w5x00_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)
    
    #None DHCP
    nic.ifconfig(('192.168.199.200','255.255.255.0','192.168.199.1','8.8.8.8'))
    
    #DHCP
    #nic.ifconfig('dhcp')
    
    print('IP address :', nic.ifconfig())
    while not nic.isconnected():
        time.sleep(1)
        print(nic.regs())
    
def server_loop(): 
    s = socket()
    s.bind(('192.168.199.200', 5000)) #Source IP Address
    s.listen(5)
    
    print("TEST server")
    conn, addr = s.accept()
    print("Connect to:", conn, "address:", addr) 
    print("Loopback server Open!")
    while True:
        data = conn.recv(2048)
        print(data.decode('utf-8'))
        if data != 'NULL':
            conn.send(data)

def client_loop():
    s = socket()
    s.connect(('192.168.199.192', 5000)) #Destination IP Address
    
    print("Loopback client Connect!")
    while True:
        data = s.recv(2048)
        print(data.decode('utf-8'))
        if data != 'NULL' :
            s.send(data)
        
def main():
    w5x00_init()
    
###TCP SERVER###
    #server_loop()

###TCP CLIENT###
    client_loop()

if __name__ == "__main__":
    main()

三、演示视频

基础任务二

 

进阶任务:


从NTP服务器(注意数据交互格式的解析)同步时间,获取时间送显示屏(串口)显示。

一、NTP介绍

1、什么是NTP

    网络时间协议NTP(Network Time Protocol)是TCP/IP协议族里面的一个应用层协议,用来使客户端和服务器之间进行时钟同步,提供高精准度的时间校正。NTP服务器从权威时钟源(例如原子钟、GPS)接收精确的协调世界时UTC,客户端再从服务器请求和接收时间。
    NTP基于UDP报文进行传输,使用的UDP端口号为123。

2、名词介绍

  • NTP(Network Time Protocol),互联网时间协议。
  • UTC(Coordinated Universal Time),协调通用时间。根据原子振荡周期所计算的物理时钟,这种计算方式对于时间的计算误差时很小的。
  • GMT(Greenwich Mean Time),表示的是格林尼治时间,是根据地球的自转周期计算的标准时间,由于各种不稳定因素的影响,计时不是很理想。
  • 软件时钟:表示的是操作系统从1970/01/01开始计算的秒数。
  • 硬件时钟:主机硬件上面的时钟,主要是BIOS内部时间的记录了。

3、协议原理

NTP是为实现高精确度的时间同步,而设计的网络时钟同步协议,基于IP和UDP,相关标准在RFC1305中有定义。

NTP客户端按照规定的时间间隔内向时钟源发出探测报文,一次发出8份报文,报文中记录了进行时间同步需要的所有信息。如果当前客户端和时钟源之间的时差和同步距离在容忍之内,则进行平滑同步(不允许时间跳变),若超出容忍值,则认为该时钟源不可信,返回400标识,不同步。

4、协议发展历史

NTP是由美国Delaware大学David L .Mills教授设计的,是最早用于网络中时钟同步的标准之一。NTP是从时间协议和ICMP时间戳报文演变而来,NTP的版本演进如下所示。

 

 

5、应用场景

  • 网络管理:从不同网络设备采集来的日志信息进行分析时,需要以时间作为参照依据。如果不同设备上的系统时间不一致,会因先后顺序等问题给故障定位带来障碍。
  • 计费系统:计费业务对于时间尤其敏感,要求所有设备的时间保持一致,否则会引起计费不准确,导致用户质疑、投诉等。
  • 协同处理:多个系统协同处理同一个复杂事件,为保证正确的执行顺序,多个系统必须参考同一时钟。
  • 系统时间:某些应用或服务需要准确的时间来标记用户登录、交易等操作信息,确保可追溯记录。

6、国内NTP服务器源

名称 公共NTP服务器地址
国家授时中心 NTP 服务器
NTSC NTP Server
ntp.ntsc.ac.cn
中国 NTP 快速授时服务
NTP ORG CN
cn.ntp.org.cn
中国教育网专用 edu.ntp.org.cn
阿里云公共 NTP 服务器
Aliyun NTP Server
ntp1.aliyun.com
ntp2.aliyun.com
ntp3.aliyun.com
ntp4.aliyun.com
ntp5.aliyun.com
ntp6.aliyun.com
ntp7.aliyun.com
腾讯公共 NTP 服务器
Tencent Cloud NTP Server
ntp.tencent.com
ntp1.tencent.com
ntp2.tencent.com
ntp3.tencent.com
ntp4.tencent.com
ntp5.tencent.com
上海交大NTP 服务器 ntp.sjtu.edu.cn
东北大学NTP服务器 ntp.neu.edu.cn
北京邮电大学NTP服务器 ntp.bupt.edu.cn
上海大学NTP服务器 ntp.shu.edu.cn
清华大学NTP服务器 ntp.tuna.tsinghua.edu.cn
国际 NTP 快速授时服务
中国片区
cn.pool.ntp.org
0.cn.pool.ntp.org
1.cn.pool.ntp.org
2.cn.pool.ntp.org
3.cn.pool.ntp.org

二、软件代码

软件可以直接从前两个任务里进行修改,初始化联网部分不需要动,只需要增加访问NTP服务器获取时间的部分。

from usocket import socket
from machine import Pin,SPI,RTC
import network
import time
import ntptime

led = Pin(25, Pin.OUT)

#W5x00 chip init
def w5x00_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)
    nic.ifconfig(('192.168.199.200','255.255.255.0','192.168.199.1','8.8.8.8'))
    while not nic.isconnected():
        time.sleep(1)
        #print(nic.regs())
    print('IP address:', nic.ifconfig())
#显示时间函数
def showtime():
    rtc = RTC()
    now = time.time()
    now += 8 * 3600
    t = time.localtime(now)
    print(f'{t[0]}-{t[1]:02d}-{t[2]:02d} {t[3]:02d}:{t[4]:02d}:{t[5]:02d}')
    
def main():
    w5x00_init()
    
    #通过NTP服务器校时
    print('开始NTP校时..')
    ntptime.host = 'ntp.tencent.com'
    ntptime.settime()
    print(f'校准后系统时间:')
    showtime()
    
    while True:
        led.value(1)
        time.sleep(1)
        led.value(0)
        showtime()
        time.sleep(1)

if __name__ == "__main__":
    main()

三、视频演示

进阶任务

 

■  终极任务二:


使用外部存储器,组建简易FTP文件服务器,并能正常上传下载文件。

一、硬件

接线方式

 

二、软件代码

1、测试SD卡

这里使用micropython官网的sd支持类,下载链接如下

链接已隐藏,如需查看请登录或者注册

下载到电脑后,在Thoony内选中类文件右键上传到开发板内。

 

遇到的问题:sd卡始终报错,真是无语了,调换cs线也不行,但是用arduino就没事

    这里把我的sd卡测试代码传上来。

RP2040_CardInfo.7z (2.13 KB, 下载次数: 0)

2、实现FTP服务

ftp参考了网上几个例程,结果统统都报错,真是无语了,这里把只有第18行根目录报错的放上来

 

import gc
import uos
import time
import socket
import network
from time import localtime
from machine import Pin, SPI
from micropython import const


_LED_PIN = const(25)  # 绿色 LED 引脚
_SPI_SPEED = const(2_000_000)  # SPI 速率
_MOSI_PIN = const(19)  # SPI MOSI 引脚
_MISO_PIN = const(16)  # SPI MISO 引脚
_SCK_PIN = const(18)  # SPI SCK 引脚
_CS_PIN = const(17)  # SPI CS 引脚
_RST_PIN = const(20)  # SPI RESET 引脚
FTP_ROOT_PATH = const("/")  # FTP 根目录

month_name = [
    "",
    "Jan",
    "Feb",
    "Mar",
    "Apr",
    "May",
    "Jun",
    "Jul",
    "Aug",
    "Sep",
    "Oct",
    "Nov",
    "Dec",
]

# SPI 定义
spi = SPI(0, _SPI_SPEED, mosi=Pin(_MOSI_PIN), miso=Pin(_MISO_PIN), sck=Pin(_SCK_PIN))
nic = None

""" W5500 初始化 """


def w5x00_init():
    global nic
    # 网口初始化
    nic = network.WIZNET5K(spi, Pin(_CS_PIN), Pin(_RST_PIN))  # spi,cs,reset pin
    nic.active(True)
    # 配置网络
    # If you use the Dynamic IP(DHCP), you must use the "nic.ifconfig('dhcp')".
    nic.ifconfig("dhcp")
    # If you use the Static IP, you must use the  "nic.ifconfig("IP","subnet","Gateway","DNS")".
    # nic.ifconfig(('192.168.0.106','255.255.255.0','192.168.0.1','114.114.114.114'))

    while not nic.isconnected():
        time.sleep(1)
        print(nic.regs())
    print("IP地址:  %s" % nic.ifconfig()[0])
    print("子网掩码: %s" % nic.ifconfig()[1])
    print("网关:    %s" % nic.ifconfig()[2])
    print("DNS:     %s" % nic.ifconfig()[3])


""" 响应文件列表请求 """


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):
    try:
        with open(path, "rb") as file:
            chunk = file.read(512)
            print("chunk 0: ", len(chunk))
            while len(chunk) > 0:
                print("chunk: ", len(chunk))
                dataclient.sendall(chunk)
                chunk = file.read(512)
    except Exception as err:
        print("error: ", err.args, err.value, err.errno)


""" 保存文件上传数据 """


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


""" 文件名比较 """


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


""" 启动FTP服务 """


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)

    print("FTP服务启动成功!监听端口:21")

    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 = FTP_ROOT_PATH
            try:
                print("新的FTP连接来自: %s:%s" % (remote_addr[0], remote_addr[1]))
                cl.sendall("220 Welcome! This is the W5500_EVB_PICO!\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("命令={}, 参数={}, 路径={}".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数据连接来自: %s:%s" % (data_addr[0], data_addr[1]))
                    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, "wb")
                            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()


if __name__ == "__main__":
    print("run in main")
    w5x00_init()  # 初始化网络
    ftpserver()  # 运行 FTP Server


 

补充任务:


此处不是官方规定必须的任务,我这里主要是买了电子纸E-paper显示屏,所以得想办法驱动起来。

一、硬件

1、资料查询

这里我购买的是Pervasive Displays的4.2寸三色屏幕,这里到官网找了下资料,这点必须好评,资料很齐全。

https://www.pervasivedisplays.com/product/4-2-e-ink-displays/

 

截图这里可以看到,此款屏幕有四款,根据E2417后面的字母进行区分,C为单色屏,P为单色支持快速刷新,K为单色宽温支持快速刷新,J为三色液晶屏。
买了之后微信群里乔帮主就提醒过,三色屏幕刷新很慢,这点在官方也有提到3-colors pigments inside.Taking longer time to complete a refresh.
 

资料里显示,此款屏幕是内置驱动芯片的iTC方式,下面是官网对IC内置外置的区别。

 

2、资料下载

此处是官网收集到的资料手册:

Datesheet 1P251-00_03_E2417CS0D1_20211126.pdf (2.32 MB, 下载次数: 1)
驱动文档 ApplicationNote_Small_Size_Mono_v02_220606.pdf (596.8 KB, 下载次数: 1)

3、官方驱动EPD开发套件EPD Extension Kit Gen 3 (EXT3-1)

也就是乔帮主买的那款,把他的帖子连接贴上来,供大家参考https://bbs.eeworld.com.cn/thread-1268978-1-1.html

4、硬件连线
 

二、开发环境搭建

1、准备开发环境

此处因为屏幕官网提供了Arduino环境的库,所以切换使用Arduino环境。

arduino的安装这里不再赘述,官网下载安装即可。

安装完成后需要添加板子,首先是增加板子管理器地址。文件→首选项→其他开发板管理器地址右侧  按钮,把下面链接粘贴进去

链接已隐藏,如需查看请登录或者注册

 

 

 

等待右下角更新开发板管理器信息:

  开发板管理器里可以搜索到pico了

 

这里受限于国内网络,可能下载非常慢,可以参考下面例程通过离线方式进行安装,速度快很多。(亲身验证)

接下来安装屏幕的库,这里是直接用的前面提到的开发套件的库文件

 

 

最新回复

开发板的主要用途是对各个功能模块的验证,对于应用级的训练比较少     详情 回复 发表于 2024-2-27 08:39
点赞 关注
 
 

回复
举报

6471

帖子

9

TA的资源

版主

沙发
 

Follow me是真正的实践教程,这类活动其实可以好好多办点  

点评

非常感谢Digi-key和EE举办的这个活动,对于新手来说非常棒,真正的能从自己动手中学到东西。 平时开发板那种买来都是现成代码,单纯编译跑一下没任何意义,只有在自己钻研,遇到问题排除问题过程中才能更快成长。  详情 回复 发表于 2024-2-26 21:07
个人签名

在爱好的道路上不断前进,在生活的迷雾中播撒光引

 
 
 

回复

57

帖子

4

TA的资源

一粒金砂(中级)

板凳
 

补充下终极任务二今天研究情况。

首先非常感谢乔帮主群里的指点,最后发现我无法驱动成功sd卡的原因有三个:

  1. sdcard类有问题,之前是从micropython下载的(也是坛友推荐的),一直没怀疑它,我用了乔帮主分享的立马就能初始化成功;
  2. sd卡兼容性有问题,之前用的2G小容量的,在arduino下访问没问题,但是用micropython就不行了,然后换了张新的32G的就没事;
  3. 手头没杜邦线,用的4Pin端子连接线,接头上了点焊锡后查到排母里,貌似有点接触不良;

 

这里我把乔帮主分享的文件传上来,也给大家做参考。(大家根据自己接线方式修改Pin定义)

sdCardDemo.py (1.74 KB, 下载次数: 0) sdcard.py (7.57 KB, 下载次数: 0)

一、SD卡驱动

软件代码

1、测试SD卡

# Filename: tfcard_test.py
import uos  # os/uos
import machine
import sdcard
from machine import SPI, Pin

spi = SPI(1, sck=Pin(10), mosi=Pin(11), miso=Pin(12))
cs = Pin(13)
sd = sdcard.SDCard(spi,cs)

# 挂载文件到sd
uos.mount(sd,"/sd")
# 列出MicroSD/TF卡中的目录文件
print(uos.listdir('/sd'))

# 写文件测试
f = open('/sd/test.txt','w',encoding='utf-8')
f.write('MicroSD/TF存储卡访问测试!')
f.close()

# 读文件测试
f = open('/sd/test.txt','r')
print(f.read())
f.close()

2、运行结果:

 

二、FTP服务器搭建

1、软件代码

端口及参数定义

import gc
import uos
import time
import socket
import network
from time import localtime
from machine import Pin, SPI
from micropython import const

/'初始化引脚'/
_LED_PIN = const(25)  # LED 指示灯引脚
_SPI_SPEED = const(2_000_000)  # SPI 速率
_MOSI_PIN = const(19)  # SPI MOSI 引脚
_MISO_PIN = const(16)  # SPI MISO 引脚
_SCK_PIN = const(18)  # SPI SCK 引脚
_CS_PIN = const(17)  # SPI CS 引脚
_RST_PIN = const(20)  # SPI RESET 引脚

FTP_ROOT_PATH = const("/")  # FTP 根目录

month_name = ["","Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec",
]

# SPI 定义
spi = SPI(0, _SPI_SPEED, mosi=Pin(_MOSI_PIN), miso=Pin(_MISO_PIN), sck=Pin(_SCK_PIN))
nic = None

W5500初始化

""" W5500 初始化 """


def w5x00_init():
    global nic
    # 网口初始化
    nic = network.WIZNET5K(spi, Pin(_CS_PIN), Pin(_RST_PIN))  # spi,cs,reset pin
    nic.active(True)
    # 配置网络
    # If you use the Dynamic IP(DHCP), you must use the "nic.ifconfig('dhcp')".
    nic.ifconfig("dhcp")
    # If you use the Static IP, you must use the  "nic.ifconfig("IP","subnet","Gateway","DNS")".
    # nic.ifconfig(('192.168.0.106','255.255.255.0','192.168.0.1','114.114.114.114'))

    while not nic.isconnected():
        time.sleep(1)
        print(nic.regs())
    print("IP地址:  %s" % nic.ifconfig()[0])
    print("子网掩码: %s" % nic.ifconfig()[1])
    print("网关:    %s" % nic.ifconfig()[2])
    print("DNS:     %s" % nic.ifconfig()[3])

文件列表请求响应函数

'/ 响应文件列表请求 /'


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):
    try:
        with open(path, "rb") as file:
            chunk = file.read(512)
            print("chunk 0: ", len(chunk))
            while len(chunk) > 0:
                print("chunk: ", len(chunk))
                dataclient.sendall(chunk)
                chunk = file.read(512)
    except Exception as err:
        print("error: ", err.args, err.value, err.errno)

文件数据保存

""" 保存文件上传数据 """


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

文件名比较函数

""" 文件名比较 """


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

FTP服务启动


""" 启动FTP服务 """


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)

    print("FTP服务启动成功!监听端口:21")

    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 = FTP_ROOT_PATH
            try:
                print("新的FTP连接来自: %s:%s" % (remote_addr[0], remote_addr[1]))
                cl.sendall("220 Welcome! This is the W5500_EVB_PICO!\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("命令={}, 参数={}, 路径={}".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数据连接来自: %s:%s" % (data_addr[0], data_addr[1]))
                    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, "wb")
                            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()


if __name__ == "__main__":
    print("run in main")
    w5x00_init()  # 初始化网络
    ftpserver()  # 运行 FTP Server

三、视频演示

进阶任务

四、完整代码

import gc
import uos
import time
import socket
import network
from time import localtime
from machine import Pin, SPI
from micropython import const
import sdcard

"""初始化引脚"""
_LED_PIN = const(25)  # LED 指示灯引脚
_SPI_SPEED = const(2_000_000)  # SPI 速率
_MOSI_PIN = const(19)  # SPI MOSI 引脚
_MISO_PIN = const(16)  # SPI MISO 引脚
_SCK_PIN = const(18)  # SPI SCK 引脚
_CS_PIN = const(17)  # SPI CS 引脚
_RST_PIN = const(20)  # SPI RESET 引脚

FTP_ROOT_PATH = const("/sd")  # FTP 根目录

month_name = ["","Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec",
]

# SPI 定义
spi = SPI(0, _SPI_SPEED, mosi=Pin(_MOSI_PIN), miso=Pin(_MISO_PIN), sck=Pin(_SCK_PIN))
nic = None


spi1 = SPI(1, sck=Pin(10), mosi=Pin(11), miso=Pin(12))
cs = Pin(13)
sd = sdcard.SDCard(spi1,cs)

# 挂载文件到sd
uos.mount(sd,"/sd")
# 列出MicroSD/TF卡中的目录文件
print(uos.listdir('/sd'))

# 写文件测试
f = open('/sd/test.txt','w',encoding='utf-8')
f.write('MicroSD/TF存储卡访问测试!')
f.close()

# 读文件测试
f = open('/sd/test.txt','r')
print(f.read())
f.close()

""" W5500 初始化 """


def w5x00_init():
    global nic
    # 网口初始化
    nic = network.WIZNET5K(spi, Pin(_CS_PIN), Pin(_RST_PIN))  # spi,cs,reset pin
    nic.active(True)
    # 配置网络
    # If you use the Dynamic IP(DHCP), you must use the "nic.ifconfig('dhcp')".
    nic.ifconfig("dhcp")
    # If you use the Static IP, you must use the  "nic.ifconfig("IP","subnet","Gateway","DNS")".
    # nic.ifconfig(('192.168.0.106','255.255.255.0','192.168.0.1','114.114.114.114'))

    while not nic.isconnected():
        time.sleep(1)
        print(nic.regs())
    print("IP地址:  %s" % nic.ifconfig()[0])
    print("子网掩码: %s" % nic.ifconfig()[1])
    print("网关:    %s" % nic.ifconfig()[2])
    print("DNS:     %s" % nic.ifconfig()[3])


'/ 响应文件列表请求 /'


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):
    try:
        with open(path, "rb") as file:
            chunk = file.read(512)
            print("chunk 0: ", len(chunk))
            while len(chunk) > 0:
                print("chunk: ", len(chunk))
                dataclient.sendall(chunk)
                chunk = file.read(512)
    except Exception as err:
        print("error: ", err.args, err.value, err.errno)


""" 保存文件上传数据 """


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


""" 文件名比较 """


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


""" 启动FTP服务 """


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)

    print("FTP服务启动成功!监听端口:21")

    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 = FTP_ROOT_PATH
            try:
                print("新的FTP连接来自: %s:%s" % (remote_addr[0], remote_addr[1]))
                cl.sendall("220 Welcome! This is the W5500_EVB_PICO!\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("命令={}, 参数={}, 路径={}".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数据连接来自: %s:%s" % (data_addr[0], data_addr[1]))
                    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, "wb")
                            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()


if __name__ == "__main__":
    print("run in main")
    w5x00_init()  # 初始化网络
    ftpserver()  # 运行 FTP Server




 

 
 
 

回复

57

帖子

4

TA的资源

一粒金砂(中级)

4
 
秦天qintian0303 发表于 2024-2-26 09:16 Follow me是真正的实践教程,这类活动其实可以好好多办点  

非常感谢Digi-key和EE举办的这个活动,对于新手来说非常棒,真正的能从自己动手中学到东西。

平时开发板那种买来都是现成代码,单纯编译跑一下没任何意义,只有在自己钻研,遇到问题排除问题过程中才能更快成长。

点评

开发板的主要用途是对各个功能模块的验证,对于应用级的训练比较少    详情 回复 发表于 2024-2-27 08:39
 
 
 

回复

6471

帖子

9

TA的资源

版主

5
 
爱吃鱼的加菲猫 发表于 2024-2-26 21:07 非常感谢Digi-key和EE举办的这个活动,对于新手来说非常棒,真正的能从自己动手中学到东西。 平时开发 ...

开发板的主要用途是对各个功能模块的验证,对于应用级的训练比较少  

个人签名

在爱好的道路上不断前进,在生活的迷雾中播撒光引

 
 
 

回复

57

帖子

4

TA的资源

一粒金砂(中级)

6
 

任务总结视频:

(PS:请原谅视频里我穿着睡衣,这活真的是忙活了一晚上才搞定,搞技术的玩视频剪辑真的是不咋溜)

任务总结视频

 

 
 
 

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

随便看看
查找数据手册?

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
快速回复 返回顶部 返回列表