栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

2021-10-12

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

2021-10-12

stm32HAL库串口接收中断HAL_UART_Receive_IT函数问题描述与分析

main.c中

while (1)
  {
		HAL_Delay(1000);
		
		HAL_UART_Receive_IT(&huart1,string3,5);
		recog=0;while(!recog);

stm32f4xx_it.c中

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
	if(huart==&huart1)/
	{
		temp++;
		recog=1;
		HAL_UART_Transmit_IT(&huart1,string3,5);//
	}
}

问题:若接收数据超过5个时,单片机便卡死,无法继续接收。经调试,发现它会将第6个字符接收至string3[0]中,然后卡死。

分析
首先是HAL_UART_Receive_IT函数,

HAL_StatusTypeDef HAL_UART_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)
{
  
  //1.判断receive是否已经在运行
  if (huart->RxState == HAL_UART_STATE_READY)
  {
    if ((pData == NULL) || (Size == 0U))
    {
      return HAL_ERROR;
    }

    
    __HAL_LOCK(huart);

    
    huart->ReceptionType = HAL_UART_RECEPTION_STANDARD;
	//开始接收中断
    return (UART_Start_Receive_IT(huart, pData, Size));
  }
  else
  {
    return HAL_BUSY;
  }
}

再到UART_Start_Receive_IT函数

HAL_StatusTypeDef UART_Start_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)
{
  huart->pRxBuffPtr = pData;
  huart->RxXferSize = Size;
  huart->RxXferCount = Size;

  huart->ErrorCode = HAL_UART_ERROR_NONE;
  huart->RxState = HAL_UART_STATE_BUSY_RX;

  
  __HAL_UNLOCK(huart);

  
  __HAL_UART_ENABLE_IT(huart, UART_IT_PE);

  
  __HAL_UART_ENABLE_IT(huart, UART_IT_ERR);

  
  __HAL_UART_ENABLE_IT(huart, UART_IT_RXNE);

  return HAL_OK;
}

该函数打开了UART_IT_RXNE中断;

接下来看中断里做了什么:

void USART1_IRQHandler(void)
{
  

  
  HAL_UART_IRQHandler(&huart1);
}

HAL_UART_IRQHandler函数:

void HAL_UART_IRQHandler(UART_HandleTypeDef *huart)
{
  uint32_t isrflags   = READ_REG(huart->Instance->SR);
  uint32_t cr1its     = READ_REG(huart->Instance->CR1);
  uint32_t cr3its     = READ_REG(huart->Instance->CR3);
  uint32_t errorflags = 0x00U;
  uint32_t dmarequest = 0x00U;

  
  errorflags = (isrflags & (uint32_t)(USART_SR_PE | USART_SR_FE | USART_SR_ORE | USART_SR_NE));
  if (errorflags == RESET)
  {
    
    if (((isrflags & USART_SR_RXNE) != RESET) && ((cr1its & USART_CR1_RXNEIE) != RESET))
    {
      UART_Receive_IT(huart);
      return;
    }
  }
  //截取了recieve的那部分

无错误,则进入UART_Receive_IT函数:

static HAL_StatusTypeDef UART_Receive_IT(UART_HandleTypeDef *huart)
{
  uint8_t  *pdata8bits;
  uint16_t *pdata16bits;

  
  if (huart->RxState == HAL_UART_STATE_BUSY_RX)
  {
      pdata8bits = (uint8_t *) huart->pRxBuffPtr;
      pdata16bits  = NULL;

      if ((huart->Init.WordLength == UART_WORDLENGTH_9B) || ((huart->Init.WordLength == UART_WORDLENGTH_8B) && (huart->Init.Parity == UART_PARITY_NONE)))
      {
        *pdata8bits = (uint8_t)(huart->Instance->DR & (uint8_t)0x00FF);
      }
      else
      {
        *pdata8bits = (uint8_t)(huart->Instance->DR & (uint8_t)0x007F);
      }
      huart->pRxBuffPtr += 1U;
//剩余需要接收字符数减减
    if (--huart->RxXferCount == 0U)
    {
      
      __HAL_UART_DISABLE_IT(huart, UART_IT_RXNE);

      
      __HAL_UART_DISABLE_IT(huart, UART_IT_PE);

      
      __HAL_UART_DISABLE_IT(huart, UART_IT_ERR);

      
      //接收结束
      huart->RxState = HAL_UART_STATE_READY;
      
      //调用回调函数
        
#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
        
        huart->RxCpltCallback(huart);
#else
        
        HAL_UART_RxCpltCallback(huart);
#endif 
      }

      return HAL_OK;
  }
  else
  {
    return HAL_BUSY;
  }
}

可见若接收字符数为5,则USART1_IRQHandler函数开始会连续进行5次中断,然后在最底层函数UART_Receive_IT中disable RXNE中断.

打开receive_IT,有字符传入,RXNE寄存器硬件置1,数据保存至DR寄存器. 程序进入中断,

经调试,开头的问题程序在多一个字符后huart1
始终处于HAL_ready,errorcode为8
看到这篇文章,讲的挺有道理
STM32 之 HAL 库串口 USART 丢数据及ORE卡死的解决方案_luoyu510183的博客-CSDN博客 https://blog.csdn.net/luoyu510183/article/details/86515644
但我添加如下错误回调函数,并未解决问题。

void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart){
	if(huart->ErrorCode&HAL_UART_ERROR_ORE){
		__HAL_UART_CLEAR_OREFLAG(huart);
	}
}

想到可以接收完后disable串口

 while (1)
  {
		HAL_Delay(1000);
		
		__HAL_UART_ENABLE(&huart1);
		//__HAL_UART_CLEAR_FLAG(&huart1,UART_FLAG_RXNE);
		HAL_UART_Receive_IT(&huart1,string3,5);
		recog=0;while(!recog);
		__HAL_UART_DISABLE(&huart1);
    

    
  }
  
}

调试后发现,问题终于解决。

补充:
在hal库函数发现这条语句,因此不进接收中断。

      dmarequest = HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAR);
      if (((huart->ErrorCode & HAL_UART_ERROR_ORE) != RESET) || dmarequest)
      {
        
        UART_EndRxTransfer(huart);
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/315988.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号