理解HAL_UARTEx_ReceiveToIdle_IT的工作过程

先只看没错误发生, 没开DMA时候的情况

将会面临3种结局,   

  • 收满数据时候IDLE正好发生,     
  • 数据发多了, 数据已经收满时候IDLE还没发生
  • IDLE发生了数据没收满,     

首先: 接收开始

理解HAL_UARTEx_ReceiveToIdle_IT的工作过程_第1张图片

 主要的动作是
1.  status =  UART_Start_Receive_IT(huart, pData, Size);  开始中断接口

2. SET_BIT(huart->Instance->CR1, USART_CR1_IDLEIE);     使能IDLE中断

理解HAL_UARTEx_ReceiveToIdle_IT的工作过程_第2张图片

上面开接收中断调用的这里

主要作用是打开了RXNE 中断

到目前为止, 打开了RXNE和IDLE两个中断

如果串口收到数据将会进入中断处理HAL_UART_IRQHander  , 中断处理里面一个部分是处理RXNE, 也就是收到的数据

理解HAL_UARTEx_ReceiveToIdle_IT的工作过程_第3张图片

当不是错误导致进入的中断, 而且SR的RXNE和CR1的RXNEIE都是被使能了 

去调用中断接收函数       UART_Receive_IT(huart);

 UART_Receive_IT, 在没收满要收的数量的时候, 展开状态:

理解HAL_UARTEx_ReceiveToIdle_IT的工作过程_第4张图片

 这里从DR拿一个字节, 把这个计数减一 RxXferCount.  

如果已经到了最后一个要读的字节, 再减就0了, 那么就顺便处理了收满了数据的动作

理解HAL_UARTEx_ReceiveToIdle_IT的工作过程_第5张图片

 理解HAL_UARTEx_ReceiveToIdle_IT的工作过程_第6张图片

关各个中断 , 清标志, 如果这时候碰巧IDLE标志也发生了, 那就是IDLE时候正好收满了数据, 那把ILDE的标志也清了, 这里是清的SR里的IDLE, 顺便清了一次DR.  最后进入用户可以重新定义的weak回调函数, 顺手还把收到的数据数量(其实这里直接就传了要收的数据量!!!)传给了回调函数

这时候完成了一次数量对得上的接收, IDLE发生时候正好收到了要收的数据量.    结局1

如果这时候数据数量收满了,  但是没收到IDLE, 就是外界往串口发来了数量大于要收的数量的数据,    那就不会在这里清SR的IDLE标志,  但是也去调用了回调,  这是  结局2

HAL_UART_IRQHander   另一个部分是处理IDLE, SR的IDLE

理解HAL_UARTEx_ReceiveToIdle_IT的工作过程_第7张图片

这个情况就是接收数据量没满的时候, 由于IDLE进来了中断

这时候做了和UART_Receive_IT几乎一样的动作序列, 关中断最后调用回调, 这是结局3

但是,  解决3和结局1往回调函数里传的数据数量计数值是不一样的

结局1:(收满时候正好发生IDLE)

结局3:  (数据量没收满,  就因为IDLE进了中断)

重新梳理一下另一条线,  接收数量的计数值.   RxXferSize和RxXferCount

他们在HAL_UARTEx_ReceiveToIdle_IT时候, 调用UART_Start_Receive_IT, 一同被赋值为了用户要收的数据量

 RxXferSize 结局1(收满正好IDLE)时候 被传进回调函数给用户使用. 

 RxXferCount 在UART_Receive_IT里 先--, 在判断是否为0, 以此判断是否刚好收满了要收的数据

UART_Receive_IT是谁调用的?    是中断处理函数HAL_UART_IRQHandler,  也就是说是因为每次的RXNE时候进行减1.  

那么结局3 传递给回调函数的计数值就能理解了

理解HAL_UARTEx_ReceiveToIdle_IT的工作过程_第8张图片

count是从size往下减,  size-count的结果是当前实际收到的 字节数

coutn>0是没收满的意思, nb_rx_data>0是还真收到了不止一个字节的意思

至此  分析完毕!

你可能感兴趣的:(STM32,stm32,单片机)