You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

STM32 UART接收缓冲区数据异常与RTC时钟问题排查

STM32 UART接收异常排查(仅收到字符'e')

问题背景

测试STM32的RTC定时器功能,代码预期通过UART接收数据更新RTC时间。但发送字符串SetTime141414后,调试发现仅能接收到字符‘e’,需排查代码潜在问题,确认是否与RTC功能相关。

相关代码

RTC_TimeTypeDef sTime;
RTC_DateTypeDef sDate;

char temp[100];
uint8_t rx;
uint8_t bufindex=0;
uint8_t buf[30];
uint8_t dataReceived  = 0;

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_USART2_UART_Init(void);
static void MX_RTC_Init(void);
/* USER CODE BEGIN PFP */
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
  if(huart->Instance == USART2)
  {
    buf[bufindex] = rx;

    if(rx == '\n')
    {
      dataReceived  = 1;
    }
    else
    {
      bufindex++;
    }

    HAL_UART_Receive_IT(&huart2, &rx, 1);
  }
}

err_r handle_data(void)
{
  char *pData;
  uint32_t  lenStr  = 0;

  if((pData = strstr((char *)buf,"SetTime")) != NULL)
  {
    lenStr  = strlen("SetTime");

    sTime.Hours   = ((*(pData + lenStr    ) - '0') << 4) + (*(pData + lenStr + 1) - '0');
    sTime.Minutes = ((*(pData + lenStr + 2) - '0') << 4) + (*(pData + lenStr + 3) - '0');
    sTime.Seconds = ((*(pData + lenStr + 4) - '0') << 4) + (*(pData + lenStr + 5) - '0');

    HAL_RTC_SetTime(&hrtc, &sTime, RTC_FORMAT_BCD);

    bufindex  = 0;
  }
  else if((pData = strstr((char *)buf,"SetDate")) != NULL)
  {
    lenStr  = strlen("SetDate");

    sDate.Year    = ((*(pData + lenStr    ) - '0') << 4) + (*(pData + lenStr + 1) - '0');
    sDate.Month   = ((*(pData + lenStr + 2) - '0') << 4) + (*(pData + lenStr + 3) - '0');
    sDate.Date    = ((*(pData + lenStr + 4) - '0') << 4) + (*(pData + lenStr + 5) - '0');

    HAL_RTC_SetDate(&hrtc, &sDate, RTC_FORMAT_BCD);

    bufindex  = 0;
  }
  else
  {
    bufindex      = 0;
    dataReceived  = 0;
    return  ERROR_NOTFOUND;
  }

  dataReceived  = 0;

  return  ERROR_NONE;
}

/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */

/* USER CODE END 0 */

/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{

  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_USART2_UART_Init();
  MX_RTC_Init();
  /* USER CODE BEGIN 2 */
  HAL_UART_Receive_IT(&huart2, &rx, 1);

  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    HAL_RTC_GetTime(&hrtc, &sTime, RTC_FORMAT_BCD);
    HAL_RTC_GetDate(&hrtc, &sDate, RTC_FORMAT_BCD);

    if(dataReceived == 1)
    {
      if(handle_data() != ERROR_NONE)
      {
        //  HANDLE ERROR BY ERROR NAME
      }
    }

    sprintf(temp,"\r\n20%02x-%02x %02x %02x:%02x:%02x", sDate.Year, sDate.Month, sDate.Date, sTime.Hours, sTime.Minutes,sTime.Seconds); // sprintf to temp

    HAL_UART_Transmit(&huart2, (uint8_t*)temp, strlen(temp), 10);

    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

问题分析与修复建议

核心问题

当前现象与RTC定时器无直接关联,问题根源出在UART接收逻辑和主循环设计上:

  1. 主循环无延时,CPU被完全占用
    主循环高频执行HAL_RTC_GetTime、HAL_UART_Transmit等操作,没有任何延时,导致UART中断响应被抢占,后续字符无法及时接收。
  2. 接收缓冲区无边界检查
    bufindex未做上限校验,当接收数据超过buf[30]长度时会触发缓冲区溢出,破坏其他变量(如rx、dataReceived),导致接收逻辑混乱。
  3. 字符串处理缺少终止符
    使用strstr等字符串函数时,buf未添加\0终止符,会读取缓冲区外的垃圾数据,引发匹配失败或逻辑异常。

修复措施

  • 给主循环添加延时
    在主循环末尾加入HAL_Delay(1000);(可根据需求调整时长),降低循环频率,给UART中断足够响应时间:
    while (1)
    {
      // ... 原有代码 ...
      HAL_Delay(1000);
    }
    
  • 添加缓冲区边界检查
    在HAL_UART_RxCpltCallback中更新bufindex前判断是否超出缓冲区上限:
    else
    {
      if(bufindex < sizeof(buf)-1) // 预留一个位置给字符串终止符
      {
        bufindex++;
      }
    }
    
  • 确保字符串有终止符
    在触发dataReceived = 1时,给buf添加终止符:
    if(rx == '\n')
    {
      buf[bufindex] = '\0';
      dataReceived = 1;
    }
    

内容的提问来源于stack exchange,提问作者Gogu Mi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 20:35:04