我想知道为什么会发生 UART 错误,以及何时应该检查此类错误。这里有一篇帖子询问如何处理个别错误,例如溢出、奇偶校验等……我很清楚为什么会发生数据溢出,为什么会发生奇偶校验错误,但我想知道根本原因是什么。我的问题更侧重于为什么会发生这些错误(物理原因),以及何时应该将错误检查作为其应用的一个因素。
到目前为止,我的程序似乎运行良好(没有错误检查),但我知道噪音会搞砸事情。如何模拟可能导致 UART Rx/Tx 端口失败的条件?
我想知道为什么会发生 UART 错误,以及何时应该检查此类错误。这里有一篇帖子询问如何处理个别错误,例如溢出、奇偶校验等……我很清楚为什么会发生数据溢出,为什么会发生奇偶校验错误,但我想知道根本原因是什么。我的问题更侧重于为什么会发生这些错误(物理原因),以及何时应该将错误检查作为其应用的一个因素。
到目前为止,我的程序似乎运行良好(没有错误检查),但我知道噪音会搞砸事情。如何模拟可能导致 UART Rx/Tx 端口失败的条件?
在任何电路中都有几个潜在的噪声源。一些最常见的包括:
此外(正如@jippie 提到的),时钟偏差是使用预定数据速率的任何类型的串行通信中错误的一个非常常见的原因。如果您使用外部晶体并连接到可以合理预期准确的另一个系统,则不太可能导致问题。然而,内部振荡器的容差可能比晶体差几个数量级,并且往往在温度范围内变化更大。
可以在正在运行的系统上执行几项基本测试,以确定接口的基本噪声(和偏移)抗扰度,包括:
还有很多其他的——事实上,有专门用于EMC认证的大型测试实验室。
通常,除非可以接受最小程度的数据丢失,否则在您的通信代码中包含某种错误检查总是谨慎的。即使是一个简单的校验和也比没有好。
除了信号电平质量(噪声、上升/下降时间)之外,UART 上的一个常见错误来源是时钟偏差。如果发送器时钟和接收器时钟不是来自同一源(大多数情况下都是这种情况),那么其中一个将比另一个运行得更快。当时序误差太大时,您可能偶尔会读到错误的位。
帧错误可能是由@jippie 提到的 - 接收器检测到起始位并且它期望停止位数据被反转。这也可能是由于线路干扰影响停止位而导致数据损坏。您总是需要检查收到的每个字节。
当在数据链路上实施奇偶校验并且存在导致接收数据中奇偶校验不匹配的损坏时,会发生奇偶校验错误。您总是需要检查收到的每个字节。
接收中断也被视为错误,尽管它确实表明传入数据已下降到逻辑零的时间超过 1 个字节的数据。通常逻辑 1 是连续数据字节之间的“环境”状态,并保持这种状态。我认为这是对旧电报系统的回归。除非您使用此“功能”向接收器指示(例如)重置命令,否则我不会费心检查这一点。
溢出错误是在 CPU 读取前一个字节之前接收到一个新字节。当涉及 FIFO 时略有不同,但等同于相同的事情 - 由于 CPU 速度缓慢,有效接收到的数据会丢失。在读取字节之前务必检查这一点,如果该字节是较长消息(或命令)的一部分,则将整个消息/命令扔掉,并以某种方式请求发送器重新发送整个消息/命令。
Under run 并不是真正的错误,而是向发送 UART 表明它的发送缓冲区是空的,即它正在请求一个新字节来发送。你不需要检查这个。
大多数错误源于三个原因:(1)发射机生成的信号不代表有效数据;(2) 发送器的信号在生成时没有被接收到,或者 (3) 接收器在接收到数据时还没有准备好处理数据。我看到的问题 #1 的最常见原因是发射器在传输数据时被重新配置或关闭。问题#2 很容易出现在信号通过“外部世界”传播的情况下,例如无线电干扰(移动电话可能非常讨厌!),但通常不会出现在单个板上的信号。问题 #3 可能是因为太多字节到达的速度超过了它们的处理速度,或者是因为接收器在传输过程中被重新配置、关闭或启动。
在许多情况下,很难完全消除所有这些问题;一个人的目标应该是确保他们造成的总“损害”(发生概率,每次发生的损害乘以)是可接受的低。最容易做到这一点的方法是选择对可靠性的悲观估计,然后设计一个协议,以便即使与估计一致的最严重故障对系统性能的影响也将在可接受的范围内。