马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
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
- #include "main.h"
- #include "stm32f4xx_hal.h"
- #include "cmsis_os.h"
- // 队列句柄
- osMessageQId myQueueHandle;
- // 发送任务函数
- void SenderTask(void const * argument)
- {
- uint32_t data = 0;
- for(;;)
- {
- // 发送数据到队列
- if(osMessagePut(myQueueHandle, data, osWaitForever) == osOK)
- {
- HAL_UART_Transmit(&huart1, (uint8_t *)"Data sent to queue!\r\n", 20, 100);
- data++;
- }
- osDelay(1000); // 每隔1秒发送一次数据
- }
- }
- // 接收任务函数
- void ReceiverTask(void const * argument)
- {
- osEvent event;
- for(;;)
- {
- // 从队列中接收数据
- event = osMessageGet(myQueueHandle, osWaitForever);
- if(event.status == osEventMessage)
- {
- uint32_t receivedData = event.value.v;
- char buffer[50];
- sprintf(buffer, "Received data: %lu\r\n", receivedData);
- HAL_UART_Transmit(&huart1, (uint8_t *)buffer, strlen(buffer), 100);
- }
- }
- }
- void SystemClock_Config(void);
- static void MX_GPIO_Init(void);
- static void MX_USART1_UART_Init(void);
- static void MX_FREERTOS_Init(void);
- int main(void)
- {
- HAL_Init();
- SystemClock_Config();
- MX_GPIO_Init();
- MX_USART1_UART_Init();
- MX_FREERTOS_Init();
- /* 启动调度器 */
- osKernelStart();
- while (1)
- {
- // 主循环一般为空
- }
- }
- void SystemClock_Config(void)
- {
- RCC_OscInitTypeDef RCC_OscInitStruct = {0};
- RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
- /** 初始化RCC振荡器
- */
- RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
- RCC_OscInitStruct.HSEState = RCC_HSE_ON;
- RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
- RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
- RCC_OscInitStruct.PLL.PLLM = 8;
- RCC_OscInitStruct.PLL.PLLN = 336;
- RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
- RCC_OscInitStruct.PLL.PLLQ = 7;
- if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
- {
- Error_Handler();
- }
- /** 初始化RCC时钟
- */
- RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
- |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
- RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
- RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
- RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
- RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;
- if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK)
- {
- Error_Handler();
- }
- }
- static void MX_GPIO_Init(void)
- {
- GPIO_InitTypeDef GPIO_InitStruct = {0};
- /* GPIO Ports Clock Enable */
- __HAL_RCC_GPIOA_CLK_ENABLE();
- /*Configure GPIO pin Output Level */
- HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_RESET);
- /*Configure GPIO pin : PA5 */
- GPIO_InitStruct.Pin = GPIO_PIN_5;
- GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
- GPIO_InitStruct.Pull = GPIO_NOPULL;
- GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
- HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
- }
- static void MX_USART1_UART_Init(void)
- {
- huart1.Instance = USART1;
- huart1.Init.BaudRate = 115200;
- huart1.Init.WordLength = UART_WORDLENGTH_8B;
- huart1.Init.StopBits = UART_STOPBITS_1;
- huart1.Init.Parity = UART_PARITY_NONE;
- huart1.Init.Mode = UART_MODE_TX_RX;
- huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
- huart1.Init.OverSampling = UART_OVERSAMPLING_16;
- if (HAL_UART_Init(&huart1) != HAL_OK)
- {
- Error_Handler();
- }
- }
- static void MX_FREERTOS_Init(void)
- {
- // 创建队列
- osMessageQDef(myQueue, 16, uint32_t);
- myQueueHandle = osMessageCreate(osMessageQ(myQueue), NULL);
- // 创建发送任务
- osThreadDef(SenderTask, SenderTask, osPriorityNormal, 0, 128);
- osThreadCreate(osThread(SenderTask), NULL);
- // 创建接收任务
- osThreadDef(ReceiverTask, ReceiverTask, osPriorityNormal, 0, 128);
- osThreadCreate(osThread(ReceiverTask), NULL);
- }
- void Error_Handler(void)
- {
- while(1)
- {
- }
- }
复制代码 4. 代码解析
4.1 队列的创建
在MX_FREERTOS_Init函数中,使用osMessageQDef宏界说队列的参数,包罗队列名称、队列长度和数据项类型。然后使用osMessageCreate函数创建队列,并返回队列句柄。
- osMessageQDef(myQueue, 16, uint32_t);
- myQueueHandle = osMessageCreate(osMessageQ(myQueue), NULL);
复制代码 这里创建了一个长度为 16,数据项类型为uint32_t的队列。
4.2 发送数据到队列
在SenderTask函数中,使用osMessagePut函数将数据发送到队列中。osWaitForever表示如果队列已满,任务将一直等待直到有空间可用。
- if(osMessagePut(myQueueHandle, data, osWaitForever) == osOK)
- {
- HAL_UART_Transmit(&huart1, (uint8_t *)"Data sent to queue!\r\n", 20, 100);
- data++;
- }
复制代码 4.3 从队列中接收数据
在ReceiverTask函数中,使用osMessageGet函数从队列中接收数据。osWaitForever表示如果队列为空,任务将一直等待直到有数据可用。
- event = osMessageGet(myQueueHandle, osWaitForever);
- if(event.status == osEventMessage)
- {
- uint32_t receivedData = event.value.v;
- char buffer[50];
- sprintf(buffer, "Received data: %lu\r\n", receivedData);
- HAL_UART_Transmit(&huart1, (uint8_t *)buffer, strlen(buffer), 100);
- }
复制代码 5. 留意事项
- 队列长度:队列的长度决定了队列可以存储的数据项数量。如果队列已满,继续发送数据大概会导致任务壅闭。
- 数据类型:队列中的数据项必须是雷同的数据类型,在创建队列时需要明确指定。
- 错误处理:在使用osMessagePut和osMessageGet函数时,需要检查返回值以确保操作成功。
通过以上步调,你可以在基于 STM32F407 HAL 库和 FreeRTOS 的项目中使用队列进行任务间通信。
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |