MicroPython 以太网实战:Pico+W5500 TCP 客户端详解

TCP 客户端实验

以下代码可以在我们提供的资料包中 elegance-devkit v1\Demo\41 ETH_TCP_Client 文件夹找到。

在该实验中,我们将会配置 w5500 和树莓派 Pico 作为 TCP 协议的客户端,向网路调试助手软件中创建的 TCP 服务器传输相关数据,示例代码如下:

Python 复制代码
# Python env   : MicroPython v1.23.0 on Wiznet W5500
# -*- coding: utf-8 -*-        
# @Time    : 2024/8/7 下午9:12   
# @Author  : 李清水            
# @File    : main.py       
# @Description : 以太网类实验,进行TCP客户端测试

# ======================================== 导入相关模块 ========================================

# 导入用于创建和管理网络连接的套接字模块
from usocket import socket
# 导入硬件相关模块
from machine import Pin,SPI
# 导入时间相关模块
import time
# 导入网络相关模块
import network

# ======================================== 全局变量 ============================================

# TCP客户端IP地址
ip = '192.168.1.20'
sn = '255.255.255.0'
gw = '192.168.1.1'
dns= '8.8.8.8'
# 用于网络连接的元组对象
netinfo=(ip, sn, gw, dns)

# TCP服务器IP地址:为使用电脑主机的IP地址
destip = '192.168.1.6'
# TCP服务器端口
destport = 8080
# 用于网络连接的元组对象
conn_info = (destip, destport)

# 全局变量,表示连接状态
conn_flag = False

# ======================================== 功能函数 ============================================

# 初始化网络接口
def w5x00_init() -> network.WIZNET5K:
    """
​    初始化 network.WIZNET5K 实例,设置静态 IP 地址并进行网络连接。

​    Args:
​        None

​    Returns:
​        network.WIZNET5K: 初始化并连接成功的 network.WIZNET5K 实例。

​    Raises:
​        None
​    """
​    ​# 声明全局变量
    global netinfo

    # 初始化SPI对象
    spi = SPI(0, 2_000_000, mosi=Pin(19), miso=Pin(16), sck=Pin(18))
    # 实例化network.WIZNET5K类,传入使用的片选引脚CS和复位引脚RST
    nic = network.WIZNET5K(spi, Pin(17), Pin(20))
    # 激活网络接口
    nic.active(True)
    # 设置静态IP地址:主机地址、子网掩码、网关地址和DNS服务器地址
    nic.ifconfig(netinfo)

    # 若是没有连接网络,则循环执行
    while not nic.isconnected():
        time.sleep(1)
        # 输出寄存器信息
        print(nic.regs())

    # 打印设置的IP地址
    print('ip :', nic.ifconfig()[0])
    print('sn :', nic.ifconfig()[1])
    print('gw :', nic.ifconfig()[2])
    print('dns:', nic.ifconfig()[3])

    # 返回network.WIZNET5K实例
    return nic

def client_loop() -> None:
    """
​    客户端循环,不断接收服务端发送的数据并回传。

​    该函数会尝试连接到指定的服务器地址和端口,并在连接成功后接收服务器发送的数据。
​    如果接收到数据,会将数据回传给服务器。如果连接断开,会尝试重新连接。

​    Args:
​        None

​    Returns:
​        None

​    Raises:
​        None
​    """

​    ​# 声明全局变量
    global conn_flag

    # 创建一个套接字对象
    s = None

    # 循环接收发送
    while (True):
        # 如果当前未连接
        if not conn_flag:
            # 如果socket存在,先关闭它
            if s:
                try:
                    s.close()
                except:
                    pass

            # 延时100ms再重新创建socket
            time.sleep_ms(100)

            # 创建新的套接字对象
            try:
                s = socket()
                print("Created new socket")
            except:
                print("Failed to create socket")
                # 创建socket失败,继续循环
                continue

            # 尝试连接到指定的IP地址和端口
            try:
                s.connect(conn_info)
                conn_flag = True
                print("Loopback client Connect!")
            except:
                print('connect error')
                conn_flag = False

        # 如果已经连接
        elif conn_flag and s:
            try:
                # 尝试接收最多2048个字节的数据
                data = s.recv(2048)
                # 检查是否接收到数据
                if data:
                    # 将接收到的数据解码为字符串
                    data_str = data.decode('utf-8')
                    print(f'recv from {conn_info[0]}:{conn_info[1]}: {data_str}')
                    # 将数据回传
                    s.send(data)
                else:
                    # 接收到空数据表示连接已关闭
                    print('Connection closed by server')
                    conn_flag = False
            except:
                print('disconnect')
                conn_flag = False

# ======================================== 自定义类 ============================================

# ======================================== 初始化配置 ==========================================

# 延时3s,等待器件上电
time.sleep(3)
# 打印调试信息
print("FreakStudio : Using W5x00 Ethernet to do TCP Client Test")

# 初始化w5500模块
nic = w5x00_init()

# ========================================  主程序  ===========================================

# 运行客户端循环
client_loop()

这里,我们首先进行 TCP 客户端和服务器端的 IP 地址及网络配置,需要注意的是,TCP服务器端 ​**IP 地址需要设置为电脑主机的地址:通常情况下,嵌入式设备(如 MicroPython 开发板)作为客户端,会连接到运行在电脑上的 ​ TCP ​ 服务器。因此,服务器的 ​ IP ​ 地址应该是电脑主机的 ​ IP​ 地址,这样才能与实际的网络环境对应**。

然后我们进行 W5500 模块的初始化,在客户端循环 client_loop() 函数中,我们进行如下操作:

  • 初始化套接字变量并进入无限循环;
  • 若当前未连接(conn_flagFalse):
    • 如果已有套接字则关闭它,延时 100ms 后创建新的套接字对象;
    • 尝试连接服务器:
      • 连接成功则将 conn_flag 设为 True 并输出连接信息
      • 连接失败则输出错误信息并保持 conn_flagFalse
  • 若已连接(conn_flagTrue 且套接字有效):
    • 尝试接收数据,若接收到数据则解码为字符串并输出,同时将数据回传;
    • 若接收到空数据(表示服务器关闭连接)或出现异常,则输出相应信息并将 conn_flag 设为 False

然后我们打开 NetAssist 软件,选择协议类型为 TCP Server,配置本地主机地址为 198.168.1.6 ,主机地址可通过在终端中输入 ipconfig 命令查询到,本地主机端口设置与代码中一致,为 8080,其余选项均为默认,点击"​**打开**​"按钮:

此时,软件左下角显示"​**就绪**​"信息:

烧录代码,连接远程终端:

可以看到,TCP 客户端和服务器均已连接完成。

接下来,我们通过服务器向客户端发送数据:

可以看到,客户端接收的数据又回传到服务器。

相关推荐
Freak嵌入式1 小时前
MicroPython W5500 以太网实验|ping 测试:原理 + 实操全解析
嵌入式
Freak嵌入式5 小时前
USB-CDC 通信实战应用:树莓派 Pico 虚拟串口 + select+MicroPython 全拆解
嵌入式
Freak嵌入式1 天前
PIO 入门:手把手实现板载 LED 闪烁,原理与代码全解析
嵌入式
Freak嵌入式1 天前
一文搞懂树莓派 Pico 任务调度器:基于定时器的 MicroPython 多任务实现
嵌入式
花 满 楼2 天前
国芯科技CCFC3008PCS BIST (内建自测试) 分析总结
mcu·嵌入式·bist
虎王物联2 天前
ESP32 FreeRTOS多任务优先级翻转与互斥量保护实战
物联网·嵌入式·esp32·freertos
与你4033 天前
CLion 中为什么要重写 _write,而不是 fputc?
嵌入式
Freak嵌入式3 天前
MicroPython 开发避坑:用 Signal 类解决不同电路的电平兼容问题
嵌入式
智码看视界4 天前
Edge AI 全栈1:ESP32 传感器采集到云端大模型推理的完整链路
人工智能·物联网·嵌入式·esp32·aiot·全栈开发·edgeai