文章目录[隐藏]
FREERTOS学习笔记三-消息队列
1.实验内容
实验二内容:创建两个动态任务,任务一控制LED的闪烁,任务二用于检测按键。当按键KEY0按下时,任务一被挂起;当按键KEY1被按下时,任务一被取消挂起。
实验三是在实验二的基础上进行修改,增加一个消息队列和两个任务进程;任务二按键检测,当按键被按下时,会发生消息;任务三和任务四负责接收消息。
2.CubeMX的配置
1.1添加两个优先级相同的任务
1.2添加消息队列
消息大小为16,消息格式为无符号的16位
1.3添加调试串口
2.程序编写
2.1printf函数重定向
2.1.1添加头文件
#include "stdio.h"
2.1.2添加重定义函数
int fputc(int ch,FILE *f)
{
HAL_UART_Transmit(&huart1,(uint8_t *)&ch,1,0xFFFF);//hurat1为串口号,根据自己情况进行选择
return ch;
}
2.1.3勾选use microlib
2.2按键任务编写
void StartKEY_Task(void const * argument)
{
/* USER CODE BEGIN StartKEY_Task */
/* Infinite loop */
uint16_t ProducerValue = 1;
for(;;)
{
if(HAL_GPIO_ReadPin(KEY0_GPIO_Port,KEY0_Pin) == 0)
{
osDelay(10);//消抖
if(HAL_GPIO_ReadPin(KEY0_GPIO_Port,KEY0_Pin) == 0)
{
if(osMessagePut(myQueue01Handle,ProducerValue,0) != osOK)//0表示发送完等待时间
{
osThreadSuspendAll();
printf("发送失败\r\n");
osThreadResumeAll();
}
else
{
osThreadSuspendAll();
printf("发送成功\r\n");
ProducerValue++;
osThreadResumeAll();
}
}
}
while(HAL_GPIO_ReadPin(KEY0_GPIO_Port,KEY0_Pin) == 0)//等待按键释放,防止连续发送
{
osDelay(10);
}
osDelay(1);
}
/* USER CODE END StartKEY_Task */
}
2.3任务3编写
void StartTask03(void const * argument)
{
/* USER CODE BEGIN StartTask03 */
/* Infinite loop */
osEvent event;
for(;;)
{
event = osMessageGet(myQueue01Handle,osWaitForever);//一直等待消息
if(event.status == osEventMessage)
{
printf("任务3数据:%d\r\n",event.value.v);
}
osDelay(1);
}
/* USER CODE END StartTask03 */
}
2.4任务4编写
void StartTask04(void const * argument)
{
/* USER CODE BEGIN StartTask04 */
/* Infinite loop */
osEvent event;
for(;;)
{
event = osMessageGet(myQueue01Handle,osWaitForever);//一直等待消息
if(event.status == osEventMessage)
{
printf("任务4数据:%d\r\n",event.value.v);
}
osDelay(1);
osDelay(1);
}
/* USER CODE END StartTask04 */
}
3.运行结果1
任务3和任务4争抢时间片接收消息
4.提高任务三的优先级
5.调试结果2
因为任务3的优先级较高,当任务3是采用osMessageGet()函数接收消息,在其接到之后会删除消息内容,然后任务4不会接收到消息。
6.更改接收函数
将任务3的osMessageGet()更换为osMessagePeek()接收函数
同时在库函数中添加
event.value.v = 0;
因为这个函数是处理32位的数据,而本次实验采用的数据为16位,该函数处理数据时会将这16位数据存在在32位数据的低16位,而将高的十六位用1补充,这会导致输出结果错误(输出-65535),所以添加这句能够使该函数在处理16位数据时,将32位的高16位置为0.
7.调试结果3
由于osMessagePeek()函数接收消息后,不会删除消息,那么任务4就可以接收到消息。
8.关键函数
发送消息
osMessagePut(myQueue01Handle,ProducerValue,0)
删除消息的接收消息
event = osMessageGet(myQueue01Handle,osWaitForever);
不删除消息的接收消息
event = osMessagePeek(myQueue01Handle,osWaitForever);
版权声明:本文为CSDN博主「ViTO_2001」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_46384359/article/details/122775860
暂无评论