检测软件 UART 中的起始位

电器工程 UART
2022-01-28 07:37:21

我正在尝试使用 GPIO 引脚在我的微控制器上编写软件 UART。这是在项目中临时添加一个 UART 通道,直到我们实现使用具有更多 UART 端口的 uC 的新设计。

我遇到的困难是正确检测串行流中的起始位。流的来源是外部的,并不关心我的设备何时启动。因此,我的设备很可能会打开电源并开始在字节传输中间看到数据位。毫无疑问,这将导致我的软件 UART 读取错误值,因为它无法区分起始位和任何其他从高到低的转换。

这是 UART 通道不可避免的问题吗?还是 uC 制造商在他们的硬件 UART 中使用了一些巧妙的技巧?

3个回答

如果您使用的停止位长度很容易从数据流的其余部分中辨别出来,例如 1.5 位时间,那么应该很容易在传输过程中开始接收。然而,这是以增加开销为代价的。随着停止位长度的增加,您的总可用数据吞吐量将受到影响。

如果您没有大量使用总线,并且经常在帧之间存在间隙,那么可能只是等待其中一个间隙发生,然后将第一个高低传输作为您的开始下一个起始位。

请记住,数据位的数量应该是可预测的,帧大小也应该是可预测的,因此即使您使用 100% 的总线容量并且您的停止位是单个位时间,您仍然应该能够找到如果您收集了足够的帧,请开始位。保证每一帧都有一个高低过渡。停止位始终为高位。起始位始终为低位。假设您的数据是随机的(或足够随机的),您可以做一些简单的事情,例如创建一个与帧大小相同的缓冲区,设置其中的每一位,然后继续收集帧并将它们与此缓冲区进行 AND 运算,直到缓冲区只有 1位设置。该位是您的停止位。后面的那个是你的开始位。瞧!你已经找到了。

如果您使用奇偶校验位,另一种选择是获取两帧数据,选择第一个低位作为起始位,然后计算校验和并与奇偶校验位进行比较。如果匹配,那么您(可能)找到了起始位。如果不是,请选择下一个低位并重复,直到获得良好的校验和。如果您在两帧数据中找不到作为有效起始位校验的位,那么您的数据已损坏,您需要再抓取两帧。

硬件 UART 也有同样的问题。但无论如何,它通常会在短时间内自行解决。在每一帧结束时,检查停止位,如果它不为高,则丢弃该帧并等待下一次从高到低的转换。假设来自源的数据不是完全病态的(例如,“UUUU”的长字符串,或 ASCII 0x55),UART 最终将自己“走”到真正的起始位。

假设8N1传输。

您必须连续等待一串 9 个高位或低位。

如果为高,则表示数据中的空闲间隙或 0xFF 字符和 STOP 位
,或者
如果为低,则表示 START 位和 NULL 0x00 字符。

这些条件中的任何一个都将允许重新同步。

加快速度:如果您知道数据中不可能出现的某些字符,您可以重复(事后)解析每个位的传入数据,并且如果您得到一系列 7 个无意义的字符(高位设置,低位设置)大小写,控制代码,标点符号或其他)后跟一个有效字符,您可以相当确定您已重新同步。

当您使用内置 UART 外设并且无法进行按位评估时,您将遇到类似的问题,并且还必须记住在发生时重置所有帧错误位等(尤其是在上电时)。