消息队列介绍
消息队列可以看作是一个先进先出(FIFO)的数据缓冲区,用于存储和传递消息。消息可以是任意类型的数据,如整数、结构体等。发送者将消息放入队列的尾部,接收者从队列的头部取出消息。这种方式保证了消息的顺序性,即先发送的消息会先被接收。
为什么不使用全局变量
多个任务可能同时访问和修改全局变量,这会导致数据竞争问题。例如,一个任务正在读取全局变量的值,而另一个任务同时在修改这个值,就可能会读取到不一致的数据。
为了保证全局变量的安全访问,需要使用互斥锁等同步机制。但如果使用不当,容易出现死锁等问题,增加了编程的复杂度。
消息队列的使用
创建队列
动态创建
函数原型
QueueHandle_t xQueueCreate(UBaseType_t uxQueueLength,UBaseType_t uxItemSize);
关键词
xQueueCreate
点击查看参数解析
UBaseType_t uxQueueLength:设置消息队列长度;
UBaseType_t uxItemSize:设置消息队列中单个消息的大小;
静态创建
函数原型
QueueHandle_t xQueueCreateStatic(UBaseType_t uxQueueLength,UBaseType_t uxItemSize,uint8_t *pucQueueStorage,StaticQueue_t *pxQueueBuffer);
关键词
xQueueCreateStatic
点击查看参数解析
UBaseType_t uxQueueLength:设置消息队列长度;
UBaseType_t uxItemSize:设置单个消息大小;
uint8_t *pucQueueStorage:传递单个消息的存储结构;
StaticQueue_t *pxQueueBuffer:传递自定义的消息队列;
队列复位
函数原型
BaseType_t xQueueReset(QueueHandle_t pxQueue);
关键词
xQueueReset
将队列恢复为初始状态。
点击查看参数解析
QueueHandle_t pxQueue:队列句柄
删除队列
函数原型
void vQueueDelete( QueueHandle_t xQueue );
关键词
vQueueDelete
只能删除使用动态方法创建的队列,会释放内存。
点击查看参数解析
QueueHandle_t xQueue:队列句柄
写队列
队尾写入
函数原型
BaseType_t xQueueSend( QueueHandle_t xQueue, const void * pvItemToQueue, TickType_t xTicksToWait );
BaseType_t xQueueSendToBack( QueueHandle_t xQueue, const void * pvItemToQueue, TickType_t xTicksToWait );
关键词
xQueueSend
xQueueSendToBack
队满会无法写入,一般使用第一个
点击查看参数解析
QueueHandle_t xQueue:队列句柄;
const void * pvItemToQueue:需要发送到消息队列中的数据;注意为指针
TickType_t xTicksToWait:设置阻塞超时时间,单位为tick。设置成0,可直接返回;设置成portMAX_DELAY,会一直阻塞,直到成功写入数据。
队头写入
函数原型
BaseType_t xQueueSendToFront( QueueHandle_t xQueue, const void * pvItemToQueue, TickType_t xTicksToWait );
关键词
xQueueSendToFront
点击查看参数解析
QueueHandle_t xQueue:队列句柄;
const void * pvItemToQueue:需要发送到消息队列中的数据;注意为指针
TickType_t xTicksToWait:设置阻塞超时时间,单位为tick。设置成0,可直接返回;设置成portMAX_DELAY,会一直阻塞,直到成功写入数据。
中断写入
函数原型
BaseType_t xQueueSendFromISR( QueueHandle_t xQueue, const void *pvItemToQueue, BaseType_t *pxHigherPriorityTaskWoken );
关键词
xQueueSendFromISR
在中断服务程序里将数据发送到消息队列的操作。
点击查看参数解析
QueueHandle_t xQueue:传递消息队列的控制权柄;
const void *pvItemToQueue:传递需要发送的消息;注意为指针
BaseType_t *pxHigherPriorityTaskWoken:若消息入队列时产生一个更高优先级的任务,那么改参数就会被设置成pdTRUE,系统在中断函数结束前会切换任务,去执行更高优先级的任务。(可选)
覆盖队列
函数原型
BaseType_t xQueueOverwrite( QueueHandle_t xQueue, const void *pvItemToQueue, );
关键词
xQueueOverwrite
点击查看参数解析
QueueHandle_t xQueue:传递消息队列的控制权柄;
const void *pvItemToQueue:传递需要发送的消息;注意为指针
读队列
普通读取
函数原型
BaseType_t xQueueReceive( QueueHandle_t xQueue, void * const pvBuffer, TickType_t xTicksToWait );
关键词
xQueueReceive
从队头读取,会删除队列中被读取的元素。成功读取会返回pdTRUE
,否则返回pdFALSE
点击查看参数解析
QueueHandle_t xQueue:队列权柄;
void * const pvBuffer:指向存储消息队列数据的存储空间;注意为指针
TickType_t xTicksToWait:消息队列接收函数的最大阻塞时间。设置成0,可直接返回;设置成portMAX_DELAY,会一直阻塞,直到成功读取数据。
中断读取
函数原型
BaseType_t xQueueReceiveFromISR( QueueHandle_t xQueue, void * const pvBuffer, BaseType_t * const pxHigherPriorityTaskWoken );
关键词
xQueueReceiveFromISR
在中断服务程序里读取消息队列的操作。
点击查看参数解析
QueueHandle_t xQueue:队列权柄;
void * const pvBuffer:指向存储消息队列数据的存储空间;注意为指针
BaseType_t * const pxHigherPriorityTaskWoken:任务在往队列发送信息时,如果队列满,则任务将阻塞在该队列上,
若xQueueReceiveFromISR()函数碰到一个任务,则*pxHigherPriorityTaskWoken=pdTRUE;否则,其值为NULL。
窥探队列
函数原型
BaseType_t xQueuePeek( QueueHandle_t xQueue, void * const pvBuffer, TickType_t xTicksToWait );
关键词
xQueuePeek
点击查看参数解析
QueueHandle_t xQueue:队列权柄;
void * const pvBuffer:指向存储消息队列数据的存储空间;注意为指针
TickType_t xTicksToWait:消息队列窥探函数的最大阻塞时间。设置成0,可直接返回;设置成portMAX_DELAY,会一直阻塞,直到成功窥探数据。
其余函数
查询队列
查询可用数据个数
UBaseType_t uxQueueMessagesWaiting(const QueueHandle_t xQueue);
查询可用空间个数
UBaseType_t uxQueueSpaceAvailable(const QueueHandle_t xQueue);
中断
关键词
+FromISR
可用
写队列(队尾、队头、覆盖)、读队列(普通、窥探)。