STM32 HAL库 Freertos队列使用解析

打印 上一主题 下一主题

主题 1742|帖子 1742|积分 5226

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

x
在基于 STM32F407 HAL 库和 FreeRTOS 的开辟中,队列是一种紧张的任务间通信机制,它答应任务之间安全地传递数据。下面将详细解析如何使用 FreeRTOS 的队列。
1. 队列的基本概念

队列是一种先进先出(FIFO)的数据布局,在 FreeRTOS 中,队列可以用来在任务之间传递数据。队列中的每个数据项都有固定的大小,并且可以存储多个数据项。
2. 配置开辟环境

起首,你需要使用 STM32CubeMX 配置好 STM32F407 的项目,并启用 FreeRTOS。步调如下:

  • 打开 STM32CubeMX,选择 STM32F407 芯片。
  • 配置时钟、调试接口等基本设置。
  • 在 “Middleware” -> “RTOS” 中选择 FreeRTOS,并进行必要的配置。
  • 天生代码并导入到 Keil MDK 中。
3. 队列的创建与使用示例

以下是一个基于 STM32F407 HAL 库和 FreeRTOS 的队列使用示例代码:
stm32f407-freertos-queue基于STM32F407 HAL库和FreeRTOS的队列使用示例代码
天生 main.c
  1. #include "main.h"
  2. #include "stm32f4xx_hal.h"
  3. #include "cmsis_os.h"
  4. // 队列句柄
  5. osMessageQId myQueueHandle;
  6. // 发送任务函数
  7. void SenderTask(void const * argument)
  8. {
  9.     uint32_t data = 0;
  10.     for(;;)
  11.     {
  12.         // 发送数据到队列
  13.         if(osMessagePut(myQueueHandle, data, osWaitForever) == osOK)
  14.         {
  15.             HAL_UART_Transmit(&huart1, (uint8_t *)"Data sent to queue!\r\n", 20, 100);
  16.             data++;
  17.         }
  18.         osDelay(1000); // 每隔1秒发送一次数据
  19.     }
  20. }
  21. // 接收任务函数
  22. void ReceiverTask(void const * argument)
  23. {
  24.     osEvent event;
  25.     for(;;)
  26.     {
  27.         // 从队列中接收数据
  28.         event = osMessageGet(myQueueHandle, osWaitForever);
  29.         if(event.status == osEventMessage)
  30.         {
  31.             uint32_t receivedData = event.value.v;
  32.             char buffer[50];
  33.             sprintf(buffer, "Received data: %lu\r\n", receivedData);
  34.             HAL_UART_Transmit(&huart1, (uint8_t *)buffer, strlen(buffer), 100);
  35.         }
  36.     }
  37. }
  38. void SystemClock_Config(void);
  39. static void MX_GPIO_Init(void);
  40. static void MX_USART1_UART_Init(void);
  41. static void MX_FREERTOS_Init(void);
  42. int main(void)
  43. {
  44.     HAL_Init();
  45.     SystemClock_Config();
  46.     MX_GPIO_Init();
  47.     MX_USART1_UART_Init();
  48.     MX_FREERTOS_Init();
  49.     /* 启动调度器 */
  50.     osKernelStart();
  51.     while (1)
  52.     {
  53.         // 主循环一般为空
  54.     }
  55. }
  56. void SystemClock_Config(void)
  57. {
  58.     RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  59.     RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
  60.     /** 初始化RCC振荡器
  61.     */
  62.     RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  63.     RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  64.     RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  65.     RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  66.     RCC_OscInitStruct.PLL.PLLM = 8;
  67.     RCC_OscInitStruct.PLL.PLLN = 336;
  68.     RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
  69.     RCC_OscInitStruct.PLL.PLLQ = 7;
  70.     if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  71.     {
  72.         Error_Handler();
  73.     }
  74.     /** 初始化RCC时钟
  75.     */
  76.     RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
  77.                                   |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  78.     RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  79.     RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  80.     RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
  81.     RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;
  82.     if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK)
  83.     {
  84.         Error_Handler();
  85.     }
  86. }
  87. static void MX_GPIO_Init(void)
  88. {
  89.     GPIO_InitTypeDef GPIO_InitStruct = {0};
  90.     /* GPIO Ports Clock Enable */
  91.     __HAL_RCC_GPIOA_CLK_ENABLE();
  92.     /*Configure GPIO pin Output Level */
  93.     HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_RESET);
  94.     /*Configure GPIO pin : PA5 */
  95.     GPIO_InitStruct.Pin = GPIO_PIN_5;
  96.     GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  97.     GPIO_InitStruct.Pull = GPIO_NOPULL;
  98.     GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  99.     HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
  100. }
  101. static void MX_USART1_UART_Init(void)
  102. {
  103.     huart1.Instance = USART1;
  104.     huart1.Init.BaudRate = 115200;
  105.     huart1.Init.WordLength = UART_WORDLENGTH_8B;
  106.     huart1.Init.StopBits = UART_STOPBITS_1;
  107.     huart1.Init.Parity = UART_PARITY_NONE;
  108.     huart1.Init.Mode = UART_MODE_TX_RX;
  109.     huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  110.     huart1.Init.OverSampling = UART_OVERSAMPLING_16;
  111.     if (HAL_UART_Init(&huart1) != HAL_OK)
  112.     {
  113.         Error_Handler();
  114.     }
  115. }
  116. static void MX_FREERTOS_Init(void)
  117. {
  118.     // 创建队列
  119.     osMessageQDef(myQueue, 16, uint32_t);
  120.     myQueueHandle = osMessageCreate(osMessageQ(myQueue), NULL);
  121.     // 创建发送任务
  122.     osThreadDef(SenderTask, SenderTask, osPriorityNormal, 0, 128);
  123.     osThreadCreate(osThread(SenderTask), NULL);
  124.     // 创建接收任务
  125.     osThreadDef(ReceiverTask, ReceiverTask, osPriorityNormal, 0, 128);
  126.     osThreadCreate(osThread(ReceiverTask), NULL);
  127. }
  128. void Error_Handler(void)
  129. {
  130.     while(1)
  131.     {
  132.     }
  133. }   
复制代码
4. 代码解析

4.1 队列的创建

在MX_FREERTOS_Init函数中,使用osMessageQDef宏界说队列的参数,包罗队列名称、队列长度和数据项类型。然后使用osMessageCreate函数创建队列,并返回队列句柄。
  1. osMessageQDef(myQueue, 16, uint32_t);
  2. myQueueHandle = osMessageCreate(osMessageQ(myQueue), NULL);
复制代码
这里创建了一个长度为 16,数据项类型为uint32_t的队列。
4.2 发送数据到队列

在SenderTask函数中,使用osMessagePut函数将数据发送到队列中。osWaitForever表示如果队列已满,任务将一直等待直到有空间可用。
  1. if(osMessagePut(myQueueHandle, data, osWaitForever) == osOK)
  2. {
  3.     HAL_UART_Transmit(&huart1, (uint8_t *)"Data sent to queue!\r\n", 20, 100);
  4.     data++;
  5. }
复制代码
4.3 从队列中接收数据

在ReceiverTask函数中,使用osMessageGet函数从队列中接收数据。osWaitForever表示如果队列为空,任务将一直等待直到有数据可用。
  1. event = osMessageGet(myQueueHandle, osWaitForever);
  2. if(event.status == osEventMessage)
  3. {
  4.     uint32_t receivedData = event.value.v;
  5.     char buffer[50];
  6.     sprintf(buffer, "Received data: %lu\r\n", receivedData);
  7.     HAL_UART_Transmit(&huart1, (uint8_t *)buffer, strlen(buffer), 100);
  8. }
复制代码
5. 留意事项



  • 队列长度:队列的长度决定了队列可以存储的数据项数量。如果队列已满,继续发送数据大概会导致任务壅闭。
  • 数据类型:队列中的数据项必须是雷同的数据类型,在创建队列时需要明确指定。
  • 错误处理:在使用osMessagePut和osMessageGet函数时,需要检查返回值以确保操作成功。
通过以上步调,你可以在基于 STM32F407 HAL 库和 FreeRTOS 的项目中使用队列进行任务间通信。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

温锦文欧普厨电及净水器总代理

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表