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接收逻辑和主循环设计上:
- 主循环无延时,CPU被完全占用
主循环高频执行HAL_RTC_GetTime、HAL_UART_Transmit等操作,没有任何延时,导致UART中断响应被抢占,后续字符无法及时接收。 - 接收缓冲区无边界检查
bufindex未做上限校验,当接收数据超过buf[30]长度时会触发缓冲区溢出,破坏其他变量(如rx、dataReceived),导致接收逻辑混乱。 - 字符串处理缺少终止符
使用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
相关产品推荐
相关产品推荐

