【STM32F407+CUBEMX+FreeRTOS+lwIP之UDP记录】

2024-05-02 16:20

本文主要是介绍【STM32F407+CUBEMX+FreeRTOS+lwIP之UDP记录】,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

STM32F407+CUBEMX+FreeRTOS+lwIP之UDP记录

  • 基本信息
  • cubemx配置
    • GPIO
    • NVIC
    • RCC
    • SYS
    • ETH
    • FREERTOS
    • lwIP
  • UDP(SOCKET)
    • 效果
  • UDP广播(SOCKET)
    • 效果
  • UDP组播(SOCKET)
    • cubemx注意以下
    • ethernetif.c
    • 效果
  • 可参考正点原子和野火的手册

基本信息

正点原子F407探索者开发板
cubemx v6.10.0
STM32Cube FM_f4 v1.28.0
8720A

cubemx配置

GPIO

在这里插入图片描述

NVIC

在这里插入图片描述
在这里插入图片描述

RCC

在这里插入图片描述

SYS

在这里插入图片描述

ETH

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

FREERTOS

这个按需配置
在这里插入图片描述

lwIP

这个按需配置

8720A可以选下图中这个,其他为适配的可以生成代码后自己修改

UDP(SOCKET)

本地端口是本地对外开放的端口
远程端口目标IP的端口

一些定义

#include <lwip/sockets.h>
#include "lwip/opt.h"
#include "lwip/sys.h"
#include "lwip/api.h"
#include "lwip/udp.h"
#include "queue.h"osThreadId_t led_TaskHandle;
const osThreadAttr_t led_Task_attributes = {.name = "led_Task",.stack_size = 128 * 4,.priority = (osPriority_t) (osPriorityNormal-10),
};
void Start_led_Task(void *argument);#ifdef lwip_socket_udp_base
osThreadId_t socket_udp_TaskHandle;
const osThreadAttr_t socket_udp_Task_attributes = {.name = "socket_udp_Task",.stack_size = 128 * 8,.priority = (osPriority_t) (osPriorityNormal-9),
};
void Start_socket_udp_Task(void *argument);
#define LWIP_DEMO_PORT 8081
#define LWIP_DEMO_RX_BUFSIZE         200    /* 最大接收数据长度 */
//#define IP_ADDR   "192.168.123.92"		/* 单播 一对一*/
socklen_t sock_fd;                     /* 定义一个Socket接口 */
struct sockaddr_in local_info;         /* 定义Socket地址信息结构体 */
/* 接收数据缓冲区 */
uint8_t g_lwip_demo_recvbuf[LWIP_DEMO_RX_BUFSIZE];osThreadId_t lwip_recv_TaskHandle;
const osThreadAttr_t lwip_recv_Task_attributes = {.name = "lwip_recv_Task",.stack_size = 128 * 4,.priority = (osPriority_t) (osPriorityNormal-9),
};
/* 显示消息队列的数量 */
#define DISPLAYMSG_Q_NUM    20              /* 显示消息队列的数量 */
QueueHandle_t g_display_queue;              /* 显示消息队列句柄 */

创建led任务

led_TaskHandle = osThreadNew(Start_led_Task, NULL, &led_Task_attributes);

lwIP初始化后UDP、接收、队列

void StartDefaultTask(void *argument)
{/* init code for LWIP */MX_LWIP_Init();/* USER CODE BEGIN StartDefaultTask */taskENTER_CRITICAL();           /* 进入临界区 */socket_udp_TaskHandle = osThreadNew(Start_socket_udp_Task, NULL, &socket_udp_Task_attributes);lwip_recv_TaskHandle = osThreadNew(lwip_recv_Task, NULL, &lwip_recv_Task_attributes);g_display_queue = xQueueCreate(DISPLAYMSG_Q_NUM,200);/* 创建消息Message_Queue,队列项长度是200长度 */taskEXIT_CRITICAL();            /* 退出临界区 *//* Infinite loop */for(;;){osDelay(1);	//ticks}/* USER CODE END StartDefaultTask */
}

udp配置

void Start_socket_udp_Task(void *argument){/* 发送数据内容 */char g_lwip_demo_sendbuf[] = "ALIENTEK DATA \r\n";memset(&local_info, 0, sizeof(struct sockaddr_in)); /* 将服务器地址清空 */local_info.sin_len = sizeof(local_info);local_info.sin_family = AF_INET;                    /* IPv4地址 */local_info.sin_port = htons(LWIP_DEMO_PORT);        /* 设置端口号 */local_info.sin_addr.s_addr = htons(INADDR_ANY);     /* 设置本地IP地址 */sock_fd = socket(AF_INET,SOCK_DGRAM,0);/* 建立一个新的socket连接 */if (sock_fd < 0){printf("socket failed!\n");}int ret = bind(sock_fd,(struct sockaddr *)&local_info, sizeof(struct sockaddr_in));/* 建立绑定 */if (ret < 0){printf(" bind error!\n ");}while(1){local_info.sin_addr.s_addr = inet_addr(IP_ADDR);                /* 需要发送的远程IP地址 */sendto(sock_fd,                                         /* scoket */(char *)g_lwip_demo_sendbuf,                        /* 发送的数据 */sizeof(g_lwip_demo_sendbuf), 0,                     /* 发送的数据大小 */(struct sockaddr *)&local_info,                   /* 接收端地址信息 */ sizeof(local_info));                              /* 接收端地址信息大小 */vTaskDelay(400);LL_GPIO_TogglePin(LED1_GPIO_Port,LED1_Pin);}
}

将从队列收到的消息打印出来

void Start_led_Task(void *argument){uint8_t buffer[200];while(1){LL_GPIO_TogglePin(LED0_GPIO_Port,LED0_Pin);vTaskDelay(500);if (xQueueReceive(g_display_queue,&buffer,portMAX_DELAY)){printf("%s\n",buffer);memset(buffer,0,200);       /* 清除缓冲区 */}}
}
void lwip_recv_Task(void *argument){BaseType_t lwip_err;struct sockaddr_in sender;/*存放发送方信息*/int sender_len = sizeof(sender);/*发送方信息长度*/while(1){memset(g_lwip_demo_recvbuf, 0, sizeof(g_lwip_demo_recvbuf));
//		recv(sock_fd, (void *)g_lwip_demo_recvbuf, sizeof(g_lwip_demo_recvbuf), 0);/*这个只有通信数据*/recvfrom(sock_fd, (void *)g_lwip_demo_recvbuf, sizeof(g_lwip_demo_recvbuf), 0,(struct sockaddr*)&sender,(socklen_t *)&sender_len);/*这个只有通信数据、还有发送方信息*/lwip_err = xQueueSend(g_display_queue,&g_lwip_demo_recvbuf,0);if (lwip_err == errQUEUE_FULL){printf("队列Key_Queue已满,数据发送失败!\r\n");}else{/*IP*/printf("%s %d \n", inet_ntoa(sender.sin_addr), ntohs(sender.sin_port));/*打印发送放IP和端口*/}vTaskDelay(10);}
}

效果

在这里插入图片描述

UDP广播(SOCKET)

#define IP_ADDR   "192.168.123.255"		/* 广播所有设备255.255.255.255 通常只在本地网络中使用*/

效果

在这里插入图片描述
在这里插入图片描述

UDP组播(SOCKET)

添加一些定义

/* 组播D类IP:224.0.0.0至239.255.255.255 */
/* 多播/组播 IP 地址 */
#define GROUP_IP "224.0.1.0"
/* 多播信息 */
struct ip_mreq_t
{struct ip_mreq mreq;            /* 多播信息控制块 */socklen_t mreq_len;             /* 多播信息长度 */
};
struct ip_mreq_t mreq_info;

bind后加这个

/*组播 LWIP_IGMP为1*/mreq_info.mreq.imr_multiaddr.s_addr = inet_addr(GROUP_IP);     /* 多播组 IP 地址设置 */mreq_info.mreq.imr_interface.s_addr = htonl(INADDR_ANY);       /* 待加入多播组的 IP 地址 */mreq_info.mreq_len = sizeof(struct ip_mreq);/* 添加多播组成员(该语句之前,socket 只与 某单播IP地址相关联 执行该语句后 将与多播地址相关联) */ret = setsockopt(sock_fd,IPPROTO_IP,IP_ADD_MEMBERSHIP,&mreq_info.mreq,mreq_info.mreq_len);if (ret < 0){printf("setsockopt failed !");}else{printf("setsockopt success\n");}

切到组播IP,发送数据

local_info.sin_addr.s_addr = inet_addr(GROUP_IP); /* 组播ip */
sendto(sock_fd,                                         /* scoket */(char *)g_lwip_demo_sendbuf,                        /* 发送的数据 */sizeof(g_lwip_demo_sendbuf), 0,                     /* 发送的数据大小 */(struct sockaddr *)&local_info,                   /* 接收端地址信息 */ sizeof(local_info));                              /* 接收端地址信息大小 */vTaskDelay(400);LL_GPIO_TogglePin(LED1_GPIO_Port,LED1_Pin);

cubemx注意以下

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

ethernetif.c

netif初始化前添加

netif->flags |=NETIF_FLAG_IGMP;/*组播*/

PHY初始化前添加

HAL_ETH_GetMACFilterConfig(&heth,&g_eth_macfilterconfig_handler);g_eth_macfilterconfig_handler.ReceiveAllMode = ENABLE;g_eth_macfilterconfig_handler.PassAllMulticast =ENABLE;HAL_ETH_SetMACFilterConfig(&heth,&g_eth_macfilterconfig_handler);

这个定义到外面

	ETH_MACFilterConfigTypeDef g_eth_macfilterconfig_handler;

效果

在这里插入图片描述

可参考正点原子和野火的手册

这篇关于【STM32F407+CUBEMX+FreeRTOS+lwIP之UDP记录】的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/954664

相关文章

Python MySQL如何通过Binlog获取变更记录恢复数据

《PythonMySQL如何通过Binlog获取变更记录恢复数据》本文介绍了如何使用Python和pymysqlreplication库通过MySQL的二进制日志(Binlog)获取数据库的变更记录... 目录python mysql通过Binlog获取变更记录恢复数据1.安装pymysqlreplicat

Servlet中配置和使用过滤器的步骤记录

《Servlet中配置和使用过滤器的步骤记录》:本文主要介绍在Servlet中配置和使用过滤器的方法,包括创建过滤器类、配置过滤器以及在Web应用中使用过滤器等步骤,文中通过代码介绍的非常详细,需... 目录创建过滤器类配置过滤器使用过滤器总结在Servlet中配置和使用过滤器主要包括创建过滤器类、配置过滤

正则表达式高级应用与性能优化记录

《正则表达式高级应用与性能优化记录》本文介绍了正则表达式的高级应用和性能优化技巧,包括文本拆分、合并、XML/HTML解析、数据分析、以及性能优化方法,通过这些技巧,可以更高效地利用正则表达式进行复杂... 目录第6章:正则表达式的高级应用6.1 模式匹配与文本处理6.1.1 文本拆分6.1.2 文本合并6

python与QT联合的详细步骤记录

《python与QT联合的详细步骤记录》:本文主要介绍python与QT联合的详细步骤,文章还展示了如何在Python中调用QT的.ui文件来实现GUI界面,并介绍了多窗口的应用,文中通过代码介绍... 目录一、文章简介二、安装pyqt5三、GUI页面设计四、python的使用python文件创建pytho

Node.js学习记录(二)

目录 一、express 1、初识express 2、安装express 3、创建并启动web服务器 4、监听 GET&POST 请求、响应内容给客户端 5、获取URL中携带的查询参数 6、获取URL中动态参数 7、静态资源托管 二、工具nodemon 三、express路由 1、express中路由 2、路由的匹配 3、路由模块化 4、路由模块添加前缀 四、中间件

记录每次更新到仓库 —— Git 学习笔记 10

记录每次更新到仓库 文章目录 文件的状态三个区域检查当前文件状态跟踪新文件取消跟踪(un-tracking)文件重新跟踪(re-tracking)文件暂存已修改文件忽略某些文件查看已暂存和未暂存的修改提交更新跳过暂存区删除文件移动文件参考资料 咱们接着很多天以前的 取得Git仓库 这篇文章继续说。 文件的状态 不管是通过哪种方法,现在我们已经有了一个仓库,并从这个仓

FreeRTOS-基本介绍和移植STM32

FreeRTOS-基本介绍和STM32移植 一、裸机开发和操作系统开发介绍二、任务调度和任务状态介绍2.1 任务调度2.1.1 抢占式调度2.1.2 时间片调度 2.2 任务状态 三、FreeRTOS源码和移植STM323.1 FreeRTOS源码3.2 FreeRTOS移植STM323.2.1 代码移植3.2.2 时钟中断配置 一、裸机开发和操作系统开发介绍 裸机:前后台系

学习记录:js算法(二十八):删除排序链表中的重复元素、删除排序链表中的重复元素II

文章目录 删除排序链表中的重复元素我的思路解法一:循环解法二:递归 网上思路 删除排序链表中的重复元素 II我的思路网上思路 总结 删除排序链表中的重复元素 给定一个已排序的链表的头 head , 删除所有重复的元素,使每个元素只出现一次 。返回 已排序的链表 。 图一 图二 示例 1:(图一)输入:head = [1,1,2]输出:[1,2]示例 2:(图

FreeRTOS内部机制学习03(事件组内部机制)

文章目录 事件组使用的场景事件组的核心以及Set事件API做的事情事件组的特殊之处事件组为什么不关闭中断xEventGroupSetBitsFromISR内部是怎么做的? 事件组使用的场景 学校组织秋游,组长在等待: 张三:我到了 李四:我到了 王五:我到了 组长说:好,大家都到齐了,出发! 秋游回来第二天就要提交一篇心得报告,组长在焦急等待:张三、李四、王五谁先写好就交谁的

FreeRTOS学习笔记(六)队列

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言一、队列的基本内容1.1 队列的引入1.2 FreeRTOS 队列的功能与作用1.3 队列的结构体1.4 队列的使用流程 二、相关API详解2.1 xQueueCreate2.2 xQueueSend2.3 xQueueReceive2.4 xQueueSendFromISR2.5 xQueueRecei