stm32串口(uart)2转发到串口(uart)3实现

今天博主在用kelil5写stm32的程序时遇到了一个全局变量因为在中断和任务切换时没有加 volatile 修饰,导致任务检测不到标志位变化,无法实现效果的问题。

全部代码:

cpp 复制代码
/* 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 */

出问题的主要代码:

cpp 复制代码
//中间其他代码省略

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

cpp 复制代码
volatile uint8_t uart2_rx_flag;      // 设置标志位
volatile uint32_t uart2_rx_size;   // 记录数据长度
volatile uint8_t uart3_rx_flag;
volatile uint32_t uart3_rx_size;

问题解决

相关推荐
LCG米13 小时前
STM32硬件CRC外设实测:多项式固定陷阱、CRC-32校验不匹配根因与软件查表法耗时对比落地
stm32·单片机·嵌入式硬件
La Pulga17 小时前
【FreeRTOS源码学习笔记】任务切换
单片机·mcu·学习·嵌入式·freertos·实时操作系统
女神下凡20 小时前
芯参谋(85):Linux_PPI_NAND_驱动开发指南
linux·运维·arm开发·驱动开发·单片机·嵌入式硬件·设计规范
Zw-awa1 天前
从 CH340 到 HC-05 和 HC-06:让小车脱离电脑
stm32
硅基手札1 天前
【Linux 内核专栏 19】20 · 嵌入式子系统 — GPIO·pinctrl·clock·regulator
linux·运维·单片机·linux内核·嵌入式开发·调试定位
何粥学1 天前
Vivado 2024.2 开发记录(AC820 Zynq-7020)——软件使用,点亮led灯
单片机·嵌入式硬件·zynq
Sakura_j_h_1 天前
51 单片机驱动四位数码管:动态扫描、限流电阻与消影的取舍
单片机·嵌入式硬件·51单片机·嵌入式·数码管·动态扫描·限流电阻
HANDY092001 天前
从“不照人”到“剂量达标”:扇叶遮挡式UV-C空气消毒的工程边界与可验证评估框架
开发语言·人工智能·嵌入式硬件·智能家居
飞凌嵌入式1 天前
千次静电放电试炼,守住飞凌嵌入式硬件可靠底线
嵌入式硬件
蹊黎2 天前
Linux 下用 C 语言实现进度条
linux·c语言·单片机