当前位置: 首页 > news >正文

基于正点原子阿波罗F429开发板的LWIP应用(6)——SNTP功能和lwiperf测速

说在开头

        正点原子F429开发板主芯片采用的是STM32F429IGT6,网络PHY芯片采用的是LAN8720A(V1)和YT8512C(V2),采用的是RMII连接,PHY_ADDR为0;在代码中将会对不同的芯片做出适配。

        CubeMX版本:6.6.1;

        F4芯片组Pack包版本:STM32Cube FW_F4 V1.27.0;

        本实验代码以《基于正点原子阿波罗F429开发板的LWIP应用(3)——Netbiosns功能》一章的代码作为基础;

第一部分:SNTP功能实现

        SNTP的全称是“简单网络时间协议”,是一种由NTP协议改编而来的网络时间协议,主要用来同步因特网中的计算机时钟。

        在此实验中开发板做SNTP客户端,通过单播模式定期访问SNTP服务器获得准确的时间进而不断校准单片机的RTC。

        本次实验的工作逻辑如下:首先完成RTC和LWIP的初始化,在初始化完成后开始启动SNTP服务。在完成第一次SNTP授时后还是间隔1S从RTC读取时间并从串口打印出来。

代码修改(代码注释很详细我就不再讲解了)

1、 首先将"Middlewares/Third_Party/LwIP/src/apps/sntp/sntp.c"添加进工程“Application/User/LWIP/App”分组中;

2、在“LWIP/App”中新建“sntp_client.c ”、“sntp_client.h”2个文件并添加到工程“Application/User/LWIP/App”分组中,两个文件分别添加以下代码:

/******************sntp_client.c文件代码**********************/
#include "sntp_client.h"#include "lwip/apps/sntp.h"
#include "time.h"
#include "rtc.h"/*1、中国国家授时中心NTP服务器“域名:ntp.ntsc.ac.cnIP:202.120.2.101 ---> 0X650278CA2、阿里云NTP服务器地址:域名:ntp.aliyun.comIP:110.75.8.1
*//*!
* @brief 设置 SNTP 的服务器地址,
* 		 加入多个 IP 以免某个 IP 获取不了时间
*        执行条件:无
*
* @retval: 无
*/
void set_sntp_server_list(void)
{uint32_t server_list[SNTP_MAX_SERVERS] =	{  0X650278CA,  //国家授时中心0x0B6C1978,0x0B0C5CB6,0x58066BCB,0xC51F70CA,0x521D70CA,0x820176CA,0x510176CA,};ip_addr_t sntp_server;for(int i = 0; i < SNTP_MAX_SERVERS; i++){sntp_server.addr = server_list[i];sntp_setserver(i, &sntp_server);  // 国家授时中心}
}/*!
* @brief Lwip 的 SNTP 初始化封装接口
*        执行条件:无
*
* @retval: 无
*/
void bsp_sntp_init(void)
{/*设置 SNTP 的获取方式SNTP_OPMODE_POLL             //单播模式,客户端主动发送获取时间请求SNTP_OPMODE_LISTENONLY       //组播模式,等待授时服务器主动发送更新时间请求(请求发送时间不确定)*/sntp_setoperatingmode(SNTP_OPMODE_POLL);//SNTP 初始化sntp_init();//加入授时中心的IP信息set_sntp_server_list();/*通过修改sntp_opts.h中的SNTP_UPDATE_DELAY宏定义的值来修改同步时间的间隔默认1小时——3600000,目前修改成1分钟:60000*/
}/*!
* @brief SNTP 获取时间戳的处理函数
*        执行条件:无
*
* @param [in] : sntp 获取的时间戳
*
* @retval: 无
*/
void sntp_set_time(uint32_t sntp_time)
{if(sntp_time == 0){printf("sntp_set_time: wrong!@@\n");return;}struct tm *time;sntp_time += (8 * 60 * 60); ///北京时间是东8区需偏移8小时time = localtime(&sntp_time);//RTC校准RTC_calibration((time->tm_year - 100), (time->tm_mon + 1), time->tm_mday, time->tm_hour, time->tm_min, time->tm_sec, time->tm_wday);if(RTC_calibrate_flag == 0) RTC_calibrate_flag =1;//	printf("sntp_set_time: 20%d-%02d-%02d %d:%d:%d, 星期%d", \
//		time->tm_year - 100,
//		time->tm_mon + 1,
//		time->tm_mday,
//		time->tm_hour,
//		time->tm_min,
//		time->tm_sec,
//		(time->tm_wday==0 ? 7 : time->tm_wday));//星期需要注意:0表示周天,1-6表示周一到周六}/******************sntp_client.h文件代码**********************/
#ifndef __SNTP_CLIENT_H
#define __SNTP_CLIENT_H#include "main.h"void bsp_sntp_init(void);
void sntp_set_time(uint32_t sntp_time);
#endif

3、在“lwipopts.h”文件中添加以下内容:

#define LWIP_SNTP 											1
#define SNTP_MAX_SERVERS 								8
#include "sntp_client.h"
#define SNTP_SET_SYSTEM_TIME						sntp_set_time 	//定义 Lwip SNTP 的 处理函数
#define SNTP_UPDATE_DELAY								60000           //授时请求发送间隔:1分钟

4、rtc.c文件添加以下内容:

/******************rtc.c文件添加代码**********************/
void RTC_calibration(uint8_t year,uint8_t month,uint8_t day,uint8_t hour,uint8_t minute,uint8_t sec, uint8_t week)//RTC校准
{RTC_DateTypeDef sdatestructure;RTC_TimeTypeDef stimestructure;sdatestructure.Year    = year;//年 自2000开始,0x24表示24年sdatestructure.Month   = month;//月sdatestructure.Date    = day;//日sdatestructure.WeekDay = week;//星期if(HAL_RTC_SetDate(&hrtc,&sdatestructure,RTC_FORMAT_BIN) != HAL_OK){Error_Handler(); }stimestructure.Hours        = hour;stimestructure.Minutes      = minute;stimestructure.Seconds      = sec;stimestructure.TimeFormat = 0;stimestructure.DayLightSaving = RTC_DAYLIGHTSAVING_NONE;stimestructure.StoreOperation = RTC_STOREOPERATION_RESET;if(HAL_RTC_SetTime(&hrtc,&stimestructure,RTC_FORMAT_BIN) != HAL_OK){Error_Handler();}
}void Get_time_info(uint8_t *info)
{RTC_DateTypeDef sdatestructureget;RTC_TimeTypeDef stimestructureget;uint8_t aShowTime[50] = {0};uint8_t aShowDate[50] = {0};/* Get the RTC current Time */HAL_RTC_GetTime(&hrtc, &stimestructureget, RTC_FORMAT_BIN);/* Get the RTC current Date */HAL_RTC_GetDate(&hrtc, &sdatestructureget, RTC_FORMAT_BIN);/* Display time Format : hh:mm:ss */info[0]   =  sdatestructureget.Year;//2000开始info[1] 	=	 sdatestructureget.Month;//1至12info[2]   =  sdatestructureget.Date;//1至31info[3]  	=  stimestructureget.Hours; info[4] 	=	 stimestructureget.Minutes;info[5] 	=  stimestructureget.Seconds;info[6]   =	 sdatestructureget.WeekDay;	//0至6表示周日到周六sprintf((char*)aShowTime,"%02d:%02d:%02d",stimestructureget.Hours, stimestructureget.Minutes, stimestructureget.Seconds);/* Display date Format : mm-dd-yy */sprintf((char*)aShowDate,"%02d-%02d-%02d,week=%d",sdatestructureget.Month, sdatestructureget.Date, 2000 + sdatestructureget.Year, sdatestructureget.WeekDay); printf("%s %s\n",aShowTime,aShowDate);
}/******************rtc.h文件添加代码**********************/
void RTC_calibration(uint8_t year,uint8_t month,uint8_t day,uint8_t hour,uint8_t minute,uint8_t sec, uint8_t week);
void Get_time_info(uint8_t *info);

5、main.c文件增加以下内容:

/******************main.c开头增加以下内容**********************/
uint8_t RTC_calibrate_flag = 0;//RTC校准标志位
uint8_t Internet_timeinfo[7] = { NULL };//网络时间中的:年 月 日 时 分 秒 星期	/******************main函数while(1)前增加以下内容**********************/
bsp_sntp_init();//SNTP初始化/******************main.h增加以下内容**********************/
extern uint8_t RTC_calibrate_flag;//RTC校准标志位
extern uint8_t Internet_timeinfo[7];

6、stm32f4xx_it.c文件增加以下内容:

/******************stm32f4xx_it.c开头增加以下内容**********************/
extern void Get_time_info(uint8_t *info);
uint16_t time_read_count = 0;/******************SysTick_Handler函数最后增加以下内容**********************/time_read_count++;if(time_read_count >= 1000){time_read_count = 0;if(RTC_calibrate_flag) Get_time_info(Internet_timeinfo);//从RTC获取时间}

至此就修改完成了,编译0警告0错误。烧录进开发板可以看到DS0一直闪烁,同时串口间隔1S打印RTC的时间,打印时间和串口接收的时间戳相差不超过1S钟,串口打印如下图:

第二部分:lwiperf测速实现

1、 首先将"Middlewares/Third_Party/LwIP/src/apps/lwiperf/lwiperf.c"添加进工程“Application/User/LWIP/App”分组中;

2、在“LWIP/App”中新建“speed_test.c ”、“speed_test.h”2个文件并添加到工程“Application/User/LWIP/App”分组中,两个文件分别添加以下代码:

/******************speed_test.c内容如下**********************/
#include "speed_test.h"#include "lwip.h"#include "lwip/apps/lwiperf.h"uint8_t info_buf[30];/* 报告状态 */
const char *report_type_str[] = 
{"TCP_DONE_SERVER",             /* LWIPERF_TCP_DONE_SERVER,*/"TCP_DONE_CLIENT",             /* LWIPERF_TCP_DONE_CLIENT,*/"TCP_ABORTED_LOCAL",           /* LWIPERF_TCP_ABORTED_LOCAL, */"TCP_ABORTED_LOCAL_DATAERROR", /* LWIPERF_TCP_ABORTED_LOCAL_DATAERROR, */"TCP_ABORTED_LOCAL_TXERROR",   /* LWIPERF_TCP_ABORTED_LOCAL_TXERROR, */"TCP_ABORTED_REMOTE",          /* LWIPERF_TCP_ABORTED_REMOTE, */"UDP_STARTED",                 /* LWIPERF_UDP_STARTED, */"UDP_DONE",                    /* LWIPERF_UDP_DONE, */"UDP_ABORTED_LOCAL",           /* LWIPERF_UDP_ABORTED_LOCAL, */"UDP_ABORTED_REMOTE"           /* LWIPERF_UDP_ABORTED_REMOTE */
};/* 当测试结束以后会调用此函数,此函数用来报告测试结果 */
/*** @brief       当测试结束以后会调用此函数,此函数用来报告测试结果* @param       无* @retval      无*/
static void lwiperf_report(void *arg,enum lwiperf_report_type report_type,const ip_addr_t *local_addr,u16_t local_port,const ip_addr_t *remote_addr,u16_t remote_port,u32_t bytes_transferred,u32_t ms_duration,u32_t bandwidth_kbitpsec)
{printf("-------------------------------------------------\r\n");if (((int)report_type < (sizeof(report_type_str)/sizeof(report_type_str[0]))) && local_addr && remote_addr){printf(" %s \r\n", report_type_str[report_type]);printf(" Local address : %u.%u.%u.%u ", ((u8_t *)local_addr)[0], ((u8_t *)local_addr)[1],((u8_t *)local_addr)[2], ((u8_t *)local_addr)[3]);printf(" Port %d \r\n", local_port);printf(" Remote address : %u.%u.%u.%u ", ((u8_t *)remote_addr)[0], ((u8_t *)remote_addr)[1],((u8_t *)remote_addr)[2], ((u8_t *)remote_addr)[3]);printf(" Port %d \r\n", remote_port);printf(" Bytes Transferred %d \r\n", (int)bytes_transferred);printf(" Duration (ms) %d \r\n", (int)ms_duration);printf(" Bandwidth (kbitpsec) %d \r\n", (int)bandwidth_kbitpsec);memset(info_buf,0,sizeof(info_buf));sprintf((char*)info_buf,"%u.%u.%u.%u",((u8_t *)local_addr)[0], ((u8_t *)local_addr)[1],((u8_t *)local_addr)[2], ((u8_t *)local_addr)[3]);           /* 显示动态IP地址 */printf("%s\n",info_buf);memset(info_buf,0,sizeof(info_buf));sprintf((char*)info_buf,"%d",local_port);                           /* 显示本地端口 */printf("%s\n",info_buf);memset(info_buf,0,sizeof(info_buf));sprintf((char*)info_buf,"%u.%u.%u.%u",((u8_t *)remote_addr)[0], ((u8_t *)remote_addr)[1],((u8_t *)remote_addr)[2], ((u8_t *)remote_addr)[3]);         /* 显示远程IP地址 */printf("%s\n",info_buf);memset(info_buf,0,sizeof(info_buf));sprintf((char*)info_buf,"%d",remote_port);              /* 显示远程IP端口 */printf("%s\n",info_buf);memset(info_buf,0,sizeof(info_buf));sprintf((char*)info_buf,"%d",(int)bytes_transferred/1024);   /* 转换速度 */printf("%s\n",info_buf);memset(info_buf,0,sizeof(info_buf));sprintf((char*)info_buf,"%d",(int)ms_duration);         /* 持续时间 */printf("%s\n",info_buf);memset(info_buf,0,sizeof(info_buf));sprintf((char*)info_buf,"%d",(int)bandwidth_kbitpsec);  /* 带宽 */printf("%s\n",info_buf);}else{printf(" IPERF Report error\r\n");}
}/*** @brief       lwip_demo实验入口* @param       无* @retval      无*/
void speed_test(void)
{lwiperf_start_tcp_server_default(lwiperf_report,NULL);
}/******************speed_test.h内容如下**********************/
#ifndef __SPEED_TEST_H
#define __SPEED_TEST_H#include "main.h"void speed_test(void);#endif

3、main.c文件增加以下内容:

/******************main.c开头增加以下内容**********************/
#include "speed_test.h"/******************main函数while(1)前增加以下内容**********************/
speed_test();

至此就修改完成了,编译0警告0错误。烧录进开发板串口打印模块IP。

之后运行JPerf 网络测速工具(会和实验源码一起分享),按下图操作即可进行测速:

测速完成后串口也会打印相关信息:

看到这个结果大家肯定会纳闷了,官方不是宣称开发板带的是百兆网络吗,为什么这里测出来才23M呢?那接下来就告诉大家该如何进行优化:在“lwipopts.h”文件中修改以下参数的值可以提升网速(没有就新增):

/* 堆内存的大小,如果需要更大的堆内存,那么设置高一点 */
#define MEM_SIZE (30*1024)
/* MEMP_NUM_PBUF: 设置内存池的数量 */
#define MEMP_NUM_PBUF 25
/* MEMP_NUM_UDP_PCB: UDP 协议控制块的数量. */
#define MEMP_NUM_UDP_PCB 4
/* MEMP_NUM_TCP_PCB: TCP 的数量. */
#define MEMP_NUM_TCP_PCB 8
/* MEMP_NUM_TCP_PCB_LISTEN: 监听 TCP 的数量. */
#define MEMP_NUM_TCP_PCB_LISTEN 2
/* MEMP_NUM_TCP_SEG: 同时排队的 TCP 的数量段. */
#define MEMP_NUM_TCP_SEG 150
/* PBUF_POOL_SIZE: the number of buffers in the pbuf pool. */
#define PBUF_POOL_SIZE          20
/* PBUF_POOL_BUFSIZE: the size of each pbuf in the pbuf pool. */
#define PBUF_POOL_BUFSIZE       LWIP_MEM_ALIGN_SIZE(TCP_MSS+40+PBUF_LINK_ENCAPSULATION_HLEN+PBUF_LINK_HLEN)//1536
/* TCP 接收窗口 */
#define TCP_WND 								(20*TCP_MSS)

编译完成后再次测试,虽然没有达到100M,但也可以稳定在86M,欢迎大家继续优化并把优化好的参数分享在评论区:

本次实验源代码如下:https://download.csdn.net/download/qq_44712722/90970775

http://www.xdnf.cn/news/960805.html

相关文章:

  • 第一章 空间解析几何与向量代数 ~ 空间直角坐标系
  • 【Fifty Project - D35】
  • 在线学堂-第二章媒资管理模块上
  • 高效清理C盘
  • Quick BI 自定义组件开发 -- 第一篇 Lifecycle 接口的定义
  • esp_image: invalid segment length 0xffffffff
  • MySQL自定义函数零基础学习教程
  • FastAPI 与 JWT 身份验证:保护你的 API
  • SpringBoot配置最新的AI版本加入Maven的配置方式
  • CDBench论文精读
  • 树莓派4B, ubuntu20.04, 安装Ros Noetic[踩坑记录]
  • 当拼音文字遇上回文:英语中的诗意镜像与文化密码
  • Profinet转CAN网关如何实现profinet与can协议互转
  • 如何通过API接口获取淘宝商品列表?操作详解
  • Quick BI 自定义组件开发 -- 第二篇 添加 echart 组件,开发图表
  • Spring AMQP
  • 打造高效能技术组织的逆向法则
  • 解读新交规中关于“电动自行车能否在快车道骑行”的核心问题
  • Shellshock漏洞与永恒之蓝(WannaCry)勒索病毒深度分析
  • [大A量化专栏] 看盘界面设置(未完待续)
  • Linux进程信号(一)
  • AI Bot到底是真助手,还是又一个流量收割伎俩?
  • 软件功能测试有哪些类型?软件测评机构
  • CppCon 2015 学习:The Importance of Being const
  • 鸠摩搜书官网入口,免费电子书小说在线搜索下载网站
  • 火山 RTC 引擎10 ----远端视频 转网易视频格式
  • 镜头景深的影响因素有哪些
  • 【西门子杯工业嵌入式-7-OLED】
  • 高防CDN是什么?和传统CDN有什么区别?
  • 深入浅出 红黑树:如何手写红黑树(基于TreeMap,算法导论的实现)