基于STM32F4+FREERTOS进行结构体变量的传递
原始参考链接如下↓
Freertos 接收消息队列数据不对,是姿势不正确吗 - STM32H7 - 硬汉嵌入式论坛 - Powered by Discuz!
https://www.armbbs.cn/forum.php?mod=viewthread&tid=111900&highlight=%CF%FB%CF%A2%B6%D3%C1%D0
C 语言关于结构体做参数传递 | 菜鸟教程 https://www.runoob.com/w3cnote/c-the-structure-of-the-parameter.html
由于看到的FREERTOS的例程中关于消息队列的代码,大多数都是传递的一个字节的数值;
而在实际应用中,需要传递的数据类型可以是浮点数,也可以是数组,也可以是uint16数据,所以上述链接的传递结构体指针的思路很符合我的需求。
同时,使用RTOS+消息队列的处理方式,至少有以下两个优点:
1、便于开发,因为各个模块之间是通过消息队列进行数据交互,没有直接耦合,无需像裸机编程一样进行全局变量的引用
2、便于移植,代码复用率高,各个开发者之间沟通成本低
需要注意的点是:
1、将结构体作为指针传递时是4字节,指针传递时用到的局部变量会被释放。
2、printf函数打印float数据时需要使用%f格式字符
变量初始化
查看代码
typedef struct Msg {
uint8_t ucMessageID;
uint16_t usData[2];
uint32_t ulData[2];
float_t test_buf[3];
} MSG_T;
MSG_T g_tMsg; /* 定义一个结构体用于消息队列 */
发送消息队列的代码示例
static void vTaskTaskUserIF(void* pvParameters)
static void vTaskTaskUserIF(void* pvParameters)
{
MSG_T* ptMsg;
uint8_t ucCount = 0;
uint8_t ucKeyCode;
uint8_t pcWriteBuffer[500];
/* 初始化结构体指针 */
ptMsg = &g_tMsg;
/* 初始化数组 */
ptMsg->ucMessageID = 0;
ptMsg->ulData[0] = 0;
ptMsg->usData[0] = 0;
ptMsg->test_buf[0] = 0;
while (1) {
ucKeyCode = bsp_GetKey();
if (ucKeyCode != KEY_NONE) {
switch (ucKeyCode) {
/* K1键按下,向xQueue1发送数据 */
case KEY_DOWN_K1:
ptMsg->ucMessageID++;
ptMsg->ulData[0]++;
ptMsg->test_buf[0]++;
/* 使用消息队列实现指针变量的传递 */
if (xQueueSend(xQueue2, /* 消息队列句柄 */
(void*)&ptMsg, /* 发送结构体指针变量ptMsg的地址 */
(TickType_t)10)
!= pdPASS) {
/* 发送失败,即使等待了10个时钟节拍 */
printf("K1键按下,向xQueue1发送数据失败,即使等待了10个时钟节拍\r\n");
} else {
/* 发送成功 */
printf("K1键按下,向xQueue1发送数据成功\r\n");
}
break;
/* K2键按下,向xQueue2发送数据 */
case KEY_DOWN_K2:
ptMsg->ucMessageID++;
ptMsg->ulData[0]++;
ptMsg->test_buf[0]++;
/* 使用消息队列实现指针变量的传递 */
if (xQueueSend(xQueue2, /* 消息队列句柄 */
(void*)&ptMsg, /* 发送结构体指针变量ptMsg的地址 */
(TickType_t)10)
!= pdPASS) {
/* 发送失败,即使等待了10个时钟节拍 */
printf("K2键按下,向xQueue2发送数据失败,即使等待了10个时钟节拍\r\n");
} else {
/* 发送成功 */
printf("K2键按下,向xQueue2发送数据成功\r\n");
}
break;
/* 其他的键值不处理 */
default:
break;
}
}
vTaskDelay(20);
}
}
接收消息队列的代码
static void vTaskLED(void* pvParameters)
static void vTaskLED(void* pvParameters)
{
MSG_T* ptMsg;
BaseType_t xResult;
const TickType_t xMaxBlockTime = pdMS_TO_TICKS(200); /* 设置最大等待时间为200ms */
while (1) {
xResult = xQueueReceive(xQueue2, /* 消息队列句柄 */
(void*)&ptMsg, /* 这里获取的是结构体的地址 */
(TickType_t)xMaxBlockTime); /* 设置阻塞时间 */
if (xResult == pdPASS) {
/* 成功接收,并通过串口将数据打印出来 */
printf("接收到消息队列数据ptMsg->ucMessageID = %d\r\n", ptMsg->ucMessageID);
printf("接收到消息队列数据ptMsg->ulData[0] = %d\r\n", ptMsg->ulData[0]);
printf("接收到消息队列数据ptMsg->testbuf[0] = %f\r\n", ptMsg->test_buf[0]);
} else {
/* 超时 */
bsp_LedToggle(2);
bsp_LedToggle(3);
}
}
}
分类:
得失集
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)