由于本人在使用stm32cubemx的freertos时,没有发现队列集配置的选项,因此记录一下如何手动在cubemx生成的freertos中创建和使用队列集。
首先队列集的作用是对多个队列和信号量进行“监听”,不管其中哪一个到来都会使任务退出阻塞。
硬件:正点原子miniV3.0
环境:cubemx、keil5
参考教程:【【正点原子】手把手教你学FreeRTOS实时系统】https://www.bilibili.com/video/BV19g411p7UT?p=47&vd_source=d1e91e9e17a031e2d6e11ed04c3ab205
队列集的使用方法:
- 在freertos.h中配置宏configUSE_QUEUE_SETS为1;
- 创建队列集,队列集创建函数的参数为2表示最多可以放入两个队列(信号量本质也是队列),至于队列的长度不做限制;
- 创建队列或信号量;
- 往队列集中添加队列或信号量,注意将队列添加到队列集中时队列中不能有有效消息。如果是信号量那么信号量应该为0;
- 往队列中发送信息或释放信号量;
- 获取队列集的消息;
这里拿添加二值信号量和队列为例子,注意cubemx生成的二值信号量默认值为1,因此需要在代码中将其初始值修改为0,否则无法对其进行监听。主要代码如下:
freertos.h
#ifndef configUSE_QUEUE_SETS
#define configUSE_QUEUE_SETS 1
#endif
freertos.c:
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "FreeRTOS.h"
#include "task.h"
#include "main.h"
#include "cmsis_os.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "usart.h"
#include "Key.h"
#include "Delay.h"
#include "queue.h"
#include "semphr.h"
/* USER CODE END Includes */
/* Private function prototypes -----------------------------------------------*/
/* USER CODE BEGIN FunctionPrototypes */
QueueSetHandle_t queueset01_handle; //创建队列集句柄
/**
* @brief FreeRTOS initialization
* @param None
* @retval None
*/
void MX_FREERTOS_Init(void) {
/* USER CODE BEGIN Init */
/* Create the semaphores(s) */
/* creation of myBinarySem01 */
myBinarySem01Handle = osSemaphoreNew(1, 0, &myBinarySem01_attributes);
/* Create the queue(s) */
/* creation of myQueue01 */
myQueue01Handle = osMessageQueueNew (2, sizeof(uint8_t), &myQueue01_attributes);
/* Create the thread(s) */
/* creation of myTask01 */
myTask01Handle = osThreadNew(StartTask01, NULL, &myTask01_attributes);
/* creation of myTask03 */
myTask03Handle = osThreadNew(StartTask03, NULL, &myTask03_attributes);
/* USER CODE BEGIN RTOS_THREADS */
/* add threads, ... */
//队列集创建函数的参数为2表示最多可以放入两个队列(信号量本质也是队列),至于队列的长度不做限制
queueset01_handle = xQueueCreateSet( 2 );
if(queueset01_handle != NULL)
myprintf("队列集创建成功\r\n");
xQueueAddToSet(myBinarySem01Handle,queueset01_handle); //添加信号量到队列集
xQueueAddToSet(myQueue01Handle,queueset01_handle); //添加队列到队列集
/* USER CODE END RTOS_THREADS */
/* USER CODE BEGIN RTOS_EVENTS */
/* add events, ... */
/* USER CODE END RTOS_EVENTS */
}
/* USER CODE BEGIN Header_StartTask01 */
/**
* @brief Function implementing the myTask01 thread.
* @param argument: Not used
* @retval None
*/
uint8_t key = 0;
/* USER CODE END Header_StartTask01 */
void StartTask01(void *argument)
{
/* USER CODE BEGIN StartTask01 */
/* Infinite loop */
QueueSetMemberHandle_t member_handle;
uint8_t value;
for(;;)
{
member_handle = xQueueSelectFromSet(queueset01_handle,portMAX_DELAY);
if(member_handle == myQueue01Handle)
{
osMessageQueueGet(member_handle ,&value ,0 , portMAX_DELAY);
myprintf("获取队列数据数据:%d\r\n",value);
}
if(member_handle == myBinarySem01Handle)
{
osSemaphoreAcquire(member_handle,portMAX_DELAY);
myprintf("获取信号量成功\r\n");
}
}
/* USER CODE END StartTask01 */
}
/* USER CODE BEGIN Header_StartTask03 */
/**
* @brief Function implementing the myTask03 thread.
* @param argument: Not used
* @retval None
*/
uint8_t state;
/* USER CODE END Header_StartTask03 */
void StartTask03(void *argument)
{
/* USER CODE BEGIN StartTask03 */
/* Infinite loop */
uint8_t key = 0;
for(;;)
{
key = KEY_Scan(0); //保存返回值,方便后面判断
if(key == KEY0_PRES)
{
state = osMessageQueuePut(myQueue01Handle ,&key ,0 , portMAX_DELAY);
if(state == osOK) myprintf("往队列写入数据成功\r\n");
}
if(key == KEY1_PRES)
{
state = osSemaphoreRelease(myBinarySem01Handle);
if(state == osOK) myprintf("二值信号量释放成功\r\n");
else myprintf("二值信号量释放失败\r\n");
}
osDelay(10);
}
/* USER CODE END StartTask03 */
}
/* Private application code --------------------------------------------------*/
/* USER CODE BEGIN Application */
/* USER CODE END Application */
任务三功能就是按下key0,往队列写数据,按下key1释放二值信号量
任务一功能就是对队列集中的队列和信号量进行监听,有有效值就打印
结果如下: