【计算机原理与接口技术(UNIX)⑲ 完结篇】——可编程计数器 8254 [ 流光发生器、8254工作方式检测程序的设计]


✅ 通过对 【计算机与UNIX汇编原理 ① ~ ⑫】的学习,我们已经大致掌握了汇编程序设计的相关知识

接下来,我将其分栏名改为 【计算机原理与接口技术(UNIX) 】,重点将放在 “计算机原理与接口技术” 上



Programmable Timer / Counter ⏰

上一篇文章链接:【计算机原理与接口技术(UNIX)⑱】——并行 I/O 接口 [ 芯片8255A ].


一、本章导语

本文脉络:依次介绍 可编程定时器/计数器 8254 芯片的结构、工作方式、编程、 8254 的应用、两次上机实验 + 详细讲解

本章重点内容
① 8254 内部有3个独立的16位计数器,每个计数器有6种工作方式。
② 每个计数器对外的3个引脚:门控信号输入 GATE 端、计数脉冲输入 CLK 端、输出信号 OUT 端。
③ 8254 的初始化编程。
④ PC 系列机中的 8254 的3个计数器的作用。

● 计算机系统中常常需要用到定时信号或对外部信号计数。例如:动态存储器的刷新定时、系统日时钟的计时以及发声系统的声源等。


一般定时操作可用软件和硬件两种方式实现
用软件方法实现:通过执行延时程序来达到目的。(这种方法不需要硬件设备,但是 CPU 执行延时程序将增加时间开销,这降低了 CPU 的效率,而且往往不精确)
用硬件方法实现:常用的可编程定时器/计数器有 8253 和 8254 等,其中 8254 是 8253 的增强型,它具备 8253 的全部功能,且工作效率高。【8254 的物理实件如下图所示】

在这里插入图片描述



二、8254 的内部结构

● 8254 内部集成了316位的计数器, 每个计数器有6种工作方式,计数初值可设定为二进制或 BCD 码。最高工作频率为10MHz

在这里插入图片描述
对上图的说明
数据总线缓冲器:完成和系统数据线的配接。对外有8条数据线 D7 ~ D0

读写控制模块:选择芯片内部的控制寄存器和计数器,在读写命令的控制下对选中的端口进行读写操作。对外有5条引线。

控制寄存器:寄存 CPU 对其初始化编程时写入的控制字,以决定计数器的工作方式和并设置读出命令。

计数器:每个计数器对外有3条线
[1] GATE —— 控制信号。当 GATEi = 1 时,每一个 CLKi 信号(下降沿)的到来会使 “减1计数器” 减 1。
[2] CLK —— 计数脉冲输入信号
[3] OUT —— 计数器输出信号
[4] 计数初值 N 的计算公式为 N = f C L K / f O U T N = f_{CLK} / f_{OUT}N=fCLK/fOUT这个需要记住

端口地址:(上图中的 A0 和 A1
C S ‾ = 0 \overline{CS}=0CS=0 的前提下:
[1] A1A0 = 00,选中 0# 计数器
[2] A1A0 = 01,选中 1# 计数器
[3] A1A0 = 10,选中 2# 计数器
[4] A1A0 = 11,选中控制字寄存器


8254 的引脚功能
在这里插入图片描述
对上图的说明
① D7 ~ D0 为数据线,与 CPU 数据线想连。
C S ‾ \overline{CS}CS 为片选信号输入端。
③ A1、A0 为内部寄存器,接 CPU 的地址线。
R D ‾ \overline{RD}RDW R ‾ \overline{WR}WR 接收来自 CPU 的输入、输出读写命令。
⑤ GATE0 ~ GATE2、CLK0 ~ CLK2 和 OUT0 ~ OUT23个计数器的外部引脚。

C S ‾ \overline{CS}CSR D ‾ \overline{RD}RDW R ‾ \overline{WR}WR、A1、A0的配合使用表:

在这里插入图片描述

对上图的说明:因为 “CS” 头上有一横,说明低电平有效,也就是给 “0信号” 有效。



三、8254 的工作方式

8254 的3个计数器均有6种工作方式,其主要区别如下
① 输出波形不同。
② 启动计数器的触发方式不同。
③ 计数过程中,门控信号GATE对计数器操作的影响不同。
④ 有的工作方式具备 “初值自动重装” 的功能。(初值自动重装的功能是当计数值减到规定的数值后,计数初值将会自动地装入计数器重新进行计数)

重点说明:这6种工作方式,均在 CLK 下降沿时计数一次。


3.1 方式 0 —— 计数结束输出正跃变信号(只作了解)

在这里插入图片描述
对上图的说明
软件启动。计数值从 N 减到 0。减到 0 后 OUT 从 0 → 1。
② 方式 0 不具备“初值自动重装” 的功能。(故在需要初值重装时,要重新输入 N )
③ GATE 为计数控制信号,当 GATE = 1 时,允许计数;当 GATE = 0 时,暂停/停止计数。


3.2 方式 1 —— 单脉冲发生器(只作了解)

在这里插入图片描述
对上图的说明硬件启动。GATE 可以实现上图两个功能。(方式 1 不具备“初值自动重装” 的功能。在需要初值重装时,不需要重新输入 N,只需要重填 GATE 即可)


3.3 方式 2 —— 分频器⭐️⭐️⭐️

在这里插入图片描述
对上图的说明软件启动。减1计数,减到1时 OUT 从1 → 0,下一 CLK 初值自动重装。所以 OUT 为周期性波形,输出负脉冲的宽度为一个TCLK,周期 = N × TCLK。方式 2 具备 “初值自动重装” 的功能。


3.4 方式 3 —— 方波发生器⭐️⭐️⭐️

在这里插入图片描述

对上图的说明软件启动
① 减2计数,有初值自动重装功能。
② N = 偶数时,计数值减到上图所示的情况。计数值减到0时初值重装(减到0不代表上图显示出0),输出1:1连续波形。
③ N = 奇数时:
[1] 实际装入的初值以及自动重装的初值均为写入的初值减1
[2] 输出正脉冲期间,减到-2时重新装初值。输 出 正 脉 冲 宽 度 = T C L K × ( N + 1 ) / 2 输出正脉冲宽度=T_{CLK} \times (N+1)/2=TCLK×(N+1)/2
[3] 输出负脉冲期间,减到0时重新装初值。输 出 负 脉 冲 宽 度 = T C L K × ( N − 1 ) / 2 输出负脉冲宽度=T_{CLK} \times (N-1)/2=TCLK×(N1)/2


3.5 方式 4 —— 软件触发的单脉冲发生器(只作了解)

在这里插入图片描述
对上图的说明软件启动
① 减1计数,减到0有输出,无初值自动重装功能。
② GATE 为计数控制信号,当 GATE = 1 时,允许计数;当 GATE = 0 时,暂停/停止计数。


3.6 方式 5 —— 硬件触发的单脉冲发生器(只作了解)

在这里插入图片描述
对上图的说明硬件启动,减1计数,减到0有输出。



四、8254 的控制字和编程方法

8254 的控制字有两个:【这两个控制字共用一个控制口地址,由标识位来区分】
方式控制字:用来设置计数器的工作方式。
读出控制字:用来设置读出命令。


4.1 方式控制字

方式控制字的功能:选择一个计数器,确定工作方式,并规定初值的写入顺序和计数初值 (一串0、1代码) 的数制。
在这里插入图片描述
对上图的说明
计数器选择
D7D6 = 00 → 选择 0# 计数器,
D7D6 = 01 → 选择 1# 计数器
D7D6 = 10 → 选择 2# 计数器,
D7D6 = 11 → 读出控制字标志

读写方式选择
D5D4 = 00 → 标志该命令为 “锁存命令”
D5D4 = 01 → 初值写入时,只写低8位,高8位自动补0;计数值读出时,只能读低8位。
D5D4 = 10 → 初值写入时,只写高8位,低8位自动补0;计数值读出时,只能读高8位。
D5D4 = 11 → 初值写入 / 计数值读出的顺序为先低8位,后高8位。

工作方式选择:【如下图所示】
在这里插入图片描述
数制选择
D0 = 0,计数初值为二进制数。(减1计数器按二进制规律减1。初值范围为 0000H ~ FFFFH,其中 0000H 代表 65536)
D0 = 1,初值为 BCD 码数。(减1计数器按十进制规律减1。初值范围为 0000H ~ 9999H,其中 0000H 代表十进制数 10000)

补充说明:锁存命令 —— D5D4 = 00 时,表示该命令为 “锁存命令”,此时后四位无效,如下图所示:

在这里插入图片描述

4.2 读出控制字

在这里插入图片描述
对上图的说明:读出命令是多通道的锁存命令,一条命令可以锁存3个计数器的计数值、计数器状态。(读出控制字的 D7、D6、D0 位必须分别为110,如上图所示)


4.3 状态字

在这里插入图片描述
对上图的说明:D5 ~ D0 的意义与方式控制字对应位的意义相同。(它用来表示计数器的状态,包括 OUT 在计数输出时是高电平还是低电平)


4.4 8254 的初始化编程 ⭐️⭐️

对 8254 一个计数器的初始化编程步骤
① 向控制寄存器写入方式选择命令字。目的:选择一个计数器,并确定其工作方式和计数值(计数初值)的读 / 写顺序。
② 向选择的计数器写入计数初值。注意:如果方式选择命令字 D0 = 0,则初值应是二进制, 否则初值应是 BCD 码数。

样例:设 8254 的口地址为 40H ~ 43H , 要求 2# 计数器工作在方式 3,计数初值 = 4000,写出 2# 的初始化程序段。

解法1: 设初值为二进制, 初值写入顺序为先低 8 位后高 8 位。
MOV 	AL, 10110110B	; 拆分为 10 11 011 02#计数器 + 先低8位后高8+ 方式3 + 二进制
OUT		43H, AL
MOV		AX, 4000		; 装入初值。或者把 40000FA0H
OUT		42H, AL			; 先写低8, 后写高8位
MOV		AL, AH
OUT		42H, AL


解法2: 设初值为二进制, 写入顺序为仅写高8位。
MOV 	AL, 10100110B	; 拆分为 10 10 011 02#计数器 + 只写高8(8位自动补零) + 方式3 + 二进制              
OUT		43H, AL
MOV		AL, 40			;8位
OUT		42H, AL

注意:解法2是错误的, 因为数制选择的是“二进制”,4000 = 0FA0H, 但其低 8 位是 A0(10100000) 而不等于 00。
如果想改正的话,可以把 "10100110B" 最后的 “0” → “1, 且 “40” → “40H”。[解释:40 的 BCD 码为 (0100 0000)B → (40)H]

解法3: 设初值为 BCD 码, 写入顺序为先低后高。
MOV		AL, 10110111B	; 拆分为 10 11 011 12#计数器 + 先低8位后高8+ 方式3 + 十进制
OUT     43H, AL
MOV		AL, 0			
OUT		42H, AL			; 先写低8位
MOV		AL, 40H			
OUT		42H, AL			; 后写高8位


解法4: 设初值为 BCD 码, 仅写高8位。
MOV		AL, 10100111B	; 拆分为 10 101 011 02#计数器 + 只写高8(8位自动补零) + 方式3 + 十进制
OUT		43H, AL
MOV		AL, 40H			;8 位
OUT		42H, AL 

注意: 4000 的 BCD 码数应写成 4000H, 故解法3、解法4是正确的。


补充说明
① 当计数初值9999时,“初值”选为二进制或 BCD 码都可以。
② 当计数初值 > 9999 时,“初值”只能选二进制。
③ 方式选择命令、锁存命令、读出命令必须写入控制口(即控制字)。
关于锁存命令:当程序员要了解计数器的当前计数值时,先向控制口写入锁存命令,然后从选择的计数器端口读取当前计数值。【这一句话很重要,后面上机实验二的代码中就体现了这个】
关于读出命令读出命令也是锁存命令,如果在锁存计数值的同时,也锁存状态, 那么在随后对计数器读出时,先读出的是状态字,后读的是计数值。

程序中如何表示 BCD 码数?
设初值 = (1234)10
则 		MOV AX, 1234H    是正确的
写成   	MOV AX, 1234     是错误的


五、8254 在 PC 机中的应用

● 在微型计算机系统中,8254 是 CPU 外围支持的电路之一,提供动态存储器刷新定时、系统时钟中断及发声系统音调控制等功能。系统 8254 的初始化由 BIOS 在启动 DOS 时完成。

下图是 8254 在 IBM PC/AT 中的应用示意图【嵌入在真实机器里面的】

在这里插入图片描述
下表是 8254 在 PC/AT 中的使用现状【也就是说经常这么用】

计数器工作方式计数方式初值控制字T O U T T_{OUT}TOUTf O U T / H z f_{OUT}/HzfOUT/Hz
0 #3二进制036H55ms-
1 #2二进制12H54H15μs66827
2 #3二进制533HB6H-约 900

对上表的说明
① 首先注意,最后两列的关系是“倒数关系”。
② 前面讲了计数初值 N 的计算公式为 N = f C L K / f O U T N = f_{CLK} / f_{OUT}N=fCLK/fOUT
③ 那么验证一下 1 #,N = 12H = 18,而 f C L K / N = 1193182 ÷ 18 = 66287.8889 ≈ 66287 f_{CLK} / N = 1193182 ÷ 18=66287.8889≈66287fCLK/N=1193182÷18=66287.888966287。注:PC系列机的输入频率一般为1.193182MHz


ROM-BIOS 中的3个计数器初始化程序段如下【也就是说,真实的这种芯片里面,就编写了这些代码】

① 0# 计数器 工作在方式3,计数初值N = 0,OUT0 = 周期为55ms的方波信号。
作用:每隔55ms通过中断系统提出一次日时钟中断请求。

MOV		AL, 00110110B	; 方式3, 二进制计数
OUT 	43H, AL
MOV 	AL, 0			; 初值为 0000H
OUT 	40H, AL

② 1# 计数器工作在方式2,计数初值N = 18, OUT1 = 周期为15µs的连续脉冲。
作用:每隔15µs(向DMAC)提出一次“动态存储器刷新请求”。【计算机原理中有讲,为什么要动态刷新,为了使存储信息“寿命延长”、不丢失】

MOV 	AL, 01010100B	; 方式2, 只写低 8, 二进制计数
OUT 	43H, AL
MOV 	AL, 12H			; 初值为 12H
OUT 	41H, AL

③ 2# 计数器工作在方式3,初值 = 533H,为音响系统提供900Hz方波。

MOV 	AL, 10110110B	; 方式3, 二进制计数
OUT 	43H, AL
MOV 	AX, 0533H		; 初值为533H
OUT 	42H, AL			; 先写低 8 位
MOV		AL, AH
OUT 	42H, AL			; 再写高 8

注意
① 用户程序禁止使用 1# 计数器。
② 用户程序可以使用 0#、2# 计数器。



六、8254 样例 —— 上机实验

6.1 实验一 —— 流光发生器设计 ⭐️⭐️

实验目的:掌握定时计数器/定时器8254的工作原理、工作方式、初始化编程及使用方法。

实验要求:编写程序实现 8254 的三个计数器输出不同周期的信号,控制发光二极管,达到流光效果。

;---------------------------------------------------+
;	计算机微机原理与接口计数实验							|
;		TPC-486实验箱连线图							|
;													|
;	author:	B19.....10 wly							|
;	Main refer 	→ P402-P403(textbook)				|
;	Other refer → P93(Experimental guide book)		|
;													|
;	实现功能: 8254的三个计数器输出不同周期				|
;	的信号,控制发光二极管,达到流光效果					|
;													|
;	实现功能: 8254的三个计数器输出不同周期				|
;	的信号,控制发光二极管,达到流光效果					|
;													|
;	8254的配置:										|
;	(1) 关闭实验箱电源(禁止带电插拔连线)				|
;	(2)8254的AO,A1接至扩展总线区A0,A1				|
;	(3)8254/RD,/WR接至扩展总线区/IOR,/IOW;		|
;	(4)8254/CS接至I/O地址区/220H-22FH;			|
;	(5)8254的OUT0,OUT1,OUT2接至LED显示区L7,L6,L5	|
;	(6)8254的GATEO,GATE1,GATE2接至扩展实验区+5V		|
;	(7)8254的CLKO,CLK1,CLK2接至时钟500K,100K,1K	|
;: 我们的小组的三个CLK接一样的时钟频率也可以			|
;													|
;---------------------------------------------------+

.586
CODE SEGMENT USE16
ASSUME CS:CODE
;-------------------------------------------------
DATA SEGMENT USE16
Control_1  	EQU 00110110B 	; 0+先写低8后写高8+方波 +二进制
Control_2  	EQU 01110110B 	; 1+先写低8后写高8+方波 +二进制
Control_3  	EQU 10110110B 	; 2+先写低8后写高8+方波 +二进制

Cou_addr_1	EQU 220H      	; 0号计数器口地址 
Cou_addr_2  EQU 221H      	; 1号计数器口地址 
Cou_addr_3  EQU 222H      	; 2号计数器口地址
Cont_Word  	EQU 223H      	; 控制口地址

; CLK_Input_Frequence is in the experimental guide book.
Counter_0   EQU  0C350H 	; 周期 0.1s →10Hz    →初值 N =500000/10  =50000 =C350H
Counter_1   EQU  9C40H 		; 周期 0.4s →2.5Hz   →初值 N =100000/2.5 =40000 =9C40H
Counter_2   EQU  640H 		; 周期 1.6s →0.625Hz →初值 N =1000/0.625 =1600  =640H
DATA ENDS
;-------------------------------------------------

Begin:     
	NOP  	; 空耗一个周期(启动延时)
	MOV 	DX, Cont_Word  	; 写入控制字(计数器0)
	MOV 	AL, Control_1
	OUT 	DX, AL
	MOV 	AX, Counter_0  	; 写入初值(计数器0)
	MOV 	DX, Cou_addr_1   
	OUT 	DX, AL		   	; 先写低 8, 再写高 8 位
	MOV 	AL, AH
	OUT 	DX, AL
	
	MOV 	DX, Cont_Word  	; 写入控制字(计数器1)
	MOV 	AL, Control_2
	OUT 	DX, AL
	MOV 	AX, Counter_1   ; 写入初值(计数器1)
	MOV 	DX, Cou_addr_2   
	OUT 	DX, AL			; 先写低 8 位
	MOV 	AL, AH
	OUT 	DX, AL			; 再写高 8 位
	
	MOV 	DX, Cont_Word  	; 写入控制字(计数器2)
	MOV 	AL, Control_3
	OUT 	DX, AL
	MOV 	AX, Counter_2   ; 写入初值(计数器2)
	MOV 	DX, Cou_addr_3   
	OUT 	DX, AL
	MOV 	AL, AH
	OUT 	DX, AL
	
Wait_T:     	; 为什么要一直空转?因为要一直进行流光信号输出
	NOP			; 空耗一个周期
	JMP 	Wait_T 
	
CODE ENDS
END Begin

运行结果
在这里插入图片描述
运行结果分析:8254 的三个计数器输出不同周期的信号,三个发光二极管按不同频率闪烁,展现出了流光效果。

实验相关结论
① 初值 N NN、时钟频率 f C L K f_{CLK}fCLK 和输出频率 f O U T f_{OUT}fOUT 三者之间的关系为:f O U T = f C L K / N f_{OUT} = f_{CLK} / NfOUT=fCLK/N
② 如果我们要输出频率不同的信号,我们一方面可以使三个灯的N相同,仅 f C L K f_{CLK}fCLK 不同;另一方面也可以使三个灯的 f C L K f_{CLK}fCLK 相同,仅 N NN 不同。当然也可以三个灯的 N NNf C L K f_{CLK}fCLK 都不相同。




6.2 实验二 —— 8254工作方式检测程序的设计 (结合8255) ⭐️⭐️

实验目的:学习并行接口 8255A 的工作原理及编程、定时/计数器 8254 的工作原理、数码管的工作原理及编程,运用微机接口技术,完成8254工作方式检测程序的设计。

实验要求:在微机实验装置上完成相应硬件电路连接,设计程序实现:对定时/计数器 8254 进行初始化编程,指定工作方式; 对并行接口 8255A 进行初始化编程,指定工作方式; 读出 8254 被测计数器的当前计数值,并在数码管上显示。

;-----------------------------------------------+
;	计算机微机原理与接口计数实验						|
;		TPC-486实验箱连线图						|
;												|
;	Author:B19....10 wly						|
;	Time:2021/12/30								|
;												|
;	[1]8254的配置:								|
;		CS: 220H-22FH							|
;		WR: IOW									|
;		RD: IOR									|
;		Al: A1,   A0: A0						|
;		GLKO: 单脉冲								|
;		GATEO: +5V								|
;												|
;	[2]8255的配置:								|
;		CS: 210H-21FH							|
;		WR: IOW									|
;		RD: IOR									|
;		Al: A1,   A0:  A0						|
;		PA0-PA7: 数码管A,B,C,D,E,F,G,DP			|
;		PC0: 数码管S0							|
;-----------------------------------------------+

.586 
;-------------------------------------------------
DATA SEGMENT USE16
BUF DB 3FH, 06H, 5BH, 4FH, 66H, 6DH, 7DH, 07H, 7FH, 6FH 	; 0 ~ 9 的段型码
DATA ENDS
;-------------------------------------------------
CODE SEGMENT USE16
ASSUME CS:CODE,DS:DATA
BEG:
	MOV 	AX,DATA
    MOV 	DS,AX
    MOV 	DX,223H			; 8254 的控制口
    MOV 	AL,00010100B 	; 方式控制字:0号计数器+8位写入+方式2+二进制
    OUT 	DX,AL			; AL → DX 指向的端口
    
    MOV 	DX,220H			; 82540 号计数器
    MOV 	AL,09H			; 设初值为 9
	OUT 	DX,AL			; AL → DX 指向的端口
	MOV 	DX,213H 		; 8255 的方式选择控制字
    MOV 	AL,10000000B   	; 基本型输入输(只用 A 口,方式0 + 输出)
    OUT 	DX,AL			; AL → DX 指向的端口
    MOV 	BX,OFFSET BUF

DISP: 
	MOV 	DX,223H			; 再次初始化 8254A 
	MOV 	AL,0H			; 0号计数器+计数锁存(以便读出),注:只需设置前 4 位 ————> >>> 就是这句话, 锁存命令的体现 <<< 
	OUT 	DX,AL			; AL → DX 指向的端口
    
	MOV 	DX,220H			; 0 号计数器地址
	IN 		AL,DX			; DX 指向的端口 → AL(把当前计数值读出给AL)
	MOV 	AH,0 			;8 位置 0
	
	MOV 	SI,AX			; 读偏移量(AL) → SI
	MOV 	DX,210H
	MOV 	AL,[BX+SI]		; 找到段型码
	OUT 	DX,AL
	JMP 	DISP			; 反复执行(来一个单脉冲就执行一轮循环)
	
	MOV 	AH,4CH			
	INT 	21H				; 返回 DOS
CODE ENDS
END BEG
;-------------------------------------------------

补充说明:结合上述注释,明白所有 INOUT 分别干了什么事,能完全看懂,那么你就基本掌握了 8254 的重要知识点。

运行结果
在这里插入图片描述

运行结果分析:初值为9,除 PC1 位,其余位都显示,并依次递减显示直到1 ,然后由重新赋值为9。(注意:需要了解 “段码液晶屏” 的工作特点 ——> 段选、位选 等基础知识,才能明白为什么 PC1 不亮,这个老师上课没讲,只做了解)

实验相关结论
① 8254 工作在方式2(分频器)时,在写入控制字后,OUT 输出为高电平,写入计数初值后,如果 GATE 为高电平,计数器便开始减1计数,当计数值减到1时,OUT 输出低电平,再经过一个 CLK 周期时,又变为高电平,并且计数初值自动重装,计数器开始重新计数,周而复始。
② 如果我们的 8254 采用的是方式3(方波发生器),如果写入的初值是 “9”,那显示屏能依次显示 “8、6、4、2、0、8、6、…” 。但是如果我们写入的初值是 “8” 时,那显示屏只能依次显示 “8、6、4、2、8、6、…”。这是因为:
[1] 当计数初值为偶数时,每来一个 CLK 脉冲,计数值就减2,当计数值减到0输出端将自动改变极性,内部完成初值自动填装,继续计数。
[2] 当计数初值为奇数时,每来一个 CLK 脉冲,计数值就减2,但它输出脉冲宽度有正负之分。正 脉 冲 宽 度 = T C L K ( N + 1 ) / 2 正脉冲宽度=T_{CLK}(N+1)/2=TCLK(N+1)/2,而 负 脉 冲 宽 度 = T C L K ( N − 1 ) / 2 负脉冲宽度=T_{CLK}(N-1)/2=TCLK(N1)/2 。在输出正脉冲期间时,计数器只有减到-2时,输出端才变成低电平,内部完成初值重装。而在输出负脉冲期间,计数器只需要减到0,输出端就会变为高电平,内部完成初值重装。而且,当计数初值为奇数时,实际重装的初值为编程时写入的初值减1


最后小编还和好朋友一起做了个拓展实验,成功实现下图所示的功能

在这里插入图片描述

开源代码如下

;-----------------------------------------------+
;	计算机微机原理与接口计数实验						|
;		TPC-486实验箱连线图						|
;												|
;	author:	wly、cbw							|
;												|
;	实现功能: 数字8~1依次在S7~S0位分别单独显示		|
												|
;	[1]8254的配置:								|
;		CS: 220H~22FH							|
;		WR: IOW									|
;		RD: IOR									|
;		Al: A1,   A0: A0						|
;		GLKO:100MHz、10MHZ, 都可以试一试		|
;		GATEO: +5V								|
;												|
;	[2]8255的配置:								|
;		CS: 210H~21FH							|
;		WR: IOW									|
;		RD: IOR									|
;		Al: A1,   A0: A0						|
;		PA0~PA7: 数码管A,B,C,D,E,F,G,DP			|
;		PC0~PC7: 数码管S0~S7						|
;-----------------------------------------------+

.586 
;-------------------------------------------------
DATA SEGMENT USE16
BUF 	DB 3FH, 06H, 5BH, 4FH, 66H, 6DH, 7DH, 07H, 7FH, 6FH ; 0~9 的段型码
LOCAT 	DB 80H, 40H, 20H, 10H, 08H, 04H, 02H, 01H			; 8 个位选码
DATA ENDS
;-------------------------------------------------
CODE SEGMENT USE16
ASSUME CS:CODE, DS:DATA
BEG:
	MOV 	AX, DATA
    MOV 	DS, AX
    MOV 	DX, 223H		; 8254 的控制口
    MOV 	AL, 00010100B 	; 方式控制字:0号计数器+8位写入+方式2+二进制
    OUT 	DX, AL			; AL → DX 指向的端口
    
    MOV 	DX, 220H		; 82540 号计数器
    MOV 	AL, 09H			; 设初值为 9
    OUT 	DX, AL			; AL → DX 指向的端口

    MOV 	DX, 213H 		; 8255 的方式选择控制字
    MOV 	AL, 10000000B   ; 基本型输入输(只用 A 口,方式0 + 输出)
    OUT 	DX, AL    		; AL → DX 指向的端口
   
DISP: 
	MOV 	DX, 223H		; 再次初始化 8254A 
	MOV 	AL, 0H			; 0号计数器+计数锁存(以便读出),注:只需设置前 4 位
	OUT 	DX, AL			; AL → DX 指向的端口
    
	MOV 	DX, 220H		; 0 号计数器地址
	IN 		AL, DX			; DX 指向的端口 → AL(把当前计数值读出给AL)
	MOV 	AH, 0 			;8 位置 0
	
	MOV 	SI, AX			;"数组(0~9)" 的偏移量(AL) → SI
	
	MOV 	BX, OFFSET BUF	
	MOV 	DX, 210H		; A 口地址
	MOV 	AL, [BX+SI]		; 找到段型码 → AL
	OUT 	DX, AL			; AL → DX 指向的端口
	
	MOV 	BX, OFFSET LOCAT	 
	MOV 	DX, 212H        ; C 口地址 
	DEC     SI				; 因为只用显示 S0~S7, 所以要减 1
    MOV 	AL, [BX+SI]		; 找到位选码 → AL
    OUT 	DX, AL			; AL → DX 指向的端口
	
	MOV 	ECX, 2000		; 设置一个物理延迟, 避免刷新地过快(眼睛看不出来)
DELAY: 
	LOOP 	DELAY
	JMP 	DISP			; 反复执行(来一个单脉冲就执行一轮循环)
	
	MOV 	AH, 4CH			
	INT 	21H				; 返回 DOS
CODE ENDS
END BEG
;-------------------------------------------------

补充说明:结合上述注释,明白所有 INOUT 分别干了什么事,包括 LOCAT(Location的缩写) 是用来干什么的,能完全看懂,那么你就基本掌握了 “8254 + 段码液晶屏的工作特点 —— 段选、位选” 等知识点。



七、参考附录

[1]《微型计算机原理与接口技术(慕课板)》
清华大学出版社

[2]《微型计算机原理与接口技术实验指导(第2版)》
清华大学出版社

上一篇文章链接:【计算机原理与接口技术(UNIX)⑱】——并行 I/O 接口 [ 芯片8255A ].


《微型计算机原理与接口技术》完结篇

完结打卡
2022/01/06


版权声明:本文为Wang_Dou_Dou_原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。