是什么导致UART错误?


8

我想知道为什么会发生UART错误,以及何时应检查此类错误。这里有一篇帖子,询问如何处理单个错误,例如超限,奇偶校验等。我很清楚为什么会发生数据超限,为什么会发生奇偶校验错误,但是我想知道根本原因是什么。我的问题更集中于为什么会发生这些错误(物理原因),以及何时应将错误检查作为其应用的一个因素。

到目前为止,我的程序似乎运行良好(没有错误检查),但是我知道噪音可能会使事情变得混乱。如何模拟可能导致UART Rx / Tx端口出现故障的情况?

Answers:


8

任何电路中都有几种潜在的噪声源。一些最常见的包括:

  • 电源调节不良;
  • 开关电源;
  • MCU附近电源轨的电容去耦不足;
  • 附近电磁源的电感耦合(包括来自市电的50或60Hz;即使电路是由电池供电的,当距离市电足够近时,也会受到这种干扰);
  • 射频源靠近电路板上走线的谐振频率或其谐波之一;
  • 电路板上信号线附近的大电流走线的布线;
  • 等等。

此外(如@jippie所述),时钟偏斜是使用预定数据速率的任何类型的串行通信中常见的错误原因。如果您使用的是外部晶振并连接到可以合理预期是准确的另一个系统,则引起问题的可能性较小。然而,内部振荡器的容差可能比晶体差几个数量级,并且在整个温度范围内变化更大。

可以在正在运行的系统上执行一些基本测试,以确定接口的基本噪声(和偏斜)抗扰度,包括:

  • 冻结(将电路冷却至其组件的最小额定值);
  • 烘烤(加热至最大额定值);
  • 暴露于电磁干扰
    • 将板子放在运行空间加热器的电源线的顶部;
    • 在电路板附近锁上CB收音机;
    • 将板子放在无线路由器旁边;
    • 使用长连接线(而不是正确构造的串行电缆)进行UART连接。

还有很多其他的-实际上,有专门用于EMC认证的大型测试实验室。

通常,除非可接受最小程度的数据丢失,否则在通信代码中包括某种错误检查总是明智的。即使是简单的校验和总比没有好。


6

除了信号电平质量(噪声,上升/下降时间)以外,UART上的一种常见错误源是时钟偏斜。如果发送器时钟和接收器时钟不是来自同一源(大多数情况下是这种情况),那么一个将比另一个运行得更快。当时序误差太大时,您可能偶尔会读取错误的位。


如果将微控制器独自留在黑匣子中,谁知道谁在哪里,那将导致时钟偏斜?
user791953 2013年

1
自由运行的本地时钟。每个振荡器都有自己的精度。可以将MCU时钟分频为UART可用的频率,但有时会偏离一小部分。这又由除数是整数的事实引起。
jippie 2013年

例如。MCU时钟= 16MHz,UART波特率= 9600Bd。然后,UART通常以153600Hz为时钟。但是16000000/153600不是整数,因此波特率将关闭。
jippie 2013年

是的,那会带来很小的错误率。猜猜我很幸运没有遇到任何错误,但是如果它是关键数据,则应该始终进行检查。
user791953 2013年

较低的波特率,较高的时钟率(提高了采样分辨率和定时精度)。
jippie 2013年

1

大多数错误源于三个原因:(1)发射机产生的信号不代表有效数据;(2)接收器未接收到发送器的信号,或者(3)接收器未准备好在接收到数据时对其进行处理。我发现的问题#1的最常见原因是发送器在发送数据时被重新配置或关闭。由于诸如无线电干扰(移动电话可能令人讨厌,令人讨厌!)之类的结果,问题#2对于通过“外部世界”传播的信号很容易发生,但对于局限在单个板上的信号通常不会出现。问题#3的发生可能是由于到达字节的速度超过了其处理速度,或者是因为接收器在传输期间被重新配置,关闭或启动。

在许多情况下,很难完全消除所有这些问题。一个人的目标应该是确保他们造成的总“损害”(发生的概率,每次发生的损害倍数)低得可以接受。这可以很容易地通过选择对可靠性的悲观评估,然后设计一个协议,以使即使与人的评估相一致的最严重故障对系统性能的影响也将在可接受的范围内。


0

@jippie提到的内容可能会导致成帧错误-接收器已检测到起始位,并且在期望终止位的位置将数据反转。这也可能是由于线路干扰撞击到停止位引起的数据损坏。您始终需要为接收到的每个字节检查此内容。

当在数据链路上实现奇偶校验时,会发生奇偶校验错误,并且存在导致接收数据中奇偶校验不匹配的损坏。您始终需要为接收到的每个字节检查此内容。

接收中断也被认为是错误,尽管它实际上表明传入数据已下降到逻辑零的时间超过了1个字节的数据。通常,逻辑1是连续数据字节之间的“环境”状态,并且保持这种状态。我认为这是回溯到旧的电报系统。除非您使用此“功能”向接收器指示(例如)重置命令,否则我不会打扰检查它。

溢出错误是指在CPU读取前一个字节之前接收到一个新字节。当涉及FIFO时,情况略有不同,但具有相同的意义-由于CPU速度慢,有效的接收数据会丢失。始终在读取字节之前检查此内容,如果该字节是较长消息(或命令)的一部分,则丢弃整个消息/命令,并以某种方式请求发送方重新发送整个消息/命令。

运行下并不是真正的错误,但向发送UART指示其发送缓冲区为空,即它正在请求一个新的字节进行发送。您不需要检查。


我了解这些错误是什么以及为什么会发生,我的问题更多是围绕何时应该为它们提供错误检查的问题。
user791953 2013年

@ user791953-完成
安迪(aka Andy)

顺便说一句,对于大多数协议来说,欠载都不是问题,但是某些协议使用空闲线来指示数据包结束。在这种情况下,发送侧的欠载可能导致接收器错误地认为数据包在应有的时间之前就结束了。
超级猫

0

为了处理这些错误,您必须实现更高级别的逻辑协议。类似TCP的内容,或查看OSI堆栈以获取想法。

基本上,两个重要的部分开始是校验和和超时。使用一种算法来计算一个冗余值,该冗余值以较小的形式表示每个消息的内容。然后在收到的消息中进行检查。如果总和不匹配,则可能是出现了帧错误,比特噪声等,并且您将需要丢弃该消息并尝试某种恢复,重新发送,NACK(未确认)信号等。

此外,请确保在上层协议中实现超时。如果您遇到某种帧错误,则您的UART可能永远无法恢复并重新开始处理。它可能正在等待发送方UART认为已发送但已被噪声,时钟偏斜等损坏的帧上的停止位。这会将任何输入代码发送到无限循环中。确保您对输入读数应等待多长时间(直到决定放弃此消息)有一个理智的限制,然后再次尝试重试,NACK,放弃等。


超时需要在任何更高级别协议的至少一侧实现;在许多情况下,最好只在一侧实现它们。让一侧永远等待永不到达的数据只是一个问题,如果它本来可以做其他有用的事情。如果X向Y询问某些数据,则X必须准备好重新发送其请求,以防Y没收到它。但是,Y不必担心X是否得到他的回应。如果X没有收到,X将再次要求数据。X不再要求数据的事实意味着Y不需要重新发送它。
超级猫

@supercat对,这是一个很好的模式,但是我的目标是逐行编码。您将始终有一个循环,该循环正在读取数据,并试图弄清一条完整的消息是否准备就绪,如果一条完整的消息永不存在,则它可以挂起输入子系统,而不管是否有其他等待等待的消息。完成。在这种情况下,输入子系统至少需要意识到发生了故障,刷新所有垃圾数据并重置以进行另一次尝试。
安迪斯·史密斯

如果每个数据包都以在任何情况下都始终可以识别的字节序列开头,并且如果接收方没有任何用处,则接收方在收到完整的数据包之前可以执行任何操作,为什么还要注意接收部分数据包后是否要过几个小时呢?下次有人尝试发送真实数据包时,接收方将看到数据包开始标记并放弃部分数据包。
超级猫

@supercat,因为这样您就有了一个循环,该循环正在寻找多个事物。它仍在寻找部分数据包的结尾,并寻找新的,未损坏的数据包的开始。就实际情况而言,这使逻辑变得更加复杂,如果可以的话,可以边做边编码。
安迪斯·史密斯

我不太确定这是什么困难。如果使用接收字节循环,则在发生超时或看到起始字节的情况下必须中断循环。两种行为都需要以相同的方式进行处理,仅是因为开始序列应设置一个标志,因此寻找它的下一个代码不会打扰。
2013年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.