<bug记录>STM32 HAL库lpuart低功耗串口通信错误/卡死

环境:
使用STM32L073x HAL在stop模式下,使用lpuart接收数据,在2s的RTC定时器中断内解析串口数据。

现象:
程序运行一段时间后出现主程序卡死状态,在程序运行状态下该bug极难复现(可能一个月都不复现)。

调试过程:
由于单片机处于stop模式下,想要调试需要打开debug功能

HAL_DBGMCU_DBG_EnableLowPowerConfig();
一开始考虑可能是程序跑飞,将可疑的函数、程序放入仿真环境单元测试百万次均正常,接着在单片机环境下通过串口仿真器发送高频数据,之后就定位问题在串口和stop唤醒部分。
当该bug复现是查看寄存器及lpuart实例:

寄存器状态

观察寄存器后发现CR3与ISR寄存器异常,通过数据手册可知:
寄存器指南当WUF=1时,如果WUFEIE=1,则产生唤醒中断。
接下来看串口中断的入口函数HAL_UART_IRQHandler

HAL_UART_IRQHandler函数分为三个部分
1 如果没有错误则执行回调函数RxISR()

  /* If no error occurs */
  errorflags = (isrflags & (uint32_t)(USART_ISR_PE | USART_ISR_FE | USART_ISR_ORE | USART_ISR_NE));
  if (errorflags == 0U)
  {
    /* UART in mode Receiver ---------------------------------------------------*/
    if (((isrflags & USART_ISR_RXNE) != 0U)
        && ((cr1its & USART_CR1_RXNEIE) != 0U))
    {
      if (huart->RxISR != NULL)
      {
        huart->RxISR(huart);
      }
      return;
    }
  }

2 如果有错误则清除错误标志位,之后或执行回调函数RxISR(),或执行错误处理函数

  /* If some errors occur */
  if ((errorflags != 0U)
      && (((cr3its & USART_CR3_EIE) != 0U)
          || ((cr1its & (USART_CR1_RXNEIE | USART_CR1_PEIE)) != 0U)))
  {
	......
    /* UART frame error interrupt occurred --------------------------------------*/
    if (((isrflags & USART_ISR_FE) != 0U) && ((cr3its & USART_CR3_EIE) != 0U))
    {
      __HAL_UART_CLEAR_FLAG(huart, UART_CLEAR_FEF);

      huart->ErrorCode |= HAL_UART_ERROR_FE;
    }

    /* Call UART Error Call back function if need be --------------------------*/
    if (huart->ErrorCode != HAL_UART_ERROR_NONE)
    {
		......
	}
    return;

  } /* End if some error occurs */

3 执行中断唤醒函数

  /* UART wakeup from Stop mode interrupt occurred ---------------------------*/
  if (((isrflags & USART_ISR_WUF) != 0U) && ((cr3its & USART_CR3_WUFIE) != 0U))
  {
    __HAL_UART_CLEAR_FLAG(huart, UART_CLEAR_WUF);

    /* UART Rx state is not reset as a reception process might be ongoing.
       If UART handle state fields need to be reset to READY, this could be done in Wakeup callback */

#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
    /* Call registered Wakeup Callback */
    huart->WakeupCallback(huart);
#else
    /* Call legacy weak Wakeup Callback */
    HAL_UARTEx_WakeupCallback(huart);
#endif /* USE_HAL_UART_REGISTER_CALLBACKS */
    return;
  }
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是使用STM32HAL库进行串口通信的示例代码: ```c // 引用头文件 #include "stm32f4xx_hal.h" // 定义串口句柄 UART_HandleTypeDef huart1; // 串口接收缓冲区 uint8_t rxBuffer = "yupeng"; // 串口接收完成中断回调函数 void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) { if (huart == &huart1) { // 对接收到的数据进行处理 HAL_UART_Receive_IT(&huart1, rxBuffer, 5); // 再次开启一次中断 } } int main(void) { // 初始化HAL库 HAL_Init(); // 初始化串口 __HAL_RCC_USART1_CLK_ENABLE(); huart1.Instance = USART1; huart1.Init.BaudRate = 9600; 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; HAL_UART_Init(&huart1); // 开启串口接收中断 HAL_UART_Receive_IT(&huart1, rxBuffer, 5); while (1) { // 发送数据 HAL_UART_Transmit_IT(&huart1, txBuffer, 5); // 延时等待发送完成 HAL_Delay(1000); } } ``` 这段代码中,我们首先引用了STM32HAL库的头文件,并定义了一个串口句柄`huart1`,以及接收和发送的缓冲区。在`main`函数中,我们首先初始化HAL库和串口,并开启串口接收中断。然后,在主循环中,我们使用`HAL_UART_Transmit_IT`函数将数据发送出去,并使用`HAL_Delay`函数进行延时,等待发送完成。同时,当串口接收到数据时,会触发中断回调函数`HAL_UART_RxCpltCallback`,我们在这个函数中对接收到的数据进行处理,并再次开启一次中断。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值