先只看没错误发生, 没开DMA时候的情况
将会面临3种结局,
- 收满数据时候IDLE正好发生,
- 数据发多了, 数据已经收满时候IDLE还没发生
- IDLE发生了数据没收满,
首先: 接收开始
主要的动作是
1. status = UART_Start_Receive_IT(huart, pData, Size); 开始中断接口
2. SET_BIT(huart->Instance->CR1, USART_CR1_IDLEIE); 使能IDLE中断
上面开接收中断调用的这里
主要作用是打开了RXNE 中断
到目前为止, 打开了RXNE和IDLE两个中断
如果串口收到数据将会进入中断处理HAL_UART_IRQHander , 中断处理里面一个部分是处理RXNE, 也就是收到的数据
当不是错误导致进入的中断, 而且SR的RXNE和CR1的RXNEIE都是被使能了
去调用中断接收函数 UART_Receive_IT(huart);
UART_Receive_IT, 在没收满要收的数量的时候, 展开状态:
这里从DR拿一个字节, 把这个计数减一 RxXferCount.
如果已经到了最后一个要读的字节, 再减就0了, 那么就顺便处理了收满了数据的动作
关各个中断 , 清标志, 如果这时候碰巧IDLE标志也发生了, 那就是IDLE时候正好收满了数据, 那把ILDE的标志也清了, 这里是清的SR里的IDLE, 顺便清了一次DR. 最后进入用户可以重新定义的weak回调函数, 顺手还把收到的数据数量(其实这里直接就传了要收的数据量!!!)传给了回调函数
这时候完成了一次数量对得上的接收, IDLE发生时候正好收到了要收的数据量. 结局1
如果这时候数据数量收满了, 但是没收到IDLE, 就是外界往串口发来了数量大于要收的数量的数据, 那就不会在这里清SR的IDLE标志, 但是也去调用了回调, 这是 结局2
HAL_UART_IRQHander 另一个部分是处理IDLE, SR的IDLE
这个情况就是接收数据量没满的时候, 由于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 传递给回调函数的计数值就能理解了
count是从size往下减, size-count的结果是当前实际收到的 字节数
coutn>0是没收满的意思, nb_rx_data>0是还真收到了不止一个字节的意思
至此 分析完毕!