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

使用stm32cubeide stm32f407 lan8720a freertos lwip 实现tcp客户端、服务端及网络数据转串口数据过程详解

1前言

项目需要使用MCU实现网络功能,后续确定方案stm32f407 外接lan8720a实现硬件平台搭建,针对lan8720a也是用的比较多的phy,网上比较多的开发板,硬件上都是选用了这个phy,项目周期比较短,选用了这个常用phy。记得十年前,刚参加工作那会接触的第一个项目,就是MCU实现网络控制协议,当时lwip也不是很流行呢,网络协议栈只能手撕了,当时硬着头皮写,最多也写到UDP,不过对付当时的项目也够用了。抽时间,可以把当时手撕UDP的协议拿出来再看看。技术都是不断的更新迭代,十年后,现在stm32cubeide、stm32cubemx等软件都集成了lwip,这让开发更快速、便捷。但是作为过来人建议,初学者,最好刚开始还是使用固件库、lwip的源码移植,这样对系统理解的更深刻,毕竟网络协议栈真是一门大学问。

文章使用工程下载地址

tcp客户端,具体测试过程参考5.3章节

https://download.csdn.net/download/li171049/90592463

tcp服务端,具体测试过程参考5.4章节

https://download.csdn.net/download/li171049/90592486

2硬件设计

lan8720a的硬件原理图比较成熟,没啥特别要注意的,lan8720a和stm32f407采用rmii的接口。

stm32f407采用串口6作为调试串口,直接通过ttl,也就是该串口的数据可以通过网络数据发送出来,也可以接收到网络数据通过该串口打印出来。

3软件设计

采用STM32CubeIDE 1.17.0,针对硬件配置如下

3.1时钟配置

 

3.2总体配置

如下图所示

3.3Phy的复位管教

 

3.4ETH的配置

如下图所示,选用RMII模式,这里需要注意,Rx Mode的配置为默认即可,针对采用操作系统、和不使用操作系统,该选项的配置会自动更改。

3.5freeRTOS的配置

这里增大默认任务堆栈,不然会出现堆栈溢出错误。

3.6Lwip的配置

主要是采用静态IP,不开启DHCP,针对电脑进行ping包测试。

4关键代码

4.1Phy开机复位

针对phy复位IO,进行上电复位操作

HAL_GPIO_WritePin(GPIOC, GPIO_PIN_0, GPIO_PIN_RESET);
  HAL_Delay(55);
  HAL_GPIO_WritePin(GPIOC, GPIO_PIN_0, GPIO_PIN_SET);
  HAL_Delay(55);

4.2tcp客户端初始化

这里尝试使用raw api进行编程,但是测试效果不理想,太差了,不够稳定,很多时候不能建立链接。排查问题后发现,tcp_new();后的网卡地址默认为0,无法和远端地址建立路由关系,Don't even try to send a SYN packet if we have no route since that will fail。就替换为NETCONN API进行tcp客户端设计。

采用NETCONN API实现tcp 客户端,考虑tcp连接的断掉重连,优化设计,实现客户端断弦、断电,开机重连等设计。

初始化代码如下

  /* init code for LWIP */
  MX_LWIP_Init();
  /* USER CODE BEGIN 5 */
  /* Infinite loop */
  osDelay(2000);
  //tcp_client_init();//初始化tcp客户端
  client_init();
  for(;;)
  {
    osDelay(1000);
    time_cnt++;
    printf("time_cnt = %ld\r\n", time_cnt);
  }
  /* USER CODE END 5 */

主要功能代码如下

while (1)
	{

		conn = netconn_new(NETCONN_TCP);

		if (conn == NULL)
		{
			printf("Create conn failed!\r\n");
			osDelay(1000);
			continue;
		}
		IP4_ADDR(&ipaddr,192,168,1,22);
		ret = netconn_connect(conn,&ipaddr,TCP_CLIENT_PORT);
		if (ret != ERR_OK)
		{
			printf("Connect failed!\r\n");
			netconn_disconnect(conn);
			netconn_close(conn);
			netconn_delete(conn);
			osDelay(1000);
			continue;
		}
		//printf("Connect to iperf server successful!\r\n");
		while (1)
		{
			//客户端发送数据
			ret = netconn_write(conn,send_buf,sizeof(send_buf),0);
			if(ret != ERR_OK)
			{
				netconn_disconnect(conn);
				netconn_close(conn);
				netconn_delete(conn);
				printf("netconn_write error!\r\n");
				osDelay(1000);
				break;
			}
			osDelay(1000);
			//客户端接收数据
			if(1)
			{
				struct netbuf *buf;
				void *data;
				u16_t len;
				while ((err = netconn_recv(conn, &buf)) == ERR_OK)
				{
					do
					{
						netbuf_data(buf, &data, &len);
						err= netconn_write(conn, data, len, NETCONN_COPY);
						printf("Rev:%s\r\n", (char*)data);//接收数据打印到串口
					}while (netbuf_next(buf) >= 0);
					netbuf_delete(buf);
				}
			}
		}
	}

4.3tcp服务端初始化

Tcp服务端初始化

void StartDefaultTask(void *argument)
{
  /* init code for LWIP */
  MX_LWIP_Init();
  /* USER CODE BEGIN 5 */
  /* Infinite loop */
  osDelay(2000);
  tcpecho_init();

  for(;;)
  {
    osDelay(1000);
    time_cnt++;
    printf("time_cnt = %ld\r\n", time_cnt);
  }
  /* USER CODE END 5 */
}

5测试记录

5.1电脑IP配置

同一网段,192.168.1.22

5.2ping包测试

电脑的的ping包测试

5.3网络调试助手模拟tcp服务端,STM32为tcp客户端

使用网络调试助手,作为tcp服务端监听192.169.1.22:8000端口号,

测试如下图所示,可以看到能够链接成功后,接收到This is a TCP Client test...

同时网络调试助手发送,QQQ,可以看到串口能够收到对应字样,STM32收到QQQ后又返回发送给网络调试助手。同时可以看到串口也打印了接收的数据信息。

5.4网络调试助手模拟tcp客户端,STM32为tcp服务端

使用网络调试助手,作为tcp客户端连接192.169.1.70:5001端口号,

测试如下图所示,可以看到能够链接成功后,接收到The server is connected...

同时网络调试助手发送,QQQ,可以看到串口能够收到对应字样,STM32收到QQQ后又返回发送给网络调试助手。同时可以看到串口也打印了接收的数据信息。

6资源下载 

文章使用工程下载地址

tcp客户端,具体测试过程参考5.3章节

https://download.csdn.net/download/li171049/90592463

tcp服务端,具体测试过程参考5.4章节

https://download.csdn.net/download/li171049/90592486

 

http://www.dtcms.com/a/123030.html

相关文章:

  • SQL 关键字
  • 低硬件资源微调预训练Mamba模型的方法
  • 在 transformers 中,return_tensors=‘pt‘ 里的 pt 是什么 tf,np
  • gdal_shp文件的组成
  • 【设备连接涂鸦阿里云】
  • [数据结构]Trie字典树
  • RocketMQ和kafka 的区别
  • 算法导论(递归回溯)——⼆叉树中的深搜
  • lanqiaoOJ 498 回文日期
  • ValueError: Cannot handle batch sizes > 1 if no padding token is defined`
  • 数据结构(五)——AVL树(平衡二叉搜索树)
  • 【Python语言基础】17、继承
  • 深入理解 Spring 的 MethodParameter 类
  • 测试的分类
  • OpenCV 图形API(25)图像滤波-----均值滤波(模糊处理)函数blur()
  • 写一个简单的demo来理解数据库外键
  • Java中的参数是值传递还是引用传递?
  • webpack配置导致浏览器自动刷新
  • Pytest+Allure+Excel接口自动化测试框架实战
  • 【Kafka基础】监控与维护:分区健康检查,确保数据高可用
  • 【C++算法】53.链表_重排链表
  • 数据可视化 —— 柱形图应用(大全)
  • 《Uniapp-Vue 3-TS 实战开发》构建HTTP请求拦截器
  • Windows 2016 如何关闭自动更新
  • HLSL Complex Shapes With For Loops
  • Linux启动端口,Windows 看是否通
  • 使用 Vue + PDF.js 构建在线 PDF 阅读器(支持目录与缩放)
  • Petalinux最简开发
  • (2)网络学习之堡垒机
  • 如何避免Python爬虫重复抓取相同页面?