一。消息队列的概念及应用
消息队列定义
FreeRTOS消息队列介绍
FreeRTOS消息队列工作原理
1.消息队列的作用
消息队列(queue),可以在任务与任务间、中断和任务间传递消息 实现任务接收来自其他任务或中断的不固定长度的消息
2.FreeRTOS消息队列介绍
中断或者任务给任务发消息
3.FreeRTOS消息队列工作原理
二。实验:消息队列函数应用《在CPU的利用率的基础上创建》
功能需求
API
1.功能需求
2.API
(1)xQueueCreate()
(2)xQueueSend()
(3)xQueueSendFromISR()
(4) xQueueReceive()
(5) xQueueReceiveFromISR()
3.STM32CubeMX功能配置
(1)led端口配置
(2)Usart1中断配置(中断使能)
(3)创建消息队列
注意:上面那个图应该是8字节,因为一个字符就是8字节
补充:原理解释:
由上述原理图得(第一个图),USART中断接受到的数据的控制为为RXNE。
HAL库指南图得(第二个图),HAL库中有专门使能串口中断的函数。
4.消息队列接收和发送功能开发
步骤:
(1)串口中断使能
//¿ªÆôÖÐ¶Ï ÖжÏԴΪ½ÓÊռĴæÆ÷²»Îª¿Õ
__HAL_UART_ENABLE_IT(uartHandle,UART_IT_RXNE);
(2)中断服务入队操作
在上面导入数据
extern osMessageQId CmdQueueHandle;
uint8_t u8Data;
//ÅжϽÓÊÕ±êÖ¾ÖÃλ
if(__HAL_UART_GET_FLAG(&huart1,UART_FLAG_RXNE) == SET){
//¶ÁÈ¡½ÓÊռĴæÆ÷
u8Data = huart1.Instance->DR;
//½øÐÐÈë¶Ó²Ù×÷
xQueueSendFromISR(CmdQueueHandle,&u8Data,NULL);
}
(3)出队操作
《1》电脑上输入字符串,串口上显示同样的字符串
uint8_t u8CmdBuff[20];//全局变量
//每次读取信息之前,首先初始化为0
u8Index = 0;
//一直等待接受消息,第一个消息应该放在消息缓存区的第一个元素上
if(xQueueReceive(CmdQueueHandle,&u8CmdBuff[u8Index++],portMAX_DELAY)==pdPASS){
while(xQueueReceive(CmdQueueHandle,&u8CmdBuff[u8Index++],50)){}
u8CmdBuff[u8Index]='\0';//保证完整的字符串
printf("%s\r\n",u8CmdBuff);
}
结果:
(3)字符串命令操作灯的亮灭
《1》使用字符串数组储存命令
#define LED_NUM 4
uint8_t *OpenString[LED_NUM] = {
"openled6",
"openled7",
"openled8",
"openled9",
};
uint8_t *CloseString[LED_NUM] = {
"closeled6",
"closeled7",
"closeled8",
"closeled9",
};
GPIO_TypeDef * LedPort[LED_NUM] = {
Led6_GPIO_Port,
Led7_GPIO_Port,
Led8_GPIO_Port,
Led9_GPIO_Port
};
uint16_t LedPin[LED_NUM] ={
Led6_Pin,
Led7_Pin,
Led8_Pin,
Led9_Pin
};
《2》写一个函数,目标是比较字符串命令与输入数据的比较,比较通过执行指定的命令。
void vParseString(uint8_t *buff){
//与open灯命令比较
uint8_t i;
for(i=0;i<LED_NUM;i++){
if(strcmp((char const*)buff,(char const*)OpenString[i]) == 0){
HAL_GPIO_WritePin(LedPort[i], LedPin[i], GPIO_PIN_RESET);
printf("Cmd is %s\n",OpenString[i]);
return;
}
}
//与close灯命令比较
for(i=0;i<LED_NUM;i++){
if(strcmp((char const*)buff,(char const*)CloseString[i]) == 0){
HAL_GPIO_WritePin(LedPort[i], LedPin[i], GPIO_PIN_SET);
printf("Cmd is %s\n",CloseString[i]);
return;
}
}
}
《3》在任务主函数下调用函数,注意:每回合结束要把缓存区(自己设置的字符串)清零
//比较命令
vParseString(u8CmdBuff);
//清空字符串
memset(u8CmdBuff,0,20);
结果:输入openled6,打开led6灯;输入closeled6,关闭led6灯。
三。消息队列实现原理
1.消息队列控制块
2.消息队列创建
3.消息队列删除
4.消息队列在任务中发送
5.消息队列在中断中发送
6.消息队列在任务中接收
7.消息队列在中断中接收