为什么要把串口精讲?
串口的重要性不言而喻,把串口应用起来很简单,但是用好却有一定的难度,这里包含了大量的数据处理的情况。那么如何防止数据丢失,如何接受不定长度的数据是本专题具体讨论的内容。本系列会从项目应用的角度去设计相关串口,不足之处还请指正。
了解串口的中断源
借一张图来说明一下:
中断源分类
脉冲型
脉冲型中断源是指中断请求信号以一个短暂的脉冲形式出现。这种中断源通常会在检测到某个特定事件后,向CPU发送一个短暂的脉冲信号。脉冲的上升沿或下降沿触发中断,一旦脉冲发送完毕,中断请求就被认为是完成的。这种类型的中断源适用于那些需要快速响应的场合,因为它可以迅速地通知CPU有一个事件需要处理。然而,如果CPU没有及时检测到这个脉冲,那么中断请求就有可能被错过,这就是所谓的“脉冲丢失”问题。为了避免这种情况,通常需要额外的硬件支持来确保脉冲能够被正确地检测到。
解释一下:就是中断源产生会自己关断。
电平型中断源
平型中断源则是通过维持一个稳定的电平状态来发出中断请求。当中断条件满足时,中断源会将其中断请求线保持在一个特定的电平(通常是低电平)上,直到CPU响应并处理了中断请求为止。这种方式的优点是不容易丢失中断信号,因为只要中断源保持在请求电平上,CPU就有机会检测到这个中断。不过,这种方式的缺点是可能会导致CPU频繁地被中断,因为它必须不断地检查中断请求线的状态,这可能会影响CPU处理其他任务的效率。
解释一下:不关断会一直产生中断,也就是你的cpu会把大量时间浪费在中断里面。
串口的中断源就是电平型中断源。
中断源的内部结构
图
首先状态寄存器(SR)里面装着的是中断标志位,也是产生中断的来源:
-
PE (Parity Error) - 奇偶校验错误标志位。当接收到的数据具有错误的奇偶校验位时,此位将被硬件设置。
-
FE (Framing Error) - 帧错误标志位。当接收到的帧不包含正确的停止位数时,此位将被硬件设置。
-
NF (Noise Detected Flag) - 噪声检测标志位。当接收过程中检测到噪声脉冲时,此位将被硬件设置。
-
ORE (Overrun Error) - 溢出错误标志位。当接收缓冲区已满,新的接收数据覆盖了旧数据时,此位将被硬件设置。
-
IDLE (Idle Line Detected) - 空闲线路检测标志位。当UART检测到空闲线路时,此位将被硬件设置。
-
RXNE (Read Data Register Not Empty) - 接收数据寄存器非空标志位。当接收数据寄存器中有数据可读时,此位为1。
-
TC (Transmission Complete) - 发送完成标志位。当所有数据都已经发送完毕,且发送移位寄存器为空时,此位将被硬件设置。
-
TXE (Transmit Data Register Empty) - 发送数据寄存器空标志位。当发送数据寄存器为空,即可以写入新的数据时,此位为1。
-
CTS (Clear To Send) - 清除发送标志位。此位由硬件控制,用于指示CTS(Clear To Send)输入的状态。
-
RTO (Receiver Time Out) - 接收超时标志位。当接收超时事件发生时,此位将被硬件设置。
-
EOL (End of Line) - 行结束标志位。在某些模式下,当检测到特定的行结束标志时,此位将被硬件设置。
-
UDR (Underrun) - 欠载标志位。当发送缓冲区需要数据但发送数据寄存器为空时,此位将被硬件设置。
解读
先看TXE (Transmit Data Register Empty) - 发送数据寄存器空标志位。当发送数据寄存器为空,即可以写入新的数据时,此位为1。
也就是说 我的TXE为1时,就可以发送新的数据了。这里可以开启一个中断源,当检测到TXE为1时就会触发中断,这个时候就可以发想发送的数据。这里注意一点,前面说了uart中断是电平型中断,开启中断后,无需再去手动关断TXE中断,读TDR寄存器时(发数据,也就是调用了uart_senddata(),会自动关断此中断。
TC (Transmission Complete) - 发送完成标志位。当所有数据都已经发送完毕,且发送移位寄存器为空时,此位将被硬件设置。
数据从移位寄存器发送完,TC会自动设置,如果作为中断的话,不需要关断中断源。当使用RS485时可以去读一下TC标志位的值,如果FlagStatus USART_GetFlagStatus()说明发送完毕。可以切换至接受状态。
RXNE (Read Data Register Not Empty) - 接收数据寄存器非空标志位。当接收数据寄存器中有数据可读时,此位为1。
当产生中断时,需要注意读RDR寄存器就已经将中断给关掉了。
IDLE (Idle Line Detected) - 空闲线路检测标志位。当UART检测到空闲线路时,此位将被硬件设置。
就是检测到没有数据传送过来时,可以用空闲中断去判断,类如MODBUS断帧就是相隔3.5个字节的时长,那么通过空闲中断就可判断是否收到数据帧。
注意:这里有坑,使用STM32F40系列可能要求使用特定的方法来清除。例如,读取数据寄存器(USART_DR)可能是用来清除IDLE标志位的正确方法,而不是使USART_ClearITPendingBit()
函数。具体使用方法请参考具体的芯片手册。
以STM32F4为例
// 读取USART_SR寄存器的值 uint16_t sr_value = usart1->SR;
// 读取USART_DR寄存器的值 uint16_t dr_value = usart1->DR;
执行完这个操作就可以清除空闲中断了。
关于中断的几个接口
中断使能函数:
void USART_ITConfig()
使能某个中断源。
USART_GetITStatus()
获取标志位的值,与USART_GetFlgStatus()不同的是,后者主要是获取标志位的值,而前者是获取(标志位&&中断使能位)的值。就比如中断使能没打开,但是标志位为1,那么USART_GetITStatus()也是0,而USART_GetFlgStatus()为1。
清除标志位,也可以当作清除中断用。
步骤:
第一步使能中断
第二部进入中断服务函数
1.先判断中断是由谁产生;
2.清除中断,
3.读取数据
4.处理中断(添加标志位)