一.消息队列的概念及应用
消息队列(queue):可以在任务与任务间、中断和任务间传递消息,实现任务接收来自其他任务或中断的不固定的消息
![](https://img-blog.csdnimg.cn/img_convert/34305aea5f384b6db6cd0b8373739c2e.png)
1.1任务需求
1、使用消息队列检测串口输入
2、通过串口发送字符串openled1,openled2,openled3,分别打开板载led1,led2,led3
3、通过串口发送字符串closeled1,closeled2,closeled3,分别关闭板载led1,led2,led3
1.2API
函数原型 | #include “FreeRTOS.h” #include “queue.h” QueueHandle_t xQueueCreate( ①UBaseType_t uxQueueLength, ②UBaseType_t uxItemSize ); |
功能概述 | 创建一个消息队列,并返回消息队列句柄 |
参数 | ①:队列一次可容纳消息的最大长度 ②:队列中每个消息体大小 |
返回值 | NULL:创建失败 Any other value :创建成功,返回消息队列句柄 |
注意事项 | 队列可以用于任务与任务通信,也是用于中断与任务通信 可在调度器开启之前,创建消息队列 |
函数原型 | #include “FreeRTOS.h” #include “queue.h” BaseType_t xQueueSend/xQueueSendToFront/xQueueSendToBack( ① QueueHandle_t xQueue, ②const void * pvItemToQueue, ③ TickType_t xTicksToWait ); |
功能概述 | 在任务中往队列中传入消息 xQueueSend 等价于xQueueSendToBack 入到队尾 xQueueSendToFront 入到队头 |
参数 | ①:消息队列句柄 ②:要发送的消息的地址 ③:阻塞等待时间 |
返回值 | pdPASS:发送成功 errQUEUE_FULL:队列已经满,发送失败 |
注意事项 | None |
函数原型 | #include “FreeRTOS.h” #include “queue.h” BaseType_t xQueueSendFromISR/xQueueSendToFrontFromISR/xQueueSendToBackFromISR ( ① QueueHandle_t xQueue, ②const void * pvItemToQueue, ③ BaseType_t *pxHigherPriorityTaskWoken); |
功能概述 | 在中断中往队列中传入消息 xQueueSendFromISR 等价于xQueueSendToBackFromISR 入到队尾 xQueueSendToFrontFromISR 入到队头 |
参数 | ①:消息队列句柄 ②:要发送的消息的地址 ③:NULL |
返回值 | pdTRUE:发送成功 errQUEUE_FULL:队列已经满,发送失败 |
注意事项 | 调用此函数,会触发上下文切换(当前被中断的任务优先级低于解除阻塞的任务) 在启动调度器之前不能调用此函数 |
函数原型 | #include “FreeRTOS.h” #include “queue.h” BaseType_t xQueueReceive( ①QueueHandle_t xQueue, ②void *pvBuffer, ③TickType_t xTicksToWait ); |
功能概述 | 在任务中读取消息队列消息 |
参数 | ①:消息队列句柄 ②:接收消息的缓冲区 ③:阻塞等待时间 |
返回值 | pdPASS:创建失败 errQUEUE_EMPTY:消息队列为空 |
注意事项 | None |
函数原型 | #include “FreeRTOS.h” #include “queue.h” BaseType_t xQueueReceiveFromISR( ① QueueHandle_t xQueue, ② void *pvBuffer, ③BaseType_t *pxHigherPriorityTaskWoken ); |
功能概述 | 在中断中读取消息队列消息 |
参数 | ①:消息队列句柄 ②:接收消息的缓冲区 ③:NULL |
返回值 | pdPASS:创建失败 pdFAIL:消息队列为空 |
注意事项 | 调用此函数,会触发上下文切换(当前被中断的任务优先级低于解除阻塞的任务) 在启动调度器之前不能调用此函数 |
二.函数应用
STM32CubeMX中FreeRTOS配置Queue消息队列
![](https://img-blog.csdnimg.cn/img_convert/76d883a67e0e46b197d61642ac9fece0.png)
字符串类型char 所以unit8_t。
KEIL 消息队列接收和发送功能
![](https://img-blog.csdnimg.cn/img_convert/a3fd0d638bd648bbabda572a92e406a0.png)
HAL_UART_MspInit USART串口初始化
USART.C
开启中断_HAL_UART_EABLE_IT()
__HAL_UART_ENABLE_IT(__HANDLE__, __INTERRUPT__)
@arg USART_IT_CTS: CTS change interrupt
@arg USART_IT_LBD: LIN Break detection interrupt
@arg USART_IT_TXE: Transmit Data Register empty interrupt
TDR寄存器为空时产生的中断标志位
@arg USART_IT_TC: Transmission complete interrupt
DR寄存器发送完最后一个位时产生的中断标志位。
@arg USART_IT_RXNE: Receive Data register not empty interrupt
@arg USART_IT_IDLE: Idle line detection interrupt
@arg USART_IT_PE: Parity Error interrupt
@arg USART_IT_ERR: Error interrupt(Frame error, noise error, overrun error)
![](https://img-blog.csdnimg.cn/img_convert/6a328b43479e45ae97ee1fa2b7f6ec7c.png)
void HAL_UART_MspDeInit(UART_HandleTypeDef* uartHandle)
{
if(uartHandle->Instance==USART1)
{
/* USER CODE BEGIN USART1_MspDeInit 0 */
/* USER CODE END USART1_MspDeInit 0 */
/* Peripheral clock disable */
__HAL_RCC_USART1_CLK_DISABLE();
/**USART1 GPIO Configuration
PA9 ------> USART1_TX
PA10 ------> USART1_RX
*/
HAL_GPIO_DeInit(GPIOA, GPIO_PIN_9|GPIO_PIN_10);
/* USART1 interrupt Deinit */
HAL_NVIC_DisableIRQ(USART1_IRQn);
/* USER CODE BEGIN USART1_MspDeInit 1 */
//开启中断,中断为接收寄存器不为空
__HAL_UART_ENABLE_IT(uartHandle, UART_IT_RXNE);
/* USER CODE END USART1_MspDeInit 1 */
}
STM32f1xx_it.c
获取 SR 寄存器标志位状态,获取此时的串口状态
__HAL_UART_GET_FLAG (__HANDLE__, __FLAG__)
@arg UART_FLAG_CTS: CTS Change flag (not available for UART4 and UART5).
@arg UART_FLAG_LBD: LIN Break detection flag.
@arg UART_FLAG_TC: Transmission Complete flag.
@arg UART_FLAG_RXNE: Receive data register not empty flag
前文有对该函数说明
BaseType_t xQueueSendFromISR( QueueHandle_t xQueue, const void *pvItemToQueue,
BaseType_t *pxHigherPriorityTaskWoken );
extern osMessageQueueId_t CmdQueueHandle;
void USART1_IRQHandler(void)
{
/* USER CODE BEGIN USART1_IRQn 0 */
uint8_t Data;
//判断接收标志置位
if(__HAL_UART_GET_FLAG(&huart1,UART_FLAG_RXNE)==SET)
{
//读取接收寄存器
//当读取接收寄存器后,UART_FLAG_RXNE自动清除
Data = huart1.Instance ->DR;
//进行入队操作
xQueueSendFromISR(CmdQueueHandle,&Data,NULL);
}
/* USER CODE END USART1_IRQn 0 */
HAL_UART_IRQHandler(&huart1);
/* USER CODE BEGIN USART1_IRQn 1 */
/* USER CODE END USART1_IRQn 1 */
}
freertos.c (实现消息队列的接收)
函数原型 | #include “FreeRTOS.h” #include “queue.h” BaseType_t xQueueReceive( ①QueueHandle_t xQueue, :消息队列句柄 ②void *pvBuffer, 接收消息的缓冲区 ③TickType_t xTicksToWait );阻塞等待时间 |
void Uart_Task(void const * argument)
{
/* USER CODE BEGIN Uart_Task */
/* 创建一个索引*/
uint8_t u8_index;
/* Infinite loop */
for(;;)
{
/*每次读取消息之前,把索引初始化为0;*/
u8_index = 0;
/* 一直等待接收消息,第一个消息应该放在消息缓冲区的第一个元素上 */
if(xQueueReceive(CmdQueueHandle,&CmdBuff[u8_index++],portMAX_DELAY) == pdPASS)
{
while(xQueueReceive(CmdQueueHandle,&CmdBuff[u8_index++],50));
/*保证完整一包的字符串信息*/
CmdBuff[u8_index] = '\0';
printf("%s/r/n",CmdBuff);
}
osDelay(1);
}
/* USER CODE END Uart_Task */
}