1. 队列简介
队列是任务到任务、中断到任务的数据交流的一种机制(消息传递)
假设有一个全局变量a = 0,现有两个任务都在写这个变量a,数据有受损风险。
全局变量的弊端: 数据无保护,导致数据不安全,当多个任务同时对该变量操作时,数据易受损。
1.1 使用队列的情况
写队列:
OSQPost( )
{
// 进入临界区(关中断)
写队列实际操作
// 退出临界区(开中断)
}
读队列:
OSQPend( )
{
// 进入临界区(关中断)
读队列实际操作
// 退出临界区(开中断)
}
- 读写队列做好了保护,防止多任务同时访问冲突;
- 我们只需要直接调用API函数即可,简单易用!
- 中断不可以调用队列接收函数,但是可以调用队列发送函数(中断可以写但不能读)
1.2 UCOSIII队列特点
数据入队出队方式
队列通常采用“先进先出”(FIFO)的数据存储缓冲机制,即先入队的数据会先从队列中被读取,UCOSIII中也可以配置为“后进先出”LIFO方式;
数据传输方式
UCOSIII的队列数据是一个“万能指针”,可以指向任何数据,甚至是函数,所以发送方和接收方必须按照约定好的方式去发送和接收消息,这样才能正常解析接收到的消息
多任务访问
队列不属于某个任务,任何任务和中断都可以向队列发送消息,但是读取消息只能在任务中,不支持中断读取消息
出队阻塞
当任务向一个队列读取消息时,可以指定一个阻塞时间,假设此时当队列没有数据时无法读取
- 若阻塞时间 = 0:死等,一直等到可以队列有数据可以出队为止;
- 若阻塞时间 > 0:等待设定的阻塞时间,若在该时间内还未接收到数据,超时后直接返回不再等待;
注意:入队(发送消息队列)不会阻塞!
2. 队列相关API函数介绍
使用队列的主要流程:创建队列 ->写队列(发送消息到队列) ->读队列(获取消息队列的数据)。
创建消息队列函数
void OSQCreate( OS_Q* p_q,
CPU_CHAR* p_name,
OS_MSG_QTY max_qty,
OS_ERR* p_err )
发送消息到消息队列中函数
void OSQPost( OS_Q* p_q,
void* p_void,
OS_MSG_SIZE msg_size,
OS_OPT opt,
OS_ERR* p_err )
获取消息队列中的消息函数
void * OSQPend ( OS_Q* p_q,
OS_TICK timeout,
OS_OPT opt,
OS_MSG_SIZE* p_msg_size,
CPU_TS* p_ts,
OS_ERR* p_err )
评论区