今天博主在用kelil5写stm32的程序时遇到了一个全局变量因为在中断和任务切换时没有加 volatile 修饰,导致任务检测不到标志位变化,无法实现效果的问题。
全部代码:
/* USER CODE BEGIN Header */
/**
******************************************************************************
* File Name : freertos.c
* Description : Code for freertos applications
******************************************************************************
* @attention
*
* Copyright (c) 2025 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* 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 "stdio.h"
#include "usart.h"
#include "norflash.h"
#include "command.h"
#include "string.h"
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
/* USER CODE END PTD */
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
/* USER CODE END PM */
/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN Variables */
#define SFLASH_BACKUP_APPLICATION_ADDRESS 0x380000
#define APPLICATION_SIZE 224*1024
#define SFLASH_SIZE 4*1024*1024
uint8_t recbuffer[1024] = {"hello"};
uint8_t readbuffer[1024] = {0};
uint8_t command[512];
int commandLength = 0;
uint8_t uart2_rx_flag; // 设置标志位
uint32_t uart2_rx_size; // 记录数据长度
uint8_t uart3_rx_flag;
uint32_t uart3_rx_size;
/* USER CODE END Variables */
/* Definitions for defaultTask */
osThreadId_t defaultTaskHandle;
const osThreadAttr_t defaultTask_attributes = {
.name = "defaultTask",
.stack_size = 128 * 4,
.priority = (osPriority_t) osPriorityNormal,
};
/* Definitions for myTask02 */
osThreadId_t myTask02Handle;
const osThreadAttr_t myTask02_attributes = {
.name = "myTask02",
.stack_size = 128 * 4,
.priority = (osPriority_t) osPriorityLow,
};
/* Definitions for myTask03 */
osThreadId_t myTask03Handle;
const osThreadAttr_t myTask03_attributes = {
.name = "myTask03",
.stack_size = 128 * 4,
.priority = (osPriority_t) osPriorityLow,
};
/* Private function prototypes -----------------------------------------------*/
/* USER CODE BEGIN FunctionPrototypes */
/* USER CODE END FunctionPrototypes */
void StartDefaultTask(void *argument);
void StartTask02(void *argument);
void StartTask03(void *argument);
void MX_FREERTOS_Init(void); /* (MISRA C 2004 rule 8.1) */
/**
* @brief FreeRTOS initialization
* @param None
* @retval None
*/
void MX_FREERTOS_Init(void) {
/* USER CODE BEGIN Init */
norflash_init();/* 初始化NORFLASH */
HAL_UARTEx_ReceiveToIdle_IT(&huart2, recbuffer, sizeof(recbuffer));
HAL_UARTEx_ReceiveToIdle_IT(&huart3, readbuffer, sizeof(recbuffer));
/* USER CODE END Init */
/* USER CODE BEGIN RTOS_MUTEX */
/* add mutexes, ... */
/* USER CODE END RTOS_MUTEX */
/* USER CODE BEGIN RTOS_SEMAPHORES */
/* add semaphores, ... */
/* USER CODE END RTOS_SEMAPHORES */
/* USER CODE BEGIN RTOS_TIMERS */
/* start timers, add new ones, ... */
/* USER CODE END RTOS_TIMERS */
/* USER CODE BEGIN RTOS_QUEUES */
/* add queues, ... */
/* USER CODE END RTOS_QUEUES */
/* Create the thread(s) */
/* creation of defaultTask */
defaultTaskHandle = osThreadNew(StartDefaultTask, NULL, &defaultTask_attributes);
/* creation of myTask02 */
myTask02Handle = osThreadNew(StartTask02, NULL, &myTask02_attributes);
/* creation of myTask03 */
myTask03Handle = osThreadNew(StartTask03, NULL, &myTask03_attributes);
/* USER CODE BEGIN RTOS_THREADS */
/* add threads, ... */
/* USER CODE END RTOS_THREADS */
/* USER CODE BEGIN RTOS_EVENTS */
/* add events, ... */
/* USER CODE END RTOS_EVENTS */
}
/* USER CODE BEGIN Header_StartDefaultTask */
/**
* @brief Function implementing the defaultTask thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_StartDefaultTask */
void StartDefaultTask(void *argument)
{
/* USER CODE BEGIN StartDefaultTask */
/* Infinite loop */
for(;;) {
commandLength = Command_GetCommand(command);
if (commandLength != 0) {
HAL_UART_Transmit(&huart2, command, commandLength, HAL_MAX_DELAY);
}
osDelay(500);
}
/* USER CODE END StartDefaultTask */
}
/* USER CODE BEGIN Header_StartTask02 */
/**
* @brief Function implementing the myTask02 thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_StartTask02 */
void StartTask02(void *argument)
{
/* USER CODE BEGIN StartTask02 */
/* Infinite loop */
for(;;)
{
HAL_GPIO_TogglePin(LED5_GPIO_Port, LED5_Pin);
HAL_GPIO_TogglePin(LED5_GPIO_Port, LED6_Pin);
osDelay(100);
}
/* USER CODE END StartTask02 */
}
/* USER CODE BEGIN Header_StartTask03 */
/**
* @brief Function implementing the myTask03 thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_StartTask03 */
void StartTask03(void *argument)
{
/* USER CODE BEGIN StartTask03 */
/* Infinite loop */
for(;;)
{
// if(uart2_rx_flag) {
// HAL_UART_Transmit(&huart2, recbuffer, uart2_rx_size, HAL_MAX_DELAY);
// uart2_rx_flag = 0;
// }
// strcpy(recbuffer,"hello");
// HAL_UART_Transmit(&huart3, recbuffer, sizeof(), HAL_MAX_DELAY);
// strcpy(recbuffer,"hello");
// HAL_UART_Transmit(&huart2, recbuffer, uart2_rx_size, HAL_MAX_DELAY);
// char* msg = recbuffer; //recbuffer;
// HAL_UART_Transmit(&huart3, recbuffer, strlen(recbuffer), HAL_MAX_DELAY);
// HAL_UART_Transmit(&huart2, recbuffer, strlen(recbuffer), HAL_MAX_DELAY);
// osDelay(1000);
//UART2收到的数据转发到UART3
if(uart2_rx_flag) {
HAL_UART_Transmit(&huart3, recbuffer, uart2_rx_size, HAL_MAX_DELAY);
uart2_rx_flag = 0;
}
// UART3收到的数据转发到UART2
if(uart3_rx_flag) {
HAL_UART_Transmit(&huart2, readbuffer, uart3_rx_size, HAL_MAX_DELAY);
uart3_rx_flag = 0;
}
//osDelay(1000);
}
/* USER CODE END StartTask03 */
}
/* Private application code --------------------------------------------------*/
/* USER CODE BEGIN Application */
int fputc(int ch, FILE *f) {
HAL_UART_Transmit(&huart2, (uint8_t *)&ch, 1, HAL_MAX_DELAY);
return ch;
}
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) {
if(GPIO_Pin == OK_Pin) {
HAL_GPIO_TogglePin(LED5_GPIO_Port, LED5_Pin);
}
if(GPIO_Pin == RIGHT_Pin) {
HAL_GPIO_TogglePin(LED5_GPIO_Port, LED6_Pin);
}
if(GPIO_Pin == UP_Pin) {
HAL_GPIO_TogglePin(FAULT_GPIO_Port, FAULT_Pin);
}
}
void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size) {
if(huart == &huart2) {
//Command_Write(recbuffer, Size);
uart2_rx_flag = 1; // 设置标志位
uart2_rx_size = Size; // 记录数据长度
//HAL_UART_Transmit_IT(&huart2, recbuffer, Size);
HAL_UARTEx_ReceiveToIdle_IT(&huart2, recbuffer, sizeof(recbuffer));
}
if(huart == &huart3) {
//串口3收到的数据打印到串口2
uart3_rx_flag = 1;
uart3_rx_size = Size;
//HAL_UART_Transmit_IT(&huart2, recbuffer, Size);
HAL_UARTEx_ReceiveToIdle_IT(&huart3, readbuffer, sizeof(readbuffer));
}
}
/* USER CODE END Application */
出问题的主要代码:
//中间其他代码省略
uint8_t uart2_rx_flag; // 设置标志位
uint32_t uart2_rx_size; // 记录数据长度
uint8_t uart3_rx_flag;
uint32_t uart3_rx_size;
//中间其他代码省略
//UART2收到的数据转发到UART3
if(uart2_rx_flag) {
HAL_UART_Transmit(&huart3, recbuffer, uart2_rx_size, HAL_MAX_DELAY);
uart2_rx_flag = 0;
}
// UART3收到的数据转发到UART2
if(uart3_rx_flag) {
HAL_UART_Transmit(&huart2, readbuffer, uart3_rx_size, HAL_MAX_DELAY);
uart3_rx_flag = 0;
}
//中间其他代码省略
//串口接收中断
void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size) {
if(huart == &huart2) {
//Command_Write(recbuffer, Size);
uart2_rx_flag = 1; // 设置标志位
uart2_rx_size = Size; // 记录数据长度
//HAL_UART_Transmit_IT(&huart2, recbuffer, Size);
HAL_UARTEx_ReceiveToIdle_IT(&huart2, recbuffer, sizeof(recbuffer));
}
if(huart == &huart3) {
//串口3收到的数据打印到串口2
uart3_rx_flag = 1;
uart3_rx_size = Size;
//HAL_UART_Transmit_IT(&huart2, recbuffer, Size);
HAL_UARTEx_ReceiveToIdle_IT(&huart3, readbuffer, sizeof(readbuffer));
}
}
出问题的现象是
发送到uart2的数据转发给uart3时不能立即转发给uart3,只有当uart3接收到消息转发到uart2时,uart2转发到uart3的消息才会转发一次消息给uart3
解决方法:
定义变量时加volatile
volatile uint8_t uart2_rx_flag; // 设置标志位
volatile uint32_t uart2_rx_size; // 记录数据长度
volatile uint8_t uart3_rx_flag;
volatile uint32_t uart3_rx_size;
问题解决