消息队列创建及运行,参阅安富莱电子demo
static QueueHandle_t xQueue1 = NULL;
static QueueHandle_t xQueue2 = NULL;
typedef struct Msg
{
uint8_t ucMessageID;
uint16_t usData[2];
uint32_t ulData[2];
}MSG_T;
MSG_T g_tMsg; /* 定义一个结构体用于消息队列 */
static void vTaskTaskUserIF(void *pvParameters)
{
MSG_T *ptMsg;
uint8_t ucCount = 0;
uint8_t ucKeyCode;
uint8_t pcWriteBuffer[500];
/* 初始化结构体指针 */
ptMsg = &g_tMsg;
/* 初始化数组 */
ptMsg->ucMessageID = 0;
ptMsg->ulData[0] = 0;
ptMsg->usData[0] = 0;
while(1)
{
ucKeyCode = bsp_GetKey();
if (ucKeyCode != KEY_NONE)
{
switch (ucKeyCode)
{
/* K1键按下 打印任务执行情况 */
case KEY_DOWN_K1:
printf("=================================================\r\n");
printf("任务名 任务状态 优先级 剩余栈 任务序号\r\n");
vTaskList((char *)&pcWriteBuffer);
printf("%s\r\n", pcWriteBuffer);
printf("\r\n任务名 运行计数 使用率\r\n");
vTaskGetRunTimeStats((char *)&pcWriteBuffer);
printf("%s\r\n", pcWriteBuffer);
break;
/* K2键按下,向xQueue1发送数据 */
case KEY_DOWN_K2:
ucCount++;
/* 向消息队列发数据,如果消息队列满了,等待10个时钟节拍 */
if( xQueueSend(xQueue1,
(void *) &ucCount,
(TickType_t)10) != pdPASS )
{
/* 发送失败,即使等待了10个时钟节拍 */
printf("K2键按下,向xQueue1发送数据失败,即使等待了10个时钟节拍\r\n");
}
else
{
/* 发送成功 */
printf("K2键按下,向xQueue1发送数据成功\r\n");
}
break;
/* K3键按下,向xQueue2发送数据 */
case KEY_DOWN_K3:
ptMsg->ucMessageID++;
ptMsg->ulData[0]++;;
ptMsg->usData[0]++;
/* 使用消息队列实现指针变量的传递 */
if(xQueueSend(xQueue2, /* 消息队列句柄 */
(void *) &ptMsg, /* 发送结构体指针变量ptMsg的地址 */
(TickType_t)10) != pdPASS )
{
/* 发送失败,即使等待了10个时钟节拍 */
printf("K3键按下,向xQueue2发送数据失败,即使等待了10个时钟节拍\r\n");
}
else
{
/* 发送成功 */
printf("K3键按下,向xQueue2发送数据成功\r\n");
}
/* 其他的键值不处理 */
default:
break;
}
}
vTaskDelay(20);
}
}
static void vTaskLED(void *pvParameters)
{
MSG_T *ptMsg;
BaseType_t xResult;
const TickType_t xMaxBlockTime = pdMS_TO_TICKS(200); /* 设置最大等待时间为200ms */
while(1)
{
xResult = xQueueReceive(xQueue2, /* 消息队列句柄 */
(void *)&ptMsg, /* 这里获取的是结构体的地址 */
(TickType_t)xMaxBlockTime);/* 设置阻塞时间 */
if(xResult == pdPASS)
{
/* 成功接收,并通过串口将数据打印出来 */
printf("接收到消息队列数据ptMsg->ucMessageID = %d\r\n", ptMsg->ucMessageID);
printf("接收到消息队列数据ptMsg->ulData[0] = %d\r\n", ptMsg->ulData[0]);
printf("接收到消息队列数据ptMsg->usData[0] = %d\r\n", ptMsg->usData[0]);
}
else
{
/* 超时 */
}
}
}
static void vTaskMsgPro(void *pvParameters)
{
BaseType_t xResult;
const TickType_t xMaxBlockTime = pdMS_TO_TICKS(300); /* 设置最大等待时间为300ms */
uint8_t ucQueueMsgValue;
while(1)
{
xResult = xQueueReceive(xQueue1, /* 消息队列句柄 */
(void *)&ucQueueMsgValue, /* 存储接收到的数据到变量ucQueueMsgValue中 */
(TickType_t)xMaxBlockTime);/* 设置阻塞时间 */
if(xResult == pdPASS)
{
/* 成功接收,并通过串口将数据打印出来 */
printf("接收到消息队列数据ucQueueMsgValue = %d\r\n", ucQueueMsgValue);
}
else
{
/* 超时 */
}
}
}
int main(void)
{
/*
在启动调度前,为了防止初始化STM32外设时有中断服务程序执行,这里禁止全局中断(除了NMI和HardFault)。
这样做的好处是:
1. 防止执行的中断服务程序中有FreeRTOS的API函数。
2. 保证系统正常启动,不受别的中断影响。
3. 关于是否关闭全局中断,大家根据自己的实际情况设置即可。
在移植文件port.c中的函数prvStartFirstTask中会重新开启全局中断。通过指令cpsie i开启,__set_PRIMASK(1)
和cpsie i是等效的。
*/
__set_PRIMASK(1);
/* 创建任务 ,具体创建任务参阅上一篇【FreeRTOS 任务】任务创建及运行 */
AppTaskCreate();
/* 创建任务通信机制 */
/* 创建10个uint8_t型消息队列 */
xQueue1 = xQueueCreate(10, sizeof(uint8_t));
if( xQueue1 == 0 )
{
/* 没有创建成功,用户可以在这里加入创建失败的处理机制 */
}
/* 创建10个存储指针变量的消息队列,由于CM3/CM4内核是32位机,一个指针变量占用4个字节 */
xQueue2 = xQueueCreate(10, sizeof(struct Msg *));
if( xQueue2 == 0 )
{
/* 没有创建成功,用户可以在这里加入创建失败的处理机制 */
}
/* 启动调度,开始执行任务 */
vTaskStartScheduler();
/*
如果系统正常启动是不会运行到这里的,运行到这里极有可能是用于定时器任务或者空闲任务的
heap空间不足造成创建失败,此要加大FreeRTOSConfig.h文件中定义的heap大小:
#define configTOTAL_HEAP_SIZE ( ( size_t ) ( 17 * 1024 ) )
*/
while(1);
}
/* 如果程序使用到了硬件中断请使用以下方式 */
static void TIM1_IRQHandler(void)
{
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
g_uiCount++;
/* 向消息队列发数据 */
xQueueSendFromISR(xQueue1,
(void *)&g_uiCount,
&xHigherPriorityTaskWoken);
/* 如果 xHigherPriorityTaskWoken = pdTRUE,那么退出中断后切到当前最高优先级任务执行 */
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}
static void TIM2_IRQHandler(void)
{
MSG_T *ptMsg;
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
/* 初始化结构体指针 */
ptMsg = &g_tMsg;
/* 初始化数组 */
ptMsg->ucMessageID++;
ptMsg->ulData[0]++;
ptMsg->usData[0]++;
/* 向消息队列发数据 */
xQueueSendFromISR(xQueue2,
(void *)&ptMsg,
&xHigherPriorityTaskWoken);
/* 如果 xHigherPriorityTaskWoken = pdTRUE,那么退出中断后切到当前最高优先级任务执行 */
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}
STM32CubeMX 队列创建及运行
以下是普通变量队列创建和运行
注意: STM32CubeMX 生成的代码消息队列目前只能传递普通变量,如果传递结构体或者其它类型变量,最好不使用 cmsis_os.h封装好的API
/* USER CODE BEGIN 4 */
void MessageQTask(void const * argument)
{
/* USER CODE BEGIN 5 */
/* Infinite loop */
osEvent EventMessage;
for(;;)
{
EventMessage = osMessageGet (myMessageQueueIdHandle, 10);
if(EventMessage.status == osEventMessage)
{
printf("MessageGet v : %d\r\n", EventMessage.value.v);
}else{
printf("MessageGet v null\r\n");
}
osDelay(1000);
}
/* USER CODE END 5 */
}
void StartDefaultTask(void const * argument)
{
/* USER CODE BEGIN 5 */
/* Infinite loop */
int32_t count = 0;
uint8_t bits = 1;
for(;;)
{
//HAL_UART_Transmit(&huart1,"StartDefaultTask\r\n",strlen("StartDefaultTask\r\n"),1000);
count++;
if(count == 1)
{
count = 0;
osMessagePut (myMessageQueueIdHandle, bits, 10);
bits = bits + 1;
osMessagePut (myMessageQueueIdHandle, bits, 10);
bits = bits + 1;
osMessagePut (myMessageQueueIdHandle, bits, 10);
bits = bits + 1;
osMessagePut (myMessageQueueIdHandle, bits, 10);
bits = bits + 1;
osMessagePut (myMessageQueueIdHandle, bits, 10);
bits = bits + 1;
osMessagePut (myMessageQueueIdHandle, bits, 10);
bits = bits + 1;
osMessagePut (myMessageQueueIdHandle, bits, 10);
bits = bits + 1;
osMessagePut (myMessageQueueIdHandle, bits, 10);
bits = bits + 1;
osMessagePut (myMessageQueueIdHandle, bits, 10);
bits = bits + 1;
osMessagePut (myMessageQueueIdHandle, bits, 10);
}
osDelay(10);
osThreadSuspend(defaultTaskHandle); //挂起任务
}
/* USER CODE END 5 */
}
int main(void)
{
/* USER CODE BEGIN RTOS_QUEUES */
/* add queues, ... */
/* 参数说明:队列结构体名称, 队列深度, 队列类型 */
osMessageQDef(myMessageQueueName, 10, uint8_t);
/* 参数说明:取定义好的队列结构体地址, 默认NULL */
myMessageQueueIdHandle = osMessageCreate (osMessageQ(myMessageQueueName), NULL)
/* USER CODE END RTOS_QUEUES */
/* USER CODE BEGIN RTOS_THREADS */
/* add threads, ... */
osThreadDef(defaultTask, StartDefaultTask, osPriorityNormal, 0, 128);
defaultTaskHandle = osThreadCreate(osThread(defaultTask), NULL);
osThreadDef(MessageQTask, MessageQTask, osPriorityHigh, 0, 128);
SignalTaskHandle = osThreadCreate(osThread(MessageQTask), NULL);
/* USER CODE END RTOS_THREADS */
/* Start scheduler */
osKernelStart();
}