Answers:
任何电路中都有几种潜在的噪声源。一些最常见的包括:
此外(如@jippie所述),时钟偏斜是使用预定数据速率的任何类型的串行通信中常见的错误原因。如果您使用的是外部晶振并连接到可以合理预期是准确的另一个系统,则引起问题的可能性较小。然而,内部振荡器的容差可能比晶体差几个数量级,并且在整个温度范围内变化更大。
可以在正在运行的系统上执行一些基本测试,以确定接口的基本噪声(和偏斜)抗扰度,包括:
还有很多其他的-实际上,有专门用于EMC认证的大型测试实验室。
通常,除非可接受最小程度的数据丢失,否则在通信代码中包括某种错误检查总是明智的。即使是简单的校验和总比没有好。
除了信号电平质量(噪声,上升/下降时间)以外,UART上的一种常见错误源是时钟偏斜。如果发送器时钟和接收器时钟不是来自同一源(大多数情况下是这种情况),那么一个将比另一个运行得更快。当时序误差太大时,您可能偶尔会读取错误的位。
大多数错误源于三个原因:(1)发射机产生的信号不代表有效数据;(2)接收器未接收到发送器的信号,或者(3)接收器未准备好在接收到数据时对其进行处理。我发现的问题#1的最常见原因是发送器在发送数据时被重新配置或关闭。由于诸如无线电干扰(移动电话可能令人讨厌,令人讨厌!)之类的结果,问题#2对于通过“外部世界”传播的信号很容易发生,但对于局限在单个板上的信号通常不会出现。问题#3的发生可能是由于到达字节的速度超过了其处理速度,或者是因为接收器在传输期间被重新配置,关闭或启动。
在许多情况下,很难完全消除所有这些问题。一个人的目标应该是确保他们造成的总“损害”(发生的概率,每次发生的损害倍数)低得可以接受。这可以很容易地通过选择对可靠性的悲观评估,然后设计一个协议,以使即使与人的评估相一致的最严重故障对系统性能的影响也将在可接受的范围内。
@jippie提到的内容可能会导致成帧错误-接收器已检测到起始位,并且在期望终止位的位置将数据反转。这也可能是由于线路干扰撞击到停止位引起的数据损坏。您始终需要为接收到的每个字节检查此内容。
当在数据链路上实现奇偶校验时,会发生奇偶校验错误,并且存在导致接收数据中奇偶校验不匹配的损坏。您始终需要为接收到的每个字节检查此内容。
接收中断也被认为是错误,尽管它实际上表明传入数据已下降到逻辑零的时间超过了1个字节的数据。通常,逻辑1是连续数据字节之间的“环境”状态,并且保持这种状态。我认为这是回溯到旧的电报系统。除非您使用此“功能”向接收器指示(例如)重置命令,否则我不会打扰检查它。
溢出错误是指在CPU读取前一个字节之前接收到一个新字节。当涉及FIFO时,情况略有不同,但具有相同的意义-由于CPU速度慢,有效的接收数据会丢失。始终在读取字节之前检查此内容,如果该字节是较长消息(或命令)的一部分,则丢弃整个消息/命令,并以某种方式请求发送方重新发送整个消息/命令。
运行下并不是真正的错误,但向发送UART指示其发送缓冲区为空,即它正在请求一个新的字节进行发送。您不需要检查。
为了处理这些错误,您必须实现更高级别的逻辑协议。类似TCP的内容,或查看OSI堆栈以获取想法。
基本上,两个重要的部分开始是校验和和超时。使用一种算法来计算一个冗余值,该冗余值以较小的形式表示每个消息的内容。然后在收到的消息中进行检查。如果总和不匹配,则可能是出现了帧错误,比特噪声等,并且您将需要丢弃该消息并尝试某种恢复,重新发送,NACK(未确认)信号等。
此外,请确保在上层协议中实现超时。如果您遇到某种帧错误,则您的UART可能永远无法恢复并重新开始处理。它可能正在等待发送方UART认为已发送但已被噪声,时钟偏斜等损坏的帧上的停止位。这会将任何输入代码发送到无限循环中。确保您对输入读数应等待多长时间(直到决定放弃此消息)有一个理智的限制,然后再次尝试重试,NACK,放弃等。