跳转到内容

串行编程/典型RS232硬件配置

来自维基教科书,开放的书籍,开放的世界

此页面概述了典型的串行RS232硬件配置,这种配置可以在各种计算机和设备中找到。它应该作为对某些串行硬件的直接编程的指南和介绍。

所提供的信息本质上是通用的,因为某些设备或计算机中可以找到的实际串行硬件确实有所不同。如今,硬件通常集成在一个单一的芯片中,甚至包含许多其他功能,例如并行端口,这些功能与串行通信无关。然而,本模块提供了关于哪些逻辑或物理组件执行什么以及串行硬件的实际编程发生在哪里的良好概述。

相关组件

[编辑 | 编辑源代码]

下图概述了相关组件以及它们如何原则上连接

RS232      +-----------+   +-----------+   +-----------+   +-----------+
Interface  | Line      |   |           |   | Interface |   |           |
-----------+ Driver /  +---+   UART    +---+ Logic     +---+    CPU    |
           | Receiver  |   |           |   |           |   |           |
           +-----------+   +-----+-----+   +-----+-----+   +-----------+
                                 |               |
                                 |               |
                           +-----+-----+         |
                           | Baud Rate |         |
                           | Generator +---------+
                           |           |
                           +-----------+

我们将依次讨论这些组件及其用途。

线路驱动器/接收器

[编辑 | 编辑源代码]

RS-232通信使用高达±15V的电压(一些早期规格甚至使用±25V)。它使用反向逻辑(高/真/1 是负电压,低/假/0 是正电压)。这些电压对于现代(甚至更旧的)计算机逻辑来说太高了。因此,RS-232接口通常包含特殊的硬件,即所谓的线路驱动器和线路接收器。

线路驱动器负责将典型的计算机电压逻辑转换为 RS-232 线路上使用的较高电压,并反转逻辑。当计算机硬件传输串行数据时,这将被使用。电压输出通常是连续的短路安全的,因为 RS-232 标准要求这样做。

线路接收器负责线路驱动器的反向操作。它将传入的 RS-232 信号转换为适合计算机逻辑的电压,并且它当然也反转逻辑。

实际上,通常使用多个线路驱动器和接收器,因为 RS-232 电缆中的每个传入 RS-232 信号都需要自己的接收器,每个传出的 RS-232 信号都需要自己的驱动器。但是,多个驱动器/接收器通常组合在一个芯片中。该芯片本身也保护计算机逻辑免受可能发生在串行线上的尖峰。一些线路驱动器/接收器芯片甚至在芯片上生成所需的 RS-232 电压,而另一些则需要外部电源来提供这些电压。

线路驱动器/接收器通常不可编程。它们被硬连线到逻辑中,因此对于程序员来说并不重要。

另请参阅

UART(通用异步接收器/发送器)是串行硬件的核心。它是一个芯片或芯片的一部分,其目的是在并行数据和串行数据之间转换。RS-232 UART 通常还会在传输时添加必要的开始/停止位和奇偶校验位,并在接收时解码这些信息。

UART 通常完全在计算机逻辑电压下工作。其串行数据输入/输出电压是计算机逻辑电压,而不是串行线路电压。它们将实际线路接口留给特定的线路驱动器/接收器。该线路驱动器/接收器不一定需要是 RS-232 线路驱动器/接收器,但可以是例如 RS-422 差分驱动器/接收器。这,以及波特率、奇偶校验、停止位数量、数据位数量可编程的事实是 UART 被称为“通用”的原因。当 UART 和线路驱动器/接收器都放置在同一芯片中时,它们之间的区别就会变得模糊。此类芯片通常也以“UART”的标签出售。

UART 被称为“异步”,因为它们不使用特殊的时钟信号来与远程端同步。相反,它们使用开始/停止位来识别串行流中的数据位。
由于 UART 的存在,其余硬件以及软件应用程序可以处理正常的字节来保存通信数据。UART 的工作是在发送时将字节分成一系列串行位,并在接收时将一系列位组装成字节。UART 通常包含 8 位宽的接收器和发送器缓冲器。如果使用 7 位传输等,则可能不会使用所有位。接收到的串行数据以并行方式提供给接收器缓冲器,要发送的数据以并行方式写入发送器缓冲器。根据 UART 的不同,缓冲器可能只有一个字节的深度,也可能只有几个字节的深度(在 15 或 16 字节范围内)。缓冲器越浅,CPU 与之的通信就需要越精确。例如,如果接收器缓冲器只有一个字节的深度,并且数据没有被足够快地获取,那么下一个接收到的数据可能会覆盖接收器缓冲器中之前接收到的数据,并且之前接收到的数据将丢失。

由于串行接口上的时序非常重要,因此 UART 通常连接到波特率发生器,该发生器可以是 UART 芯片中的内部发生器,也可以是外部发生器。

USART(通用同步/异步接收器/发送器)是 UART 的一个版本,它也可以同步通信。许多现代 IC 都具有此功能。但是,由于 RS232 是异步工作的,因此 USART 的同步功能不用于串行通信。根据 USART 的特定类型,同步功能要么在启动时关闭,要么需要关闭。一旦关闭,USART 对于 RS232 通信来说就是一个 UART。

波特率发生器

[编辑 | 编辑源代码]

工作原理

[编辑 | 编辑源代码]

波特率发生器是一个振荡器。它提供一个频率信号,用于控制串行接口的时序。由于不同的线路速度需要不同的时序,因此波特率发生器需要具有灵活性。

实现灵活波特率发生器有两种一般方法。波特率发生器本身是可编程的,可以产生必要的不同频率,或者 UART 有一个可编程的除法器或乘法器,它将来自波特率发生器的频率转换为所需的频率。观察者可能已经注意到,典型的波特率(300bps、600bps、1200bps、2400bps、9600bps(4 x 2400bps)等)之间存在固定的关系。这简化了使用频率除法器或乘法器来生成所需时序的过程。

根据实际的 UART,波特率发生器需要是某些外部组件,或者直接集成到 UART 芯片中。从外部来看,对波特率发生器的程序性更改是控制串行连接速度的手段。通常在对波特率进行编程时,不会以“明文”的形式提供所需的波特率,而是需要提供一些除法器或系数。要提供正确的除法器或系数,需要了解所用波特率发生器的基本频率。

振荡器与神奇石英晶体值

[编辑 | 编辑源代码]

RS-232 通信是异步的。因此,没有明确的方式,没有共享时钟信号,发射器和接收器如何同步。相反,它们在起始位上同步,并进一步假定一定的位长。位长是波特率的直接函数。例如,RS-232 上的 9600 波特意味着每秒传输 9600 位。因此,每个位长为 1/9600 秒。为了确保发射器和接收器假定相同的位长,它们需要使用相同的波特率。并且通信双方的波特率需要精确到一定程度。否则,数据传输将失败。当两侧的波特率没有很好地对齐时,常见的错误是帧错误、错误接收或丢失的位。

波特率发生器,因为它生成发送和接收数据的时钟频率,负责提供所需的波特率精度。经验法则是,波特率的总差异在最坏情况下不应超过 +/- 4%。如果将这个“误差预算”平均分配到双方,这意味着每边的波特率需要保持在标称值的 +/- 2% 以内。实际上,应该避免最坏的情况,并将波特率至少保持在每边的 +/- 1% 以内。

通常使用石英晶体振荡器来构建波特率发生器,其初始精度、温度漂移和长期漂移适用于 RS-232。也就是说,波特率发生器基于振荡器,而振荡器又使用石英晶体作为参考。更简单的振荡器,如 RC 振荡器,通常不够好。

通常,所有晶体振荡器电子设备都内置在波特率发生器 IC 中。如果使用具有集成波特率发生器的 UART,该 UART 通常包含电子设备。通常只需要添加石英晶体。

为了实现常见的波特率,石英晶体的频率值需要具有某些“神奇”值。这些值乍一看似乎相当奇怪。但是,它们通常是 300(通常支持的最低波特率)或 25(对于 25、50、75、150 的极低波特率)的倍数,以及二的幂。使用二的幂是因为将频率除以二的幂很容易,从而使可配置或可编程波特率发生器成为可能。

例如,将相当奇怪的晶体频率 4.915200 MHz 除以 256(二的幂),得到 19200 Hz 的良好值。频率为 4.915200 MHz 的晶体被称为波特率晶体神奇晶体。下表列出了常见的波特率晶体频率。

  • 1.8432 MHz、3.6864 MHz、4.9152 MHz、5.5296 MHz、6.1440 MHz、7.3728 MHz、9.8304 MHz
  • 11.0592 MHz、12.2880 MHz、12.9024 MHz、14.7456 MHz、16.5888 MHz、18.4320 MHz、19.6608 MHz
  • 20.2752 MHz、22.1184 MHz、23.9616 MHz、25.8048 MHz、27.6480 MHz、29.4912 MHz
  • 31.3344 MHz、33.1776 MHz、35.0208 MHz、36.8640 MHz

使用哪个晶体频率取决于所使用的波特率发生器/UART。应查阅波特率发生器/UART 的数据表以获取详细信息。

接口逻辑

[编辑 | 编辑源代码]

UART 和波特率发生器只是芯片,或者可以是更大芯片的组件。为了简化讨论,我们假设它们是一个芯片。该芯片通常有一堆引脚,这些引脚需要以某种方式由 CPU 写入或读取。因此,CPU 需要有一种方法来寻址芯片以与之通信。芯片还需要一种方法在某些情况下让自身被听到。

接口逻辑的职责是提供这种连接。逻辑在不同的系统架构之间差异很大。一种常用的技术是将 UART 的发送和接收缓冲区映射到 CPU 的内存地址空间。这样,它们在 CPU 看来就像普通的内存。另一种方法是将这些缓冲区连接到某些 CPU 特定的 I/O 端口。除了发送和接收缓冲区外,CPU 还必须能够访问 UART 的控制线、波特率、奇偶校验和字符大小编程接口。

由于 UART 无法缓冲无限量的传入数据(有些只能在接收缓冲区中缓冲一个字节),因此 CPU(或某些其他硬件)需要“足够快”地从 UART 读取数据。CPU 可以连续轮询 UART 以检查是否有新数据可用,或者 UART 可以通知何时有新数据准备就绪。这种通知通常通过 CPU 中断完成。接口逻辑的职责是代表 UART 触发这种中断。两种机制(轮询或中断驱动)都有优点和缺点。

在另一个方向上,在发送数据时,存在类似的问题。CPU 需要“足够快”地将数据传递给 UART,以防止缓冲区下溢。这并不致命,但会降低串行通信的性能和效率。CPU 也可以“太快”地将数据传递给 UART,导致 UART 中的发射器缓冲区溢出。这可以通过轮询(CPU 检查 UART 是否准备好发送)或通过中断(UART 告诉 CPU 它需要更多数据)来控制。同样,接口逻辑必须提供完成这两种操作模式的方法。

接口逻辑决定了程序员如何以及在何处找到他们想要编程的 UART,以及他们可以使用哪些操作模式(轮询、中断驱动)来传输和接收数据。例如,在现代 PC 中,接口逻辑在一定程度上是可编程的。但是,这通常由 BIOS 完成(设置 I/O 地址和中断号)。在较旧的 PC 和许多其他计算机中,接口逻辑不可编程。从应用程序程序员的角度来看,很少需要编程接口逻辑。通常将其视为硬连线逻辑。

为了编程特定的硬件,需要了解

  • 如何访问 UART 和波特率发生器(接口逻辑如何工作)。这通常需要了解一些 I/O 或内存地址。
  • UART 和波特率发生器的通信方式(接口逻辑是否提供轮询或中断,或者两者都提供?)。
  • 如何编程 UART。为此,拥有 UART 的数据表非常有用。
  • 如何编程波特率发生器,它可能只是 UART 芯片的一部分。

或者,使用操作系统的串行编程 API,该 API 应该了解所有这些内容,并“做正确的事”。

进一步阅读

[编辑 | 编辑源代码]
  • 页面 编程 8250 UART 提供了在特定硬件组合中编程特定 UART 的详细信息。
华夏公益教科书