深度解析 8251 USART:微处理器的串行通信核心架构与实战指南

在微处理器系统的实际开发中,我们经常面临一个挑战:如何在 CPU 与外部设备之间建立高效、可靠的通信桥梁。虽然并行通信速度很快,但在长距离传输中,高昂的线缆成本和信号干扰让人头疼。这时,串行通信成为了我们的首选。而 8251 USART(通用同步/异步接收发送器)正是为此而生的经典芯片。今天,我们将深入探讨 8251 的内部机制,看看它是如何优雅地处理数据转换,以及我们如何在代码层面驾驭它。

前置知识:

在开始之前,建议你先了解一下 8259 PIC 的基本概念,因为中断处理往往是配合串行通信使用的。

8251 是什么?

简单来说,8251 是一个可编程通信接口芯片。它的核心任务是充当微处理器与外设之间的“翻译官”。我们利用它将 CPU 内部的并行数据转换为外设能理解的串行数据,反之亦然。这种转换对于调制解调器、终端、打印机等外设至关重要。

它的工作流程通常包含以下几个步骤:

  • 接收: 从外设接收串行数据流。
  • 转换: 将这些串行位重新组装成并行字节。
  • 传输: 将组装好的并行数据发送给 CPU。

同样的流程也反向适用于 CPU 发送数据给外设:从微处理器接收并行数据 -> 转换为串行形式 -> 传输到外部设备。

8251 的内部架构:深入核心

要精通 8251,我们不能只停留在表面。让我们打开“引擎盖”,看看它的内部框图主要由哪些模块构成,以及它们是如何协同工作的。

#### 1. 数据总线缓冲器

这是 8251 与系统数据总线的接口。你可以把它想象成一个“中转站”。它帮助连接 8251 的内部总线与系统的外部数据总线。无论是 CPU 发出的控制字、要发送的数据,还是 CPU 从 8251 读取的状态信息,都必须经过这个缓冲器。它的存在确保了 8251 能够与 CPU 的数据总线无缝对接。

#### 2. 读/写控制逻辑

这是整个芯片的“大脑”或控制中心。它管理着数据的流向和设备的操作模式。这个逻辑单元根据输入的信号(如 CS, WR, RD, C/D)来决定执行什么操作。

  • 操作选择机制: 通过组合控制信号,该单元会选择三个关键寄存器之一进行操作:

* 数据缓冲寄存器: 存放实际要发送或接收的数据。

* 控制寄存器: 存放由 CPU 编程的指令,决定波特率、字符长度等。

* 状态寄存器: CPU 可以读取这个寄存器来检查 8251 的当前状态(比如是否有错误,是否准备好接收数据)。

#### 3. 调制解调器控制

这一模块是为了与调制解调器或其他外设直接连接而设计的。它处理握手信号,确保双方都准备好了。

以下是几个关键的低电平有效引脚,我们需要特别留意:

  • DSR (Data Set Ready): 输入信号。告诉 8251,调制解调器或外设已经准备好了。
  • DTR (Data Terminal Ready): 输出信号。CPU 通过 8251 发出此信号,告诉外设:“终端(也就是我们的计算机)准备好了”。
  • CTS (Clear to Send): 输入信号。这是数据发送的控制闸门。只有当 CTS 有效时,发送器才能发送数据。
  • RTS (Request to Send): 输出信号。用于通知调制解调器,终端请求发送数据。

#### 4. 发送缓冲器与发送控制

发送部分负责将数据从并行格式“压缩”成串行位流。

  • 发送缓冲器: 它本质上是一个并串转换器。它接收 CPU 发来的并行字节,将其转换为串行信号,并通过 TXD 引脚传输出去。
  • TXD (Transmitter Data): 这是串行数据的输出线。当 TXD 为高电平时,可能处于空闲状态或发送逻辑 ‘1‘(具体取决于协议)。
  • TXRDY (Transmitter Ready): 这是一个输出信号(或状态位)。当它为真时,就像 8251 在对 CPU 喊:“我现在的缓冲区空了,你可以给我发新数据了!”
  • TXEMPTY (Transmitter Empty): 这个信号表示发送器已经完全空了,连最后一位数据都发出去了。这通常用于在双工通信中切换方向或停止传输。
  • TXC (Transmitter Clock): 输入引脚。它控制着数据发送的速率。波特率通常是 TXC 频率的倍数(如 1倍、64倍等),具体取决于模式设定。

#### 5. 接收缓冲器与接收控制

接收部分的工作则是逆过程,并负责检测错误。

  • 接收缓冲器: 负责接收串行数据并将其组装成并行数据,供 CPU 读取。
  • RXD (Receiver Data): 串行数据的输入引脚。
  • RXRDY (Receiver Ready): 输出信号。当 8251 接收到一个完整的字符并准备好被 CPU 取走时,该信号置位。这通常连接到 CPU 的中断请求线。
  • RXC (Receiver Clock): 控制接收速率的输入时钟。
  • SYNDET/BD (Sync Detect/Break Detect): 这是一个双功能引脚。在同步模式下,它用于检测同步字符;在异步模式下,它可以用来检测“断点”信号。

实战代码示例与编程指南

了解了硬件结构后,让我们通过代码来看看如何实际驱动它。在编写代码时,我们需要遵循严格的初始化序列。

#### 场景 1:初始化 8251

在使用 8251 之前,我们必须先对它进行“配置”。这通常包括向控制口写入模式指令和命令指令。

; 假设 8251 的数据口地址为 80H,控制口地址为 81H

; 步骤 1: 写入模式指令
; 这里我们需要定义:波特率因子、字符长度、校验位、停止位
; 示例配置:波特率因子为16 (异步), 8位数据, 无校验, 1位停止位
; 对应的二进制控制字:0100 1111 (4FH)
MVI A, 4FH   
OUT 81H      ; 将模式字写入控制口

; 步骤 2: 写入命令指令
; 配置:使能发送器、使能接收器、复位错误标志
; 对应的二进制控制字:0001 0101 (15H)
MVI A, 15H   
OUT 81H      ; 将命令字写入控制口

; 此时 8251 已准备好工作

代码解析:

在这个例子中,我们首先发送了 INLINECODEaab40f1b。为什么要这样做?在硬件层面上,8251 内部有一个状态机。上电后,它期待第一个字节是模式指令。INLINECODEcf095a55 告诉它:“嘿,我们要用异步模式,波特率是时钟的 1/16,数据是 8 位的。”

紧接着,我们发送 INLINECODEc09f4665。这是命令指令。如果不发送这个,发送器和接收器可能处于关闭状态。INLINECODE7d17c3ec 就像按下了“启动”按钮,并清除了任何可能存在的旧错误标志。

#### 场景 2:发送一个字符

现在 8251 已经初始化好了,让我们尝试向终端发送一个字符 ‘A‘。

; 函数:发送字符 ‘A‘ 到串口

SEND_CHAR:
    MVI A, ‘A‘       ; 将 ‘A‘ 的 ASCII 码加载到累加器

CHECK_TX_READY:
    IN 81H           ; 读取状态寄存器
    ANI 01H          ; 检查第 0 位 (TXRDY - Transmitter Ready)
    JZ CHECK_TX_READY ; 如果 TXRDY 为 0,继续等待(轮询)

    ; 如果 TXRDY 为 1,发送器准备好
    OUT 80H          ; 将字符数据写入数据口
    RET              ; 返回

代码解析:

这里我们展示了最基础的轮询方式。INLINECODE073058dc 读取状态口。通过 INLINECODE0dfab9b0(AND Immediate 01H),我们屏蔽了其他位,只关心第 0 位(TXRDY)。如果发送器忙(比如正在把前一个数据移位出去),TXRDY 就是 0,我们就死循环等待。这是一种最简单但效率稍低的同步方式。

#### 场景 3:接收数据并处理

接收数据通常需要处理错误,比如奇偶校验错误或溢出错误。

; 函数:接收字符并回显

RECEIVE_CHAR:
    ; 1. 检查接收器是否准备好
    IN 81H           ; 读取状态寄存器
    ANI 02H          ; 检查第 1 位 (RXRDY - Receiver Ready)
    JZ RECEIVE_CHAR  ; 如果没收到数据,继续等待

    ; 2. 检查是否有错误
    ; 状态寄存器第 2、3、4 位分别代表奇偶错、溢出错、帧错
    IN 81H
    ANI 38H          ; 0011 1000 (检查 Bit 3,4,5)
    JNZ ERROR_HANDLER; 如果有错误,跳转到错误处理

    ; 3. 读取数据
    IN 80H           ; 从数据口读取字符
    ; 此时 A 寄存器中保存了接收到的字符

    ; 4. 简单的回显操作 - 发送回去
    PUSH PSW         ; 保存接收到的字符
    CALL SEND_CHAR   ; 调用上面的发送函数(假设已修改为通用函数)
    POP PSW          ; 恢复环境
    RET

ERROR_HANDLER:
    ; 在这里进行错误复位或记录
    MVI A, 10H       ; 发送复位错误命令
    OUT 81H
    RET

实战见解:

在实际应用中,你可能会遇到“溢出错误”。这通常发生在 CPU 处理上一个数据太慢,而 8251 又收到了新数据的时候。上面的代码通过检查状态位展示了如何防范这种情况。一旦检测到错误,写入特定的命令字(如 10H)可以复位错误标志,让芯片恢复工作。

#### 场景 4:中断驱动模式

虽然上面的轮询代码很简单,但在现代系统中,我们更倾向于使用中断来提高 CPU 效率。这需要将 8251 的 TXRDY 或 RXRDY 引脚连接到 8259 PIC(中断控制器)。

; 假设 RXRDY 连接到了 IRQ3
; 这是一个伪代码级别的中断服务程序 (ISR)

SERIAL_ISR:
    PUSH PSW         ; 保护寄存器
    PUSH B

    IN 81H           ; 读取状态,判断是发送还是接收中断
    ; 注意:这取决于硬件连接,如果只有接收中断
    ANI 02H          
    JZ ISR_END       ; 如果不是接收就绪,退出

    IN 80H           ; 读取数据
    STA BUFFER_PTR   ; 存储到内存缓冲区

ISR_END:
    POP B
    POP PSW
    EI               ; 重新开中断
    RET              ; 从中断返回

8251 USART 的优缺点:权衡的艺术

在项目选型时,我们需要客观地评估工具的优劣。8251 作为一个经典的芯片,既有它的辉煌之处,也有时代的局限性。

#### 优点:

  • 多功能性: 8251 最大的卖点在于它的灵活性。它可以通过编程支持同步(如 IBM 的 Bi-Sync)和异步(如我们常用的 RS-232)两种模式。这种“双模”能力在当时极大地简化了系统设计。
  • 错误检测: 它内置了基本的错误检测机制,主要包括奇偶校验、帧错误检测和溢出检测。虽然不如现代的 CRC 复杂,但在低速通信中足以保证数据的准确性。
  • 流量控制: 支持 CTS 和 RTS 等标准硬件流控信号。这对于防止高速发送时低速接收端“吃不消”导致的数据丢失至关重要。
  • 兼容性: 它与许多经典的微处理器(如 8080, 8085, Z80)兼容,总线接口逻辑非常简单,甚至能直接连接到某些 8 位数据总线上。
  • 易用性: 相比于用分立逻辑电路搭建串行接口,8251 的编程相对简单,只需要几个端口 OUT/IN 指令即可控制。

#### 缺点:

  • 速度有限: 这是物理层面的限制。8251 的设计年代决定了它通常工作在几百 kbps 以下(如常见的 19.2 kbps 或 115.2 kbps)。对于现在动辄 Mbps 级别的 USB 或以太网通信,它完全无法胜任。
  • 缓冲区大小有限: 8251 内部通常只有单字节的缓冲。这意味着如果 CPU 没有在下一个字节到达前读取当前字节,就会发生溢出错误。这对中断响应时间或轮询速度提出了较高要求。
  • 编程复杂度: 虽然基本的 I/O 简单,但要正确配置其同步模式或错误处理,需要深厚的硬件知识。时序问题是新手最容易踩的坑。
  • 成本与集成度: 虽然单颗芯片便宜,但在现代设计中,使用独立的 UART 芯片增加了板级空间和成本。现代微控制器(如 STM32, AVR)大多将 UART 集成在芯片内部,不再需要外挂 8251。
  • 功能局限: 它不支持 DMA(直接内存访问)传输,所有的数据都必须经过 CPU 中转。这使得它在处理大量数据传输时会占用大量 CPU 资源。

实际应用中的最佳实践与常见陷阱

在多年的嵌入式开发经验中,我们总结了一些使用 8251 或类似 UART 芯片的“避坑指南”:

  • 时序是关键: 在初始化时,务必确保先发送模式指令,再发送命令指令。如果顺序错了,芯片会进入未知状态。最简单的解决方法?系统上电时先复位(RESET)芯片。
  • 不要忽视时钟: TXC 和 RXC 的频率必须与波特率设置严格匹配。例如,如果配置为 16 倍波特率因子且需要 9600 bps 的速度,那么你的时钟引脚必须输入 $9600 \times 16 = 153.6 \text{ kHz}$ 的信号。误差过大会导致乱码。
  • 处理回显: 在调试串口终端时,如果配置为本地不回显,你需要自己在代码里将 RXD 收到的数据发回 TXD。否则,用户敲键盘时屏幕上什么都不会显示,会被误以为死机了。
  • 利用状态轮询: 在极端关键的任务中,不要完全依赖中断。有时简单的“查询状态位 – 读取数据”循环比复杂的中断系统更稳定,尤其是在干扰较强的工业环境中。

总结与后续步骤

在本文中,我们深入剖析了 8251 USART 这一经典的微处理器接口芯片。从它的内部数据总线缓冲器到调制解调器控制逻辑,从基本的数据并串转换到实际的汇编代码实现,我们见证了它如何通过简单的寄存器操作实现复杂的通信任务。

虽然现代技术已经超越了 8251 的物理限制,但理解它对于掌握计算机底层通信原理、总线时序以及 I/O 控制依然具有不可替代的教育价值。

作为接下来的学习步骤,建议你尝试:

  • 搭建一个简单的 8051 或 8086 仿真电路,连接一个虚拟的 8251。
  • 编写一个程序,实现键盘输入并回显到屏幕(全双工回显测试)。
  • 尝试修改波特率因子,观察数据传输速率的变化。

希望这篇指南能帮助你更好地理解微处理器的串行通信世界。动手试试吧,你会发现底层硬件编程的乐趣!

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。如需转载,请注明文章出处豆丁博客和来源网址。https://shluqu.cn/41253.html
点赞
0.00 平均评分 (0% 分数) - 0