891|2

29

帖子

2

TA的资源

一粒金砂(中级)

楼主
 

【得捷Follow me第4期】项目总结 [复制链接]

 

一、前言(含视频)

        本次Follow Me 4共分为4个任务:入门任务,基础任务,进阶任务和终极任务,其中,基础任务分为两个小任务,所以共六个任务,都顺利完成。

        并且已经将内容一的视频上传至网络大学堂,视频地址为:https://training.eeworld.com.cn/video/39296 ;视频里包含了各任务的现场烧录演示及说明。

 

        任务完成所用开发环境为Paspberry Pi的Pico SDK v1.5.1+VSCode;其中VSCode不多赘述,而Paspberry Pi的Pico SDK v1.5.1的下载地址为 

链接已隐藏,如需查看请登录或者注册
,安装过程可参考 WIZnet W5500-EVB-Pico树莓派入门教程(一)-CSDN博客

 

        任务完成所用硬件如下几个:W5500-EVB-Pico(必购);Pico-LCD 1.14(用于大部分的显示任务);AtomS3(W5500-EVB-Pico在做FTP服务器时,读取SD卡需要用的SPI,导致无法使用Pico-LCD做显示,通过UDP传输显示数据给AtomS3,用AtomS3做显示);SEEED XIAO ESP32 C3(测试W5500-EVB-Pico的UDP Server功能)、DAPLink一个(自备,用于在线仿真,方便调试网络)以及自己绘制的LCD转接板一个,方便给将W5500-EVB-Pico主板与Pico-LCD组合起来,转接板如下:

图1-1

        下面将各任务逐一介绍并展示(内容二)。

二、入门任务

    2.1 任务介绍

        搭建开发环境,点亮小灯让其闪烁,并在显示屏上显示内容。

    2.2 主要代码片段

        LCD的显示主要靠移植Pico-LCD的官方驱动,其下载地址为https://www.waveshare.net/w/upload/2/28/Pico_code.7z将其C驱动部分复制至工程目录下,并改名为LCD,在工程目录下的CMake中添加如下命令:

add_subdirectory(DISPLAY/Config)
add_subdirectory(DISPLAY/LCD)
add_subdirectory(DISPLAY/Fonts)
add_subdirectory(DISPLAY/GUI)

        并在项目目录下的CMake中添加如下命令:

include_directories(../DISPLAY/Config)
include_directories(../DISPLAY/GUI)
include_directories(../DISPLAY/LCD)

        这样即包含了Pico-LCD的驱动库,初始化后就可直接显示输入内容,初始化过程如下:

    DEV_Module_Init();
    DEV_SET_PWM(30);
    LCD_1IN14_V2_Init(HORIZONTAL);
    LCD_1IN14_V2_Clear(BLACK);

    UDOUBLE Imagesize = LCD_1IN14_V2_HEIGHT*LCD_1IN14_V2_WIDTH*2;
    BlackImage = (UWORD *)malloc(Imagesize);
    Paint_NewImage((UBYTE *)BlackImage,LCD_1IN14_V2.WIDTH,LCD_1IN14_V2.HEIGHT, 0, BLACK);
    Paint_SetScale(65);
    Paint_SetRotate(ROTATE);
    Paint_Clear(BLACK);
    LCD_1IN14_V2_Display(BlackImage);


			

        之后在Paint_DrawString_EN函数中输入字符串数组,显示坐标即可显示相应内容。

        小灯的闪烁代码如下:

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

    while (true) {
        gpio_put(LED_PIN, 1);
        sleep_ms(250);
        gpio_put(LED_PIN, 0);
        sleep_ms(250);
    }

    2.3 功能展示

图2-1 驱动显示屏(显示屏通过转接板叠加在主控板上)
图2-2 BLink

 

 

三、基础任务一

    3.1 任务介绍

        主板W5500-EVB-Pico获取静态IP,并且PC能够ping通,同时主板可以ping通外网;PCping通结果抓包显示。

    3.2 主要代码片段

        需要用到W5500的官方库,其地址为https://gitee.com/wiznet-hk/w5500-evb-pico-routine.git

        随后如同上述LCD添加入库,即可调用相关函数即可实现静态IP:只要初始化W5500完成,再设置网络信息,标记为静态获取即可。

// 网络信息 默认静态
wiz_NetInfo net_info = {
    .mac = {0x00, 0x08, 0xdc, 0x1e, 0xed, 0x2e}, // Configured MAC address
    .ip = {192, 168, 1, 31},                     // Configured IP address
    .sn = {255, 255, 255, 0},                    // Configured subnet mask
    .gw = {192, 168, 1, 1},                      // Configured gateway
    .dns = {8, 8, 8, 8},                         // Configured domain address
};
// 初始化
wizchip_initialize();
sleep_ms(50);
wizchip_setnetinfo(&net_info);
print_network_information(get_info);

        想要ping通互联网,则是向特定的目的主机发送 ICMP(Internet Control Message Protocol 因特网报文控制协议)Echo 请求报文,核心代码如下:

void ping_auto(uint8_t s, uint8_t *addr)
{
	uint8_t i;
	int32_t len = 0;
	uint8_t cnt=0;
	for(i = 0; i<=3;i++)																		
	{
		sleep_ms(10); 
		switch(getSn_SR(s))																		
		{
			case SOCK_CLOSED:																		
				close(s);
				IINCHIP_WRITE(Sn_PROTO(s), IPPROTO_ICMP);           
				if(socket(s,Sn_MR_IPRAW,3000,0)!=0)									
				{ }
				while(getSn_SR(s)!=SOCK_IPRAW);
				sleep_ms(2000); 																																				
			break;
				
			case SOCK_IPRAW:																		
				ping_request(s, addr);															
				req++;
				sleep_ms(50);
				while(1)
				{	
					if ( (len = getSn_RX_RSR(s) ) > 0)
					{	
						ping_reply(s, addr, len);												
						sleep_ms(50); 																	
						rep++;
						break;
					}
					else if(cnt > 200)
					{
						printf( "Request Time out. \r\n");
						cnt = 0;
						break;
					}
					else
					{
						cnt++;
						sleep_ms(50); 																	/*wait 50ms*/
					}
					// wait_time for 2 seconds, Break on fail
				}
	
			break;
			default:
			break;
		}
			#ifdef PING_DEBUG
		if(rep!=0)
		{
			printf("Ping Request = %d, PING_Reply = %d\r\n",req,rep);
			if(rep == req)
				printf( "PING SUCCESS\r\n " );
			else
				printf( "REPLY_ERROR\r\n " );
		}	
    else{}		
			#endif  
	}

}

    3.3 功能展示

图3-1 PC端Ping主板成功图
图3-2 主控板Ping互联网成功串口输出图
 

  四、基础任务二

    4.1 任务介绍

         主板W5500-EVB-Pico做UDP服务器,并能将PC端的UDP客户端发送内容显示在显示屏上,再抓包对比报文。同时使用SEEED XIAO ESP32 C3做UDP客户端进行测试。

    4.2 核心代码片段

         正常初始化网络即可,UDP主要涉及Socket,包含头文件 #include "socket.h" 即可,然后轮询状态(判断是否有数据传输等)即可,代码如下:

int32_t udps_2(uint8_t sn, uint8_t* buf, uint16_t port)
{
   int32_t  ret;
   uint16_t size, sentsize;
   uint8_t  destip[4];
   uint16_t destport;

   switch(getSn_SR(sn))
   {
      case SOCK_UDP :
         if((size = getSn_RX_RSR(sn)) > 0)
         {
            if(size > DATA_BUF_SIZE) size = DATA_BUF_SIZE;
            ret = recvfrom(sn, buf, size, destip, (uint16_t*)&destport);
            buf[ret]=0x00;
            // printf("recv from[%d.%d.%d.%d][%d]: %s\n", destip[0],destip[1],destip[2],destip[3],destport,buf);
            sprintf(RecvIP[RecvCnt], "> %d.%d.%d.%d:%d", destip[0],destip[1],destip[2],destip[3],destport);
            sprintf(RecvBuf[RecvCnt], "> %s", buf);
            ddebug(RecvIP[RecvCnt]);
            ddebug(RecvBuf[RecvCnt]);
            if(++RecvCnt >= 10) RecvCnt = 0;
            if(ret <= 0)
            {
               return ret;
            }
            size = (uint16_t) ret;
            sentsize = 0;
            while(sentsize != size)
            {
               ret = sendto(sn, buf+sentsize, size-sentsize, destip, destport);
               if(ret < 0)
               {
                  return ret;
               }
               sentsize += ret; // Don't care SOCKERR_BUSY, because it is zero.
            }
         }
         break;
      case SOCK_CLOSED:
         if((ret = socket(sn, Sn_MR_UDP, port, 0x00)) != sn)
            return ret;
         printf("local port:%d\n",port);
         break;
      default :
         break;
   }
   return 1;
}

    4.3 成果展示

          先是用PC端的UDP(192.168.1.22:3333)发送Follow Me 4!到到主控板(192.168.1.31:8000),并用WireShark抓包(过滤条件为<ip.addr == 192.168.1.31 and udp>),显示如下:

图4-1 PC和主控板UDP通信抓包显示

           再用SEED XIAO ESP32C3做UDP的客户端(192.168.1.45:8000)去测试主控板的UDP服务器功能,每3秒发送一次Follow Me 4!;同时通过显示屏展示收到的内容,完成情况如下:

图4-2 主控板显示屏显示UDP接收内容(包含主机和XIAOESP32C3)

 

五、进阶任务

    5.1 任务内容 

          从NTP服务器同步时间,获取时间送显示屏显示。

    5.2 核心代码片段

          本质上还是UDP,这里选择用tx的NTP服务器,测试期间其地址为106.55.184.199;NTP及格式解析核心代码如下:

// NTP
int8_t SNTP_run(datetime *time)
{
	uint16_t RSR_len;
	uint32_t destip = 0;
	uint16_t destport;
	uint16_t startindex = 40;

	switch(getSn_SR(NTP_SOCKET))
	{
	case SOCK_UDP:
		if ((RSR_len = getSn_RX_RSR(NTP_SOCKET)) > 0)
		{
			if (RSR_len > MAX_SNTP_BUF_SIZE) RSR_len = MAX_SNTP_BUF_SIZE;
			recvfrom(NTP_SOCKET, data_buf, RSR_len, (uint8_t *)&destip, &destport);
			get_seconds_from_ntp_server(data_buf,startindex);
			time->yy = Nowdatetime.yy;
			time->mo = Nowdatetime.mo;
			time->dd = Nowdatetime.dd;
			time->hh = Nowdatetime.hh;
			time->mm = Nowdatetime.mm;
			time->ss = Nowdatetime.ss;

			ntp_retry_cnt=0;
			close(NTP_SOCKET);

			return 1;
		}

		if(ntp_retry_cnt<0xFFFF)
		{
			if(ntp_retry_cnt==0)//first send request, no need to wait
			{
				sendto(NTP_SOCKET,ntpmessage,sizeof(ntpmessage),NTPformat.dstaddr,ntp_port);
				ntp_retry_cnt++;
			}
			else // send request again? it should wait for a while
			{
				if((ntp_retry_cnt % 0xFFF) == 0) //wait time
				{
					sendto(NTP_SOCKET,ntpmessage,sizeof(ntpmessage),NTPformat.dstaddr,ntp_port);
					ntp_retry_cnt++;
				}
			}
		}
		else //ntp retry fail
		{
			ntp_retry_cnt=0;
			close(NTP_SOCKET);
		}
		break;
	case SOCK_CLOSED:
		socket(NTP_SOCKET,Sn_MR_UDP,ntp_port,0);
		break;
	}
	return 0;
}
// 送显示
sprintf(time_str[count], "> %d-%02d-%02d %02d:%02d:%02d", time.yy, time.mo, time.dd, time.hh, time.mm, time.ss);
ddebug(time_str[count]);

    5.3 成果展示

           NTP实验内容较好展示,直接百度上搜索北京时间,然后对比即可,显示每1s才刷新一次,会存在误差,对比如下:

图5-1 左为浏览器显示北京时间 右为主控板每秒输出时间
 

六、最终任务

    6.1 任务内容

          使用外部SD卡存储器,组建简易FTP文件服务器,并能正常上传下载文件。同时因SD卡需占用一路SPI,故舍弃LCD,采用UDP传输给AtomS3用于显示FTP服务器相关内容。

    6.2 核心代码片段

          主要是SD卡和FatFs的移植,有现成的库,地址为 

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

          设置静态IP,并修改并记住FTP的ID和密码,再开启Fatfs功能,需要修改部分代码,主要添加两个接口函数,scan_files和get_filesize,分别是扫描和获取大小,内容如下

long get_filesize(const char *dirPath, const char *filename) {
    char fullPath[256];  // 假设路径长度不超过255个字符
    FILINFO fno;
    FRESULT fr;

    // 构造完整路径
    snprintf(fullPath, sizeof(fullPath), "%s/%s", dirPath, filename);
    
    // 使用 f_stat 获取文件信息
    fr = f_stat(fullPath, &fno);
    if (fr == FR_OK) {
        return (long)fno.fsize;  // 返回文件大小
    } else {
        return -1;  // 发生错误,返回 -1
    }
}

FRESULT scan_files (
	char *path, /* Start node to be scanned (***also used as work area***) */
	char *files,
	uint16_t *num)
{
	FRESULT res;
	DIR dir;
	UINT i;
	static FILINFO fno;
	uint16_t _num = 0;
	*num = 0;
	res = f_opendir(&dir, path); /* Open the directory */
	if (res == FR_OK) {
	for (;;) {
	res = f_readdir(&dir, &fno); /* Read a directory item */
	if (res != FR_OK || fno.fname[0] == 0) break; /* Break on error or end of dir */
	i = strlen(path);
	uint8_t isdir = (fno.fattrib & AM_DIR);
	char size[32];
	sprintf(size, "%ld", (fno.fattrib & AM_DIR) ? 0 : fno.fsize);
	files += sprintf(files, "%crwxr-xr-x 1 pomin pomin %s Jan 19 2024 %s\r\n", (fno.fattrib & AM_DIR) ? 'd' : '-', size, fno.fname);
	_num++;
	}
	f_closedir(&dir);
	}
	*num = _num;
	return res;
}

    6.3 成果展示

          PC端使用Filezilla做FTP客户端,W5500烧录代码后,使用Filezilla连接,地址为192.168.1.31,ID为DIgikey,密码为Followme4,端口不用选择,默认为21,连接成功,并能上传下载文件,上传过程截图如下:

图6-1 PC向W5500主控板传输图片(速度200K/s)

           虽说无法使用LCD了,但是怎么能没有显示屏呢?所以还用了AtomS3做UDP服务器,将W5500主控板通过UDP发送来的内容进行显示,当作W5500的显示屏,展示如下:

图6-2 AtomS3做主控板的显示器(演示中,上传了两张图片,下载了文本)

 

七、心得体会

        首先是学到了不少东西,接触了RP2040、W5500、ESP32,对Cmake、Ethernet、WIFI等都有了更深的理解,然后最大的感悟还是,没想到嵌入式开发还能如此简单,很多库都是别人写好的,而rp2040引脚又少,调用起来非常简单,觉得嵌入式就该往这个方向发展,更多耗费时间的还得是逻辑与算法。再者就是群里的大佬太多了,见识到了很多,自己仍需努力,向大佬看齐,最后当然是感谢得捷,感谢EEWORLD,谢谢你们提供了这个宝贵的机会,也希望今后多多出这些活动,也祝你们越来越好!

八、附件

       这里就是内容三了,已将全部源码打包并上传至:https://download.eeworld.com.cn/detail/Alohaq/631392 ;如果你也安装了Pico-sdk,那么只需要添加到pcio的vscode环境里,即可编译下载全部内容。

最新回复

Pico-LCD 1.14(用于大部分的显示任务),还是的带显示才能更高完成任务    详情 回复 发表于 2024-2-26 09:12
点赞 关注
 
 

回复
举报

6591

帖子

9

TA的资源

版主

沙发
 

Pico-LCD 1.14(用于大部分的显示任务),还是的带显示才能更高完成任务 

个人签名

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

 
 
 

回复

29

帖子

2

TA的资源

一粒金砂(中级)

板凳
 
秦天qintian0303 发表于 2024-2-26 09:12 Pico-LCD 1.14(用于大部分的显示任务),还是的带显示才能更高完成任务 

就最终任务无法使用Pico-LCD(基础任务静态IP那无需显示),因为SPI分给W5500和SD卡,没硬件SPI支持显示了,又不想软模拟,就用UDP传给AtomS3当显示了。

 
 
 

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

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

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

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