- 简述:
- 队列又称消息队列,是一种常用于任务间通信,队列可以在任务与任务间、中断和任务间传递信息;
- 实现了任务接收来自其它任务或者中断的不固定长度的消息
- 当队列中消息为空时,读取消息的任务将被阻塞,可指定阻塞的时间timeout
- 当队列中有消息时,被阻塞的任务会被唤醒并处理新消息
- 等待时间超过指定的阻塞时间,即队列中尚无有效数据,任务也会自动从阻塞态转为就绪态
- 消息队列是一种异步的通信方式
- 特性:
- 读消息队列支持超时机制
- 可以允许不同长度的任意类型数据(引用方式是指针传递而不是值传递,指向数据的指针,表明数据长度的变量和记录消息发布时刻的时间戳,指针指向的可以是一个数据区域或一个函数)
- 一个任务能够从任意一个消息队列接收和发送消息
- 多个任务能够从同一个消息队列接收和发送消息
- 构成:
- 事件控制块
- 消息队列
- 消息
- 消息队列函数:
- OS_MsgPoolInit():初始化消息池
- OSQCreate():创建一个消息队列
- OSQDel():删除一个消息队列
- OSQFlush():清空一个消息队列
- OSQPend():等待消息队列
- OSQPendAbort():取消等待消息队列
- OSQPost():向消息队列发送一条消息
- 常用函数:创建、发送、等待接收这三个函数;
- 实现例程:
- 创建消息队列:
//创建消息队列 OSQCreate((OS_Q *)&queue, //指向消息队列的指针 (CPU_CHAR *)"Queue for test", //队列的名字 (OS_MSG_QTY )20, //最多可存放消息的数目 (OS_ERR *)&err); //返回错误类型
- 发送
/************************************************** * 函数名:static void AppTaskLed(void *p_arg) * 描述 :led应用 * 输入 :无 * 输出 :无 * 返回 :无 * 调用 :内部调用 **************************************************/ static void AppTaskLed(void *p_arg) { OS_ERR err; (void)p_arg; for(;;) { HAL_GPIO_WritePin(GPIOB,GPIO_PIN_0,GPIO_PIN_SET); //PB1置1 HAL_GPIO_WritePin(GPIOB,GPIO_PIN_1,GPIO_PIN_SET); //PB0置1 //发布消息到消息队列queue OSQPost((OS_Q *)&queue, //消息变量指针 (void *)"两个灯灭了+++", //数据的指针,将内存块首地址通过队列 发送出去 (OS_MSG_SIZE )sizeof("两个灯灭了+++"), //数据字节大小 (OS_OPT )OS_OPT_POST_FIFO | OS_OPT_POST_ALL, //先进先出和发布给全部任务的形式 (OS_ERR *)&err); //返回错误类型 OSTimeDly ( 500,OS_OPT_TIME_DLY,&err); HAL_GPIO_WritePin(GPIOB,GPIO_PIN_0,GPIO_PIN_RESET); //PB1置0 HAL_GPIO_WritePin(GPIOB,GPIO_PIN_1,GPIO_PIN_RESET); //PB0置0 //发布消息到消息队列queue OSQPost((OS_Q *)&queue, //消息变量指针 (void *)"两个灯亮了---", //数据的指针,将内存块首地址通过队列 发送出去 (OS_MSG_SIZE )sizeof("两个灯亮了---"), //数据字节大小 (OS_OPT )OS_OPT_POST_FIFO | OS_OPT_POST_ALL, //先进先出和发布给全部任务的形式 (OS_ERR *)&err); //返回错误类型 OSTimeDly ( 500,OS_OPT_TIME_DLY,&err); } }
- 接收
/************************************************** * 函数名:static void AppTaskUsart(void *p_arg) * 描述 :串口打印 * 输入 :无 * 输出 :无 * 返回 :无 * 调用 :内部调用 **************************************************/ static void AppTaskUsart(void *p_arg) { OS_ERR err; OS_MSG_SIZE msg_size; char * pMsg; (void)p_arg; for(;;) { pMsg = OSQPend((OS_Q *)&queue, //消息变量指针 (OS_TICK )0, //等待时长为无限 (OS_OPT )OS_OPT_PEND_BLOCKING,//如果没有获取到信号量就等待 (OS_MSG_SIZE *)&msg_size, //获取消息的字节大小 (CPU_TS *)0, //获取任务发送时的时间戳 (OS_ERR *)&err); //返回错误类型 if(err == OS_ERR_NONE) //消息接收成功 { printf("\r\n接收消息的长度:%d字节,内容:%s\r\n", msg_size, pMsg); } } }
- 创建消息队列:
- 下载验证
- 略
- 总结
- 消息队列指针传递,传送的是首地址
- 参考资料:
- 正点原子《STM32F767 UCOS开发手册》
- 野火《uC/OS-III内核应用与开发》
- 《嵌入式实时操作系统 uC/OS-III原理及应用(第二版)》
- 官方源码
- 硬件平台:
- 正点原子阿波罗F767
- 软件平台:
- MDK5.2.5
- 库版本:
- TM32Cube_FW_F7_V1.4.0
- uC/OS-III版本
- UCOSIII 3.04