Files
final-exam/接口与通讯技术/复习文档/8254定时计数器.md
T

187 lines
6.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
tags:
- 接口与通讯技术
- 定时器
- 计数器
- 可编程芯片
create time: 2026-06-26 23:05
---
# 8254 定时计数器
## 概述
8254(兼容 8253)是 Intel 公司生产的可编程定时/计数器芯片(Programmable Interval Timer, PIT),**在全部 4 套试卷中均有出现**,其中 **方波产生和计数初值计算** 是最高频题型。芯片内部包含 3 个独立的 16 位计数器,每个计数器有 6 种工作方式。
> [!tip] 考试要点
> - **计数初值计算**:`计数初值 = CLK频率 / 输出频率`
> - **方式 3(方波发生器)** 是最常考的工作方式
> - **控制字编写**:计数器选择 + 读写格式 + 工作方式 + 数制选择
> - **BCD 与二进制** 初值装入的区别
## 正文
### 1. 内部结构
```mermaid
graph TB
A["数据总线缓冲器 D0~D7"] --> B["读/写逻辑"]
B --> C["计数器 0"]
B --> D["计数器 1"]
B --> E["计数器 2"]
C --> F["CLK0, GATE0, OUT0"]
D --> G["CLK1, GATE1, OUT1"]
E --> H["CLK2, GATE2, OUT2"]
```
每个计数器有 3 条信号线:
| 信号 | 方向 | 功能 |
|------|------|------|
| **CLK** | 输入 | 时钟输入,每个下降沿使计数值减 1 |
| **GATE** | 输入 | 门控信号,控制计数的启动/暂停/触发 |
| **OUT** | 输出 | 根据工作方式输出不同波形 |
> [!question] 思考题
> 8254 的计数器是递增还是递减计数?计数值减到 0 后会怎样?
>
> 答:**递减计数**。装入初值后每来一个 CLK 下降沿计数值减 1。减到 0 后的行为取决于工作方式——方式 0 停止,方式 2/3 自动重装初值继续计数。
### 2. 端口地址
8254 占用 **4 个端口地址**:
| A1 A0 | 选中 | 说明 |
|:------:|:----:|------|
| 0 0 | 计数器 0 | 读写计数初值 |
| 0 1 | 计数器 1 | 读写计数初值 |
| 1 0 | 计数器 2 | 读写计数初值 |
| 1 1 | 控制寄存器 | 只写,用于写入控制字 |
> [!note] 每个计数器占用 1 个还是 2 个地址?
> 每个计数器只占用 **1 个端口地址**。16 位初值通过同一地址分两次写入(先低字节后高字节)。整个芯片共需 4 个端口地址。
### 3. 控制字格式
控制字写入控制寄存器(A1A0=11 的端口),格式如下:
```
D7 D6 D5 D4 D3 D2 D1 D0
[计数器] [读写格式] [工作方式] [数制]
00=计数器0 00=锁存 000=方式0 0=二进制
01=计数器1 01=仅低字节 001=方式1 1=BCD
10=计数器2 10=仅高字节 010=方式2
11=先低后高 011=方式3
100=方式4
101=方式5
```
> [!example] 控制字速算
> **要求**:计数器 0,方式 3(方波),先低后高,二进制
>
> D7D6=00(计数器 0), D5D4=11(先低后高), D3D2D1=011(方式 3), D0=0(二进制)
>
> 控制字 = `0011 0110B` = **36H**
>
> **要求**:同上但 BCD 计数 → D0=1 → 控制字 = **37H**
### 4. 六种工作方式
> [!tip] 考试重点
> 方式 2 和方式 3 的区别几乎每卷必考!
| 方式 | 名称 | 输出波形 | 触发 | 自动重装 | 典型应用 |
|:----:|------|----------|------|:--------:|----------|
| 0 | 计数结束中断 | 计数到 0 后 OUT 变高 | 软件 | 否 | 定时中断 |
| 1 | 可编程单稳态 | 触发后输出 N 个 CLK 宽度的负脉冲 | 硬件 | 否 | 单稳态触发器 |
| 2 | **频率发生器** | 每 N 个 CLK 输出 1 个 CLK 宽的负脉冲 | 软件 | 是 | **分频器** |
| 3 | **方波发生器** | 对称方波,占空比约 50% | 软件 | 是 | **方波产生** |
| 4 | 软件触发选通 | 计数到 0 后输出 1 个 CLK 宽的负脉冲 | 软件 | 否 | 软件定时选通 |
| 5 | 硬件触发选通 | 触发后计数到 0 输出 1 个负脉冲 | 硬件 | 否 | 硬件延迟脉冲 |
#### 方式 2 vs 方式 3 对比
```mermaid
graph LR
subgraph "方式 2 - 频率发生器"
A2["CLK 输入"] --> B2["计数器 N 分频"]
B2 --> C2["OUT: 周期性窄脉冲"]
end
subgraph "方式 3 - 方波发生器"
A3["CLK 输入"] --> B3["计数器 N 分频"]
B3 --> C3["OUT: 对称方波 50%"]
end
```
| 对比项 | 方式 2 | 方式 3 |
|--------|--------|--------|
| 输出波形 | 负脉冲(宽 1 个 CLK) | 对称方波 |
| 占空比 | 很小 | ≈ 50% |
| 输出频率 | CLK / N | CLK / N |
| 重装机制 | 计数到 1 时 OUT 变低,到 0 时重装 | 计数到 0 时自动重装,交替翻转 OUT |
> [!question] GATE 引脚在方式 2 和方式 3 中的作用?
> - GATE=0:暂停计数,OUT 输出高电平
> - GATE 上升沿:重新装入初值,开始计数
> - GATE=1:允许计数正常进行
### 5. 计数初值计算(核心公式)
$$
计数初值 = \frac{f_{CLK}}{f_{OUT}}
$$
> [!example] 试卷真题计算汇总
>
> | 题目来源 | CLK 频率 | 要求频率 | 计数初值 | 控制字 |
> |:--------:|:--------:|:--------:|:--------:|:------:|
> | 试题 A | 2 MHz | 2000 Hz | 1000 (03E8H) | 34H |
> | 试题 B | 1.193182 MHz | 100 Hz | 11932 (2EA4H) | 36H |
> | 试题 B | 1 MHz | 1 kHz | 1000 (03E8H) | 36H |
> | 试题 C | 1.19318 MHz | 1 kHz | 1193 (04A9H) | 36H |
> | 试题 D | 1 MHz | 1 kHz | 1000 (03E8H) | 36H |
### 6. BCD 计数 vs 二进制计数
| 项目 | 二进制(D0=0) | BCD(D0=1) |
|------|---------------|-------------|
| 计数范围 | 0000H~FFFFH (0~65535) | 0000~9999 |
| 初值装入 | 直接装入十六进制值 | 按 BCD 码装入 |
| 初值 1000 | 03E8H | 1000 (低字节=00, 高字节=10) |
> [!warning] BCD 方式装入初值的坑
> BCD 方式下初值 11932 的装入:
> - 低字节 = **32H**(低 2 位 BCD)
> - 高字节 = **11H**(高 2 位 BCD)
>
> 而不是 2EA4H!控制字也要从 36H 改为 **37H**(D0=1)。
### 7. 初始化编程模板
```asm
; 8254 初始化通用模板
; 假设端口地址为 PORT_0 ~ PORT_3
; 步骤 1:写控制字
MOV DX, PORT_3 ; 控制寄存器地址
MOV AL, 36H ; 控制字:计数器0, 方式3, 先低后高, 二进制
OUT DX, AL
; 步骤 2:写计数初值(先低后高)
MOV DX, PORT_0 ; 计数器 0 地址
MOV AX, 03E8H ; 计数初值 = 1000
OUT DX, AL ; 先写低字节 E8H
MOV AL, AH
OUT DX, AL ; 再写高字节 03H
```
> [!danger] 易错点
> 写初值时必须 **先低后高**(与控制字 D5D4=11 对应),而且低字节和高字节要 **分两次** `OUT` 到同一个端口地址。用 `OUT DX, AX` 一次写 16 位是错误的。
## 关联笔记
- [[8255A可编程并行接口]]
- [[8259A中断控制器]]
- [[8251A串行通信接口]]
- [[接口与通讯技术/试题册/index|试题册索引]]