FreeRTOS队列传输结构体异常求助:为何无法正确接收数据?
FreeRTOS队列发送结构体无法正确接收问题分析
核心问题排查
1. 函数嵌套定义导致任务逻辑异常
你的代码中StartUpdateDisplay任务函数被嵌套定义在Start_Init函数内部,这违反了标准C语法规则,编译器无法将其正确识别为独立的FreeRTOS任务入口函数。这会直接导致:
- 该任务可能未被正确创建,或运行时执行错误代码
- 接收端的
rec变量处于未正确初始化/赋值的状态,出现乱码、异常数值
2. 结构体指针成员的潜在风险
message结构体中的char* name是指针类型:
- 当前代码中
mes.name = "test"指向的是只读存储区的字符串常量,指针地址本身能通过队列传递,但如果后续改为指向栈上的局部字符数组,发送任务挂起或栈空间被覆盖后,接收端的指针会变成野指针,同样会出现乱码问题。
修复方案
第一步:修正函数嵌套问题
将StartUpdateDisplay移到Start_Init外部,作为独立的全局函数,确保FreeRTOS能正确调用它作为任务入口:
typedef struct { int id; char* name; } message; void Start_Init(void *argument) { /* init code for USB_DEVICE */ MX_USB_DEVICE_Init(); message mes; /* USER CODE BEGIN 5 */ /* Infinite loop */ for(;;) { Screen HOME; mes.id=77; mes.name = "test"; SCREEN_INIT(&HOME,7,6,(char**)HOME_SCREEN,HOME_DATLOC,HOME_SEL); vTaskSuspend(ReadCardHandle); vTaskSuspend(WriteCardHandle); vTaskSuspend(HomeHandle); MFRC_INIT(); MFRC_ANTOFF(); OLED_INIT(); OLED_Print(TC); while(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_1)!=0); xQueueSend(DisplayDataHandle,&mes,portMAX_DELAY); //发送测试消息 osDelay(100); vTaskSuspend(NULL); } /* USER CODE END 5 */ } // 独立的任务函数 void StartUpdateDisplay(void *argument) { /* USER CODE BEGIN StartUpdateDisplay */ message rec; /* Infinite loop */ for(;;) { xQueueReceive(DisplayDataHandle, &rec, portMAX_DELAY); //从队列接收 osDelay(1); } /* USER CODE END StartUpdateDisplay */ }
第二步:优化结构体指针成员(可选但推荐)
如果需要传递可变字符串,建议改用固定长度字符数组,彻底避免指针带来的野指针风险:
typedef struct { int id; char name[16]; // 用固定长度数组替代指针 } message; // 发送时复制字符串 strncpy(mes.name, "test", sizeof(mes.name)-1); mes.name[sizeof(mes.name)-1] = '\0'; // 确保字符串以结束符收尾
调试验证要点
- 确认
DisplayDataHandle队列创建时,指定的队列项大小为sizeof(message) - 检查任务创建代码,确认
StartUpdateDisplay已被正确关联为任务入口 - 修复后重新调试,查看
rec.id和rec.name是否能正常接收值
内容的提问来源于stack exchange,提问作者Swiss Gnome
相关产品推荐
相关产品推荐

