你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

stm32f103 + HAL库 + UART + DMA + UCOS III空闲中断HardFault_Handler问题

[复制链接]
rydy 提问时间:2018-8-2 10:54 /
目的:通过UART RX DMA + UART空闲中断接收不定长数据。

描述:打开UART_RX_DMA接收,通过UART_RX空闲中断服务函数接收不定长数据,在UART_RX空闲中断服务重新打开UART_RX_DMA接收。

问题:当不使用串口调试助手发送时,系统正常运行(长时间),通过串口调试助手发送不定长数据,刚开始正常运行,运行一段时间后会进入HardFault_Handler,是什么原因?

收藏 评论7 发布时间:2018-8-2 10:54

举报

7个回答
电子星辰 回答时间:2018-8-2 13:18:28
你用的是什么函数发送?

评分

参与人数 1蝴蝶豆 +2 收起 理由
zero99 + 2

查看全部评分

rydy 回答时间:2018-8-2 14:01:10
使用hal接收 HAL_UART_Receive_DMA
feixiang20 回答时间:2018-8-2 21:57:28
关于空闲中断接收不定长数据我看到论坛里有类似的帖子你可以参考下

比如:

采用STM32cube完成ADC的DMA功能

STM32F051C8T6 STM32CubeMX ADC-DMA-UART教程


一直困惑怎么在Cube上实现串口+DMA+空闲中断接收不定长数据。
使用下来发现Cube好的地方就是你按照图形画方式配置后会帮你省掉很多初始化的工作。但是从标准库走过来略有点别扭,可能用用就习惯了。
想把这几天搞的跟大家聊聊,有不对的地方请指正啊。同时感谢网友baifernlover对本菜的指导。
USART1+DMA配置如下图:

生成工程后,在主函数里添加:


__HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE);    //使能空闲中断


  while (1)


  {


        if(recv_end_flag ==1)                                           //recv_end_flag 结束标志


        {


                printf("rx_len=%d\r\n",rx_len);                    //rx_len 此次接收到了多少数据


                for(i=0;i<rx_len;i++)


                {


                                printf("%x\r\n",rx_buffer);


                }


                rx_len=0;


                recv_end_flag=0;


        }


        HAL_UART_Receive_DMA(&huart1,rx_buffer,BUFFER_SIZE);


  }
复制代码
中断函数里面:


void USART1_IRQHandler(void)


{




        uint32_t tmp_flag = 0;


        uint32_t temp;


        tmp_flag =  __HAL_UART_GET_FLAG(&huart1,UART_FLAG_IDLE);


        if((tmp_flag != RESET))


       {


                __HAL_UART_CLEAR_IDLEFLAG(&huart1);


                temp = huart1.Instance->SR;  


                temp = huart1.Instance->DR;


                HAL_UART_DMAStop(&huart1);


                temp  = hdma_usart1_rx.Instance->NDTR;            


                rx_len =  BUFFER_SIZE - temp;                           


                 recv_end_flag = 1;


         }




}
复制代码
之前看到帖子说HAL_UART_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)和HAL_UART_Receive_DMA(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)接收需要指定接收Size长度值,但是这两个函数的Size有所区别。
HAL_UART_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)主要做了两件事:
1.   huart->pRxBuffPtr = pData;       /*!< Pointer to UART Rx transfer Buffer */
      huart->RxXferSize = Size;           /*!< UART Rx Transfer size              */        这个赋值好像没什么用
     huart->RxXferCount = Size;        /*!< UART Rx Transfer Counter           */
2.使能中断
/* Enable the UART Data Register not empty Interrupt */
    __HAL_UART_ENABLE_IT(huart, UART_IT_RXNE);
在中断处理函数中,去判断中断标志位;然后再根据相应的中断标志位去处理:
  tmp1 = __HAL_UART_GET_FLAG(huart, UART_FLAG_RXNE);
  tmp2 = __HAL_UART_GET_IT_SOURCE(huart, UART_IT_RXNE);
  /* UART in mode Receiver ---------------------------------------------------*/
  if((tmp1 != RESET) && (tmp2 != RESET))
  {
    UART_Receive_IT(huart);
  }

UART_Receive_IT函数里感觉做了两件事:
1.*huart->pRxBuffPtr++ = (uint8_t)(huart->Instance->DR & (uint8_t)0x00FF);  //存数据
2.if(--huart->RxXferCount == 0)                                          //之前赋值的 huart->RxXferCount = Size;
   {
         __HAL_UART_DISABLE_IT(huart, UART_IT_RXNE);     //最后一个数据接收完了就关闭中断
    }
   HAL_UART_RxCpltCallback(huart);                                     //调用接收完成回调函数
整个过程中,来一个数据,huart->RxXferCount做一次减法,直到等于0,去调用回调函数。


HAL_UART_Receive_DMA(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)中:
1. HAL_DMA_Start_IT(huart->hdmarx, (uint32_t)&huart->Instance->DR, *(uint32_t*)tmp, Size);--->
2.DMA_SetConfig(hdma, SrcAddress, DstAddress, DataLength);这里的DataLength就是之前的Size吧---->
3. /* Configure DMA Stream data length */
   hdma->Instance->NDTR = DataLength;   
对NDTR寄存器描述:This register can be written only
when the stream is disabled. When the stream is enabled, this register is read-only,
indicating the remaining data items to be transmitted. This register decrements after each
DMA transfer.

这里的定义的Size赋给了DMA_SxNDTR。使能之后,只能读取,表示还有多少字节需要被“传送”。所以空闲中断里面
temp  = hdma_usart1_rx.Instance->NDTR;  //读取还没有被传送的个数            
rx_len =  BUFFER_SIZE - temp;                    //DMA缓存大小减去没有被传送的个数,就等于已经被传送的个数,也就是接收到的个数。

先这样子理解了。所以感觉如果是DMA接收,即使外部过来的数据个数不等于设定的Size,那么数据也还是被接收到了指定的buffer中。
DMA中断处理函数HAL_DMA_IRQHandler里面会判断DMA传输的状态,完了去调用各自的回调函数。比如传输完成的话会去调用UART_DMAReceiveCplt()--->HAL_UART_RxCpltCallback(huart);最后还是调用了HAL_UART_RxCpltCallback(huart)函数。

评分

参与人数 1蝴蝶豆 +3 收起 理由
zero99 + 3

查看全部评分

xmstudio 回答时间:2018-8-3 08:11:22
这个可能是溢出了,你检查一下你的程序里面有没有指针变量,指针变量有没有无限制累加,我有一次就是for循环写成死循环了,里面有一个指针不停的加,如果超过地址范围了就会进这个中断

评分

参与人数 1蝴蝶豆 +3 收起 理由
zero99 + 3

查看全部评分

s2333 回答时间:2018-8-3 09:58:10
八成是溢出了,猜测是接收数据超过了你设置的数组的上限...

评分

参与人数 1蝴蝶豆 +2 收起 理由
zero99 + 2

查看全部评分

rydy 回答时间:2018-8-7 17:59:34
谢谢你,已解决,低级错误,M3的板子下载M4的ucos iii源码移植。

评分

参与人数 1蝴蝶豆 +2 收起 理由
zero99 + 2 结帖奖励

查看全部评分

rydy 回答时间:2018-8-7 17:59:56
感谢,已解决,低级错误,M3的板子下载M4的ucos iii源码移植。

所属标签

相似问题

关于意法半导体
我们是谁
投资者关系
意法半导体可持续发展举措
创新和工艺
招聘信息
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版