1451|1

19

帖子

2

TA的资源

一粒金砂(中级)

楼主
 

【得捷Follow me第4期】+小白手把手带你学习rp2040+w5500(所有任务) [复制链接]

 

总结视频:

【得捷Follow me第4期】+小白手把手带你学习rp2040+w5500(所有任务)

 

可编译下载的代码:

download.eeworld.com.cn/detail/lihuahua/631259

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

0.1 开发环境搭建(在ubuntu环境下使用clion进行C开发)

1、更新软件包列表,不进行实际升级操作:

book@100ask:~$ sudo apt-get update

2、安装git工具:                 

book@100ask:~$ sudo apt-get install git

3、安装python:

book@100ask:~$ sudo apt-get install python-tk python3-tk

4、拉取树莓派sdk文件:

book@100ask:~$ git clone

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

5、进入pico-setup路径,并修改文件“pico-setup.sh”,需要注释一些代码:

book@100ask:~/rp2040/pico-setup$ vi pico-setup.sh

 

6、安装“pico_setup.sh “:

book@100ask:~/rp2040/pico-setup$ ./pico_setup.sh

7、安装clion-IDE:

book@100ask:~/rp2040/pico-setup$ sudo snap install clion –classic

8、拉取树莓派工程生成软件包:

book@100ask:~/rp2040/pico-setup$ cd ..

book@100ask:~/rp2040$ git clone

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

9、重新打开终端,修改sdk的路径:

book@100ask:~/rp2040/pico-setup$ ls

pico  pico-project-generator  pico_setup.sh

book@100ask:~/rp2040/pico-setup$ pwd

/home/book/rp2040/pico-setup

book@100ask:~/rp2040/pico-setup$ echo "export PICO_SDK_PATH=/home/book/rp2040/pico-setup" >> .bashrc

10、安装树莓派工程生成软件:

book@100ask:~/rp2040/pico-setup$ cd pico-project-generator

11、打开树莓派工程生成软件:

book@100ask:~/rp2040/pico-setup/pico-project-generator$ ./pico_project.py --gui

 

12、通过clion打开刚刚生成的工程:

12.1将工程路径中的头文件所在文件夹告诉编译器:

 

12.2将工程路径中的源文件告诉cmake:被编译的c文件左上角有蓝色方块标记

 

12.3工程编译:

 

13、程序烧录

按下BOOT和RESET,然板子复位

松开RESET(BOOT仍按下),然板子进入BOOT

等电脑上弹出RPI-RP2的盘符(文件夹)后,可松开BOOT

 

然后把编译后的uf2固件拖拽到这个盘中即可

 

拖拽成功后,盘符会自动消失,此时固件烧录工作即完成

Pico会重新启动,开始运行程序

14、安装网络数据检测软件:

book@100ask:~$ sudo add-apt-repository ppa:wireshark-dev/stable

book@100ask:~$ sudo apt update

book@100ask:~$ sudo apt install

book@100ask:~$ sudo usermod -aG wireshark $USER

0.2 BLINKGPIO25

0.3 串口HelloWorld

将rp2040开发板的GP0引脚连接到串口调试助手的RXD引脚

 

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include "pico/stdlib.h"
#include "pico/binary_info.h"

int main()
{
    stdio_init_all();

    const uint LED_PIN = PICO_DEFAULT_LED_PIN;
    gpio_init(LED_PIN);
    gpio_set_dir(LED_PIN, GPIO_OUT);


    while(1){
        gpio_put(LED_PIN, 1);
        sleep_ms(500);
        gpio_put(LED_PIN, 0);
        sleep_ms(250);
		printf("hello world!\n")
    }
}

 

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

 

将笔记本wifi的因特网共享给有线网卡:

 

通过网线连接W5100和PC的网口。

 

Rp2040的ip设置为:192.168.137.110

 

虚拟机中的Ubuntu ping树莓派rp2040结果:

 

主机PC ping树莓派:

 

使用抓包软件Wireshark抓取ubuntu的ping报文:

使用过滤器找到需要的数据包:

输入icmp协议找到ping包:

 

       通过ip地址筛选:ip.addr==192.168.137.110

 

              第一行:物理层

              第二行:数据链路层,数据来源于什么设备,发往什么设备

              第三行:网络层ipv4协议

              第四行:icmp应用层协议

 

根据type和code获得当前数据包的类型,下图为ping请求数据包

 

树莓派dns转换:

   

树莓派ping百度:

     

本任务需要官方sdk包的支持:

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

将sdk包中的以下文件放入工程文件中:

 

主函数:

#include <stdio.h>
#include <string.h>
#include "pico/stdlib.h"
#include "pico/binary_info.h"
#include "hardware/spi.h"
#include "hardware/i2c.h"
#include "inc/raspberry26x32.h"
#include "inc/ssd1306_font.h"
#include "inc/ssd1306_i2c.h"

#include "inc/wizchip_conf.h"
#include "inc/w5500.h"
#include "inc/w5500_spi.h"
#include "inc/dns.h"
#include "inc/loopback.h"
#include "inc/ping.h"

//定义了一个全局变量net_info来存储网卡地址信息
static wiz_NetInfo net_info = {
        .mac = {0x00, 0x08, 0xdc, 0x16, 0xed, 0x2e},//mac地址
        .ip = {192, 168, 137, 110},                         //IP地址
        .sn = {255, 255, 255, 0},                           //子网掩码
        .gw = {192, 168, 137, 1},                           //默认网关
        .dns = {8, 8, 8, 8},                                //dns信息
        .dhcp = NETINFO_STATIC};                                            //DHCP模式为静态地址模式

#define ETHERNET_BUF_MAX_SIZE (1024 * 2)
#define SOCKET_ID 0

int dns_test(void);
bool repeating_timer_callback(struct repeating_timer *t);
void do_ping(void);

wiz_NetInfo get_info;
static uint8_t ethernet_buf_dns[ETHERNET_BUF_MAX_SIZE] = {0,};
uint8_t DNS_2nd[4] = {114,114,114,114};
uint8_t Domain_name[] = "www.baidu.com";                                    //需要的解析域名
uint8_t Domain_IP[4] = {0,};                                                //域名IP地址
uint8_t g_msec_cnt = 0;

static uint8_t ethernet_buf_ping[ETHERNET_BUF_MAX_SIZE] = {0,};
static uint8_t destip[4]={192, 168, 137, 1};
static uint16_t destport = 8080;
static uint16_t local_port =8000;

int main()
{
    /*---------------------------------LED-GPIO-CONFIGURATION---------------------------------------*/
    const uint LED_PIN = PICO_DEFAULT_LED_PIN;
    gpio_init(LED_PIN);
    gpio_set_dir(LED_PIN, GPIO_OUT);

    /*---------------------------------W5500-CONFIGURATION---------------------------------------*/
    struct repeating_timer timer;
    stdio_init_all();       //串口重定义到printf函数
    sleep_ms(2000);

    wizchip_initialize();   //初始化
    sleep_ms(5000);

    printf("W5500 network install example.\r\n");
    wizchip_setnetinfo(&net_info);              //设置网卡信息
    print_network_information(get_info);

    printf("W5500 dns test example.\r\n");
    DNS_init(0,ethernet_buf_dns);   //传入一个socket端口号和dns信息的接收缓存buff地址
    add_repeating_timer_ms(1000, repeating_timer_callback, NULL, &timer);

    while (true) {
        if (dns_test()){

            while(true){
                do_ping();
                if(req>=4)
                {
                    while (true) {
                        gpio_put(LED_PIN, 1);
                        sleep_ms(500);
                        gpio_put(LED_PIN, 0);
                        sleep_ms(250);
                    }
                }

            }

        }
        sleep_ms(2000);

    }
}

int dns_test(void)
{
    int ret;
    printf("\r\n===== DNS Client Example =====\r\n");
    printf("> DNS 1st: %d.%d.%d.%d\r\n",net_info.dns[0],net_info.dns[1],net_info.dns[2],net_info.dns[3]);
    printf("> DNS 2nd: %d.%d.%d.%d\r\n",DNS_2nd[0],DNS_2nd[1],DNS_2nd[2],DNS_2nd[3]);
    printf("==============================\r\n");
    printf("> Example Domain Name : %s\r\n",Domain_name);

    //dns服务器ip,请求解析的域名,以及解析后ip存放的地址
    if((ret = DNS_run(net_info.dns, Domain_name, Domain_IP)) > 0)
    {
        printf("> 1st DNS Reponsed\r\n");
    }
    else if((ret != -1) && ((ret = DNS_run(DNS_2nd, Domain_name, Domain_IP)) > 0))
    {
        printf("> 2nd DNS Responsed\r\n");
    }
    else if(ret == -1)
    {
        printf("> MAX_DOMAIN_NAME is too small. Should be redefined it. \r\n");
    }
    else
    {
        printf("> DNS Failed\r\n");
    }
    if(ret > 0)
    {
        printf("> Translated %s to %d.%d.%d.%d\r\n",Domain_name,Domain_IP[0],Domain_IP[1],Domain_IP[2],Domain_IP[3]);
        return 1;
    }
    return 0;
}

/* Timer */
bool repeating_timer_callback(struct repeating_timer *t)
{
    DNS_time_handler();
    return true;
}

void do_ping(void)
{
    printf("------------PING_TEST_START-----------------------\r\n");
    sleep_ms(1000); // wait 1000ms
    //ping_auto(0,destip);        //传入一个socket端口号和需要Ping的对象IP信息,成功则返回Ping的信息,Ping失败则打印失败的信息
    ping_auto(0,Domain_IP);
}

 

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

更改笔记本电脑有线网口ip为:192.168.0.18

 

rp2040+w5500的ip设置为:192.168.0.110

 

 

报文分析:

 

主函数:

#include <stdio.h>
#include "pico/stdlib.h"
#include "pico/binary_info.h"
#include "hardware/i2c.h"

#include "inc/wizchip_conf.h"
#include "inc/w5500_spi.h"
#include "inc/loopback.h"

//定义了一个全局变量net_info来存储网卡地址信息
static wiz_NetInfo net_info = {
        .mac = {0x00, 0x08, 0xdc, 0x16, 0xed, 0x2e},//mac地址
        .ip = {192, 168, 0, 110},                         //IP地址
        .sn = {255, 255, 255, 0},                           //子网掩码
        .gw = {192, 168, 0, 1},                           //默认网关
        .dns = {8, 8, 8, 8},                                //dns信息
        .dhcp = NETINFO_STATIC};                                            //DHCP模式为静态地址模式

#define ETHERNET_BUF_MAX_SIZE (1024 * 2)
#define SOCKET_ID 0

wiz_NetInfo get_info;

static uint8_t ethernet_buf_tcpclient[ETHERNET_BUF_MAX_SIZE] = {0,};
static uint16_t local_port_tcpclient = 8080;

int main()
{
    const uint LED_PIN = PICO_DEFAULT_LED_PIN;
    gpio_init(LED_PIN);
    gpio_set_dir(LED_PIN, GPIO_OUT);

    struct repeating_timer timer;
    stdio_init_all();       //串口重定义到printf函数

    wizchip_initialize();   //初始化

    printf("W5500 network install example.\r\n");
    wizchip_setnetinfo(&net_info);              //设置网卡信息
    print_network_information(get_info);
    
    sleep_ms(200);
    printf("W5500 tcp server example.\r\n");
    while(true)
    {
        //tcp服务端的回环测试函数:socket端口号、收发数据的缓存和端口
        loopback_tcps(SOCKET_ID, ethernet_buf_tcpclient, local_port_tcpclient);

        gpio_put(LED_PIN, 1);
        sleep_ms(250);
        gpio_put(LED_PIN, 0);
        sleep_ms(250);
    }

}

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

NTP报文格式

 

 

NTP报文格式如上图所示,它的字段含义参考如下:

LI 闰秒标识器,占用2个bit

VN 版本号,占用3个bits,表示NTP的版本号,现在为3

Mode 模式,占用3个bits,表示模式

stratum(层),占用8个bits

Poll 测试间隔,占用8个bits,表示连续信息之间的最大间隔

Precision 精度,占用8个bits,,表示本地时钟精度

Root Delay根时延,占用8个bits,表示在主参考源之间往返的总共时延

Root Dispersion根离散,占用8个bits,表示在主参考源有关的名义错误

Reference Identifier参考时钟标识符,占用8个bits,用来标识特殊的参考源   

参考时间戳,64bits时间戳,本地时钟被修改的最新时间。

原始时间戳,客户端发送的时间,64bits。

接受时间戳,服务端接受到的时间,64bits。

传送时间戳,服务端送出应答的时间,64bits。

认证符(可选项)

 

主函数:

#include <stdio.h>
#include "pico/stdlib.h"
#include "pico/binary_info.h"

#include "inc/wizchip_conf.h"
#include "inc/w5500_spi.h"
#include "inc/sntp.h"

//定义了一个全局变量net_info来存储网卡地址信息
static wiz_NetInfo net_info = {
        .mac = {0x00, 0x08, 0xdc, 0x16, 0xed, 0x2e},//mac地址
        .ip = {192, 168, 137, 110},                         //IP地址
        .sn = {255, 255, 255, 0},                           //子网掩码
        .gw = {192, 168, 137, 1},                           //默认网关
        .dns = {8, 8, 8, 8},                                //dns信息
        .dhcp = NETINFO_STATIC};                                            //DHCP模式为静态地址模式

wiz_NetInfo get_info;

#define ETHERNET_BUF_MAX_SIZE (1024 * 2)
#define SOCKET_SNTP 0
#define TIMEZONE 39 // China
static uint8_t ethernet_buf_ntp[ETHERNET_BUF_MAX_SIZE] = {0,};
static uint8_t g_sntp_server_ip[4] = {203, 107, 6, 88};
datetime time={0};

int main()
{
    const uint LED_PIN = PICO_DEFAULT_LED_PIN;
    gpio_init(LED_PIN);
    gpio_set_dir(LED_PIN, GPIO_OUT);

    struct repeating_timer timer;
    stdio_init_all();       //串口重定义到printf函数
    sleep_ms(2000);

    wizchip_initialize();   //初始化
    sleep_ms(5000);

    printf("W5500 network install example.\r\n");
    wizchip_setnetinfo(&net_info);              //设置网卡信息
    print_network_information(get_info);
    
    sleep_ms(200);
    printf("W5500 ntp example.\r\n");
    SNTP_init(SOCKET_SNTP,g_sntp_server_ip,TIMEZONE,ethernet_buf_ntp);

    while(true)
    {
        //tcp服务端的回环测试函数:socket端口号、收发数据的缓存和端口
        SNTP_run(&time);

        printf(" %d-%d-%d, %d:%d:%d\n", time.yy, time.mo, time.dd, time.hh, time.mm, time.ss);

        gpio_put(LED_PIN, 1);
        sleep_ms(200);
        gpio_put(LED_PIN, 0);
        sleep_ms(800);
    }
}

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

硬件连线:

软件架构: 

 

终极任务在thonny环境下使用python完成:

1、首先安装thonny开发环境(建议下载最新版本,否则有些插件搜不到):https://thonny.org/

2、然后下载固件:https://micropython.org/download/W5500_EVB_PICO/

3、线路连接:将tf卡模块的3v3、GND、cs、MOSI、CLK、MISO引脚分别连接到rp2040开发板的3v3、GND、GP13、GP11、GP10、GP12引脚。

 

4、Thonny安装sdcard库:工具-管理包

 

5、参考链接

链接已隐藏,如需查看请登录或者注册
,使用库中的uftpd.py文件,更改标签为“start”的代码:

# start listening for ftp connections on port 21
def start(host='0.0.0.0',port=21, verbose=0, splash=True):
    global ftpsockets, datasocket
    global verbose_l
    global client_list
    global client_busy

    alloc_emergency_exception_buf(100)
    verbose_l = verbose
    client_list = []
    client_busy = False

    addr = socket.getaddrinfo(host, port)
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    sock.bind(addr[0][4])
    sock.listen(1)
    sock.setsockopt(socket.SOL_SOCKET,
                    _SO_REGISTER_HANDLER,
                    lambda s : accept_ftp_connect(s,host))
    ftpsockets.append(sock)
    if splash:
        print("FTP server started on {}:{}".format(host, port))

    datasocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    datasocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    datasocket.bind(('0.0.0.0', _DATA_PORT))
    datasocket.listen(1)
    datasocket.settimeout(10)

6、主函数代码为:

import network,time
from machine import Pin,SPI

#w5500 初始化
def w5x00_init():    
    spi=SPI(0,2_000_000, mosi=Pin(19),miso=Pin(16),sck=Pin(18))#初始化SPI外设接口,用于wiznet芯片通信与控制
    nic = network.WIZNET5K(spi,Pin(17),Pin(20)) #spi,cs,reset pin
    nic.active(True)#网络激活
    
    #配置静态网络信息
    nic.ifconfig(('192.168.137.110','255.255.255.0','192.168.137.1','8.8.8.8'))
    
    while not nic.isconnected():#当网络未配置成功时
        time.sleep(1)
    print(nic.ifconfig())#打印IP、子网掩码、网关、DNS


def sdcard_init():
    import os
    from sdcard import SDCard
    from machine import Pin,SPI
    
    #sd卡模块连接到rp2040的spi1外设
    spi = SPI(1,2_000_000,sck=Pin(10), mosi=Pin(11), miso=Pin(12))
    
    #spi,cs
    sd = SDCard(spi, Pin(13))
    
    # 挂载SD卡到/sd目录
    os.mount(sd, '/sd')
    print(f'success mounted sdcard in /sd')

if __name__ == "__main__":
    # 初始化网络
    w5x00_init()
    
    # 初始化并挂在sd卡
    sdcard_init()
    
    import uftpd
    uftpd.start(host = '192.168.137.110',port = 21,verbose = 0)

7、实验结果

 

五、对本次活动的心得体会:

本人接触嵌入式有5年时间,大多偏向于单片机底层,对网络协议一知半解,故很高兴能有机会参加本次活动。通过本次活动,我学习了rp2040在linux环境下的开发、windows-thonny环境下的开发,学习了ubuntu的基本命令、python的基本语法、基本网络拓扑结构、ping操作、dns的功能、tcp服务器的原理、从ntp服务器同步时间、基于tf卡建立ftp服务器。

刚接触任务时,我采用thonny开发,但我不太熟悉python,故有些吃力,看到w5500官方有专门的c-sdk,所以我最后采用了linux环境下的clion开发,这对熟悉c语言的同学很友好。前几个任务w5500官方基本都有sdk例程参考,所以我很轻松的完成了任务。终极任务因为python环境下有github参考例程,故终极任务采用python语言开发。

六、参考链接:

eeworld follow me4教程:W5500-EVB-Pico 使用入门-直播回放: FollowMe 4 W5500-EVB-Pico 使用入门-EEWORLD大学堂

w5500官方csdn教程:WIZnet W5500-EVB-Pico C/C++教程_WIZnet的博客-CSDN博客

w5500官方c-sdk:

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

 

最新回复

感谢楼主分享,认真读了这个文章,好贴!!!!  详情 回复 发表于 2024-3-5 18:30
点赞 关注
 
 

回复
举报

419

帖子

0

TA的资源

纯净的硅(中级)

沙发
 
感谢楼主分享,认真读了这个文章,好贴!!!!
 
 
 

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

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

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

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