FREERTOS学习笔记三-消息队列

FREERTOS学习笔记三-消息队列

1.实验内容

​ 实验二内容:创建两个动态任务,任务一控制LED的闪烁,任务二用于检测按键。当按键KEY0按下时,任务一被挂起;当按键KEY1被按下时,任务一被取消挂起。

​ 实验三是在实验二的基础上进行修改,增加一个消息队列和两个任务进程;任务二按键检测,当按键被按下时,会发生消息;任务三和任务四负责接收消息。

2.CubeMX的配置

1.1添加两个优先级相同的任务

FREERTOS学习笔记三-消息队列_第1张图片

1.2添加消息队列

消息大小为16,消息格式为无符号的16位

FREERTOS学习笔记三-消息队列_第2张图片

1.3添加调试串口

FREERTOS学习笔记三-消息队列_第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

FREERTOS学习笔记三-消息队列_第4张图片

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争抢时间片接收消息

FREERTOS学习笔记三-消息队列_第5张图片

4.提高任务三的优先级

FREERTOS学习笔记三-消息队列_第6张图片

5.调试结果2

​ 因为任务3的优先级较高,当任务3是采用osMessageGet()函数接收消息,在其接到之后会删除消息内容,然后任务4不会接收到消息。

FREERTOS学习笔记三-消息队列_第7张图片

6.更改接收函数

​ 将任务3的osMessageGet()更换为osMessagePeek()接收函数

FREERTOS学习笔记三-消息队列_第8张图片

​ 同时在库函数中添加

event.value.v = 0;

因为这个函数是处理32位的数据,而本次实验采用的数据为16位,该函数处理数据时会将这16位数据存在在32位数据的低16位,而将高的十六位用1补充,这会导致输出结果错误(输出-65535),所以添加这句能够使该函数在处理16位数据时,将32位的高16位置为0.

FREERTOS学习笔记三-消息队列_第9张图片

7.调试结果3

​ 由于osMessagePeek()函数接收消息后,不会删除消息,那么任务4就可以接收到消息。

FREERTOS学习笔记三-消息队列_第10张图片

8.关键函数

发送消息

osMessagePut(myQueue01Handle,ProducerValue,0)

删除消息的接收消息

event = osMessageGet(myQueue01Handle,osWaitForever);

不删除消息的接收消息

event = osMessagePeek(myQueue01Handle,osWaitForever);

你可能感兴趣的:(FREERTOS学习笔记,单片机,stm32,c语言,freertos)