微程序CPU+8253+8255实现流水灯
一、8253芯片的结构
在计算机系统的工作过程中,经常需要使CPU处于定时工作状态,或者对外部过程进行计数。定时或计数的工作实质均体现为对脉冲信号的计数,如果计数的对象是标准的CPU内部时钟信号,由于其周期恒定,故计数值就恒定地对应于一定的时间,则为定时,如果计数的对象是CPU外部输入的脉冲信号(周期可以不相等),则为计数。
图4-8 可编程定时器/计数器芯片8253A结构图
Intel 8253A是一个可编程的定时器/计数器芯片,其结构如上图4-8所示:8253A内部有3个计数器通道02和1个控制字寄存器。CPU利用2位地址线A1A0选择访问上述部件,通过8位数据总线D7D0与其交互信息,并且使用以下控制线信号提示访问的操作:
:片选信号,决定8253A是否选中。必须先选中芯片,然后才能进行读写操作;
:读信号,CPU读取由A1A0所选定的通道内计数器的内容。
:写信号,CPU把计数初值写入各个通道计数器中,或者把控制字写入控制字寄存器中。
上述控制线信号及地址线A1A0的组合和操作功能如下表4-2所示:
表4-2 8253A控制线及地址组合功能列表
A1 A0 | 寄存器选择和操作 |
---|---|
0 0 1 0 0 | 读0通道锁存器 |
0 0 1 0 1 | 读1通道锁存器 |
0 0 1 1 0 | 读2通道锁存器 |
0 1 0 0 0 | 写 0通道计数寄存器 |
0 1 0 0 1 | 写1通道计数寄存器 |
0 1 0 1 0 | 写2通道计数寄存器 |
0 1 0 1 1 | 写控制字寄存器 |
1 X X X X | 禁止访问,总线D7~D0接口呈现高阻态 |
8253A芯片的3个计数器通道都有各自独立的输入端口CLK(脉冲输入)、GATE(门控信号)和输出端口OUT。当门控信号GATE=0,对应的通道暂停计数;当GATE=1时,对应的通道允许计数。任一通道既可以完成计数器功能,也可以完成定时器功能,其内部操作完全相同:CLK端每输入1个计数脉冲,通道作1次“减1”操作。区别仅在于:
若通道作为计数器,应将要求计数的次数(即计数初值)预置到通道的计数器中。CLK端输入的是外部脉冲个数。每输入一个计数脉冲,计数器减“1”。待计数器内容减到“0”,OUT端就输出一个脉冲信号,提示计数次数已到。
若通道作为定时器,则CLK端输入的是已知周期的时钟信号,计数器预置的计数初值(即定时系数)应根据要求定时的时间进行如下运算得到:“定时系数=需要定时的时间/时钟信号周期”。 当计数值减到“0” OUT端就输出一个脉冲信号,提示定时的时间已到。
图4-9 可编程定时器/计数器8253A芯片控制字结构图
8253A芯片的3个计数器通道结构和功能都完全相同:每个通道内含16位的初值寄存器、减1计数器和输出锁存器。计数器可进行二进制计数(最大计数值FFFFH)或十进制BCD码计数(最大计数值9999)。此外,每个通道内设有一个与计数器对应的16位计数值锁存器。若CPU需要读取计数器的当前值,因为计数器处于不断变化中,读出值可能不稳定。所以CPU通过控制字把指定通道的计数器当前值锁入锁存器,再读取计数器内容。锁存器一旦锁存当前计数值,就不随计数器变化,直到锁存器的值被读取后才解除锁存状态。
8253A芯片的“初始化”过程如下:首先,向控制字寄存器(A0A1=11)写入唯一的一个控制字,确定要设置的通道及工作方式(如上图4-9所示);其次,若计数初值是8位,则根据控制字的规定写入16位初值寄存器的低8位或高8位(未写入的另外8位自动置0);若计数初值是16位,则根据控制字的规定分两次先写入初值寄存器的低8位,后写入高8位。写入计数初值后的一个CLK时钟周期,计数器启动操作,在CLK下降沿“减1”。
二、 8255芯片的结构
Intel 8255A是一个可编程的并行I/O接口芯片,内部结构由PA、PB、PC三个8位可编程双向I/O口,A组控制器和B组控制器,数据缓冲器及读写控制逻辑电路组成, 如下图4-1所示。芯片端口可通过软件选择,并且可编程设置多种工作方式,使用灵活,通用
图4-1 可编程并行I/O接口芯片8255A结构图
从上图4-1可见,8255具有与外设连接的3个通道:PA、PB、PC口。由于8255可编程,所以将3个通道分为两组,即PA0~PA7与PC4~PC7组成A组,PB0~PB7与PC0~PC3组成B组。然后控制器也分为A组控制器(控制A口与C口的高四位)与B组控制器(控制B口与C口的低四位)。这两组控制器是根据CPU命令控制8255A工作方式的电路,内部设有控制寄存器,可以根据CPU送来的编程命令来控制8255A的工作方式,也可以根据编程命令来对指定的通道进行输入/输出操作,或者是对C口的指定位进行置位/复位操作。
8255A的外围引脚根据连接的对象,可以分为以下两大类:
1)面向CPU的引脚:
8255A作为CPU与IO外设的连接芯片,必须提供与CPU相连的数据线、地址线、控制线。因为8255能并行传送8位数据,所以有双向三态数据线D0~D7(内置8位双向三态缓冲器)。由于8255具有3个通道A、B、C,所以只要2根地址线A0/A1就能寻址A、B、C口及控制寄存器。此外,CPU通过以下控制线信号对8255A芯片进行读、写与片选操作:
RESET:复位(高电平有效),清除8255A内部寄存器,置A口,B口,C口为输入方式;
:片选信号,决定8253A是否选中。必须先选中芯片,然后才能进行读写操作;
:读信号,8255A将数据或状态信息送到CPU;
:写信号,CPU将数据或控制信息送到8255A;
上述控制线信号及地址码的组合和操作功能如下表4-1所示:
表4-1 8255A控制线及地址组合功能列表
A1 A0 | 操 作 | 数 据 传 送 方 式 |
---|---|---|
0 0 1 0 0 | 读 A 口 | A口数据→数据总线 |
0 0 1 0 1 | 读 B 口 | B口数据→数据总线 |
0 0 1 1 0 | 读 C 口 | C口数据→数据总线 |
0 1 0 0 0 | 写 A 口 | 数据总线数据→A口 |
0 1 0 0 1 | 写 B 口 | 数据总线数据→B口 |
0 1 0 1 0 | 写 C 口 | 数据总线数据→C口 |
0 1 0 1 1 | 写控制口 | 数据总线数据→控制口 |
1 X X X X | 禁止访问 | 数据总线接口高阻态 |
2)面向IO外设接口的引脚:
8255有3个8位通道A、B、C与外设连接,如下所示:
A口(PA0~PA7):独立的8位I/O口,对输入/输出数据的操作都具有锁存功能。
B口(PB0~PB7):独立的8位I/O口,仅对输出数据的操作具有锁存功能。
C口(PC0~PC7):可以看作独立的8位I/O口,或是两个相互独立的4位I.O口,或是独立的位用于应答信号的通信。仅对输出数据的操作具有锁存功能
三、流水灯实现
8253与8255工作方式就不介绍了,自行查找相关资料,仿真平台为Protues。
1、8253芯片接法
此处使用8253产生1秒的方波输出(使用100HZ的脉冲作为输入),使用了计数器0与计数器1。计数初值自行计算修改,计算方法为:某一计数器输入的频率除其out的频率即为某一个计数器的计数初值。此处使用的两个计数器的计数初值都为10,计数器级联。
2、8255芯片接法
8255芯片三个端口均使用0方式,其中A口输入、B口输出、C口输入。A口接开关作为流水灯初始状态,B口接灯,C口中PC0接8253产生的1秒脉冲PC1~PC7均接地,通过检查PC口中PC0的状态即可实现定时一秒流水灯效果。
3、通过WWSIM-MCU总线实现proteus内的仿真。
完全连接图如下:
4、代码
ORG 0000H
DB 00110000B ;SET R0,86H ;选8255地址[1000xxxx]
DB 10000110B ; ;控制端A1A0=11
DB 01010010B ;OUTA R0,PORT0
DB 00110000B ;SET R0,99H ;控制字
DB 10011001B ; ;PA方式0输入/PB方式0输出/PC方式0输入
DB 01010000B ;OUT R0,PORT0
DB 00110000B ;SET R0,80H ;选PA口
DB 10000000B ; ;A1A0=00
DB 01010010B ;OUTA R0,PORT0
DB 01000100B ;IN R1,PORT0 ;PA口输入,存入R1
DB 00110000B ;SET R0,A6H ;选8253地址[1010 x A1 A0 x ]
DB 10100110B ; ;控制端A1A0=11
DB 01010010B ;OUTA R0,PORT0
DB 00110000B ;SET R0,16H ;控制字
DB 00010110B ; ;初始化计数器0:计数长度8位(低8位),方式3(011),二进制计数(0)
DB 01010000B ;OUT R0,PORT0
DB 00110000B ;SET R0,A0 ;选计数器0
DB 10100000B ; ;A1A0=00
DB 01010010B ;OUTA R0,PORT0
DB 00110000B ;SET R0,0AH ;将计数器0计数初值设为10
DB 00001010B ;
DB 01010000B ;OUT R0,PORT0
DB 00110000B ;SET R0,A6H ;选8253地址[1010 x A1 A0 x ]
DB 10100110B ; ;控制端A1A0=11
DB 01010010B ;OUTA R0,PORT0
DB 00110000B ;SET R0,56H ;控制字
DB 01010110B ; ;计数器1,计数长度8位(低8位),方式3(011),二进制计数(0)
DB 01010000B ;OUT R0,PORT0
DB 00110000B ;SET R0,A2H ;选计数器1
DB 10100010B ; ;A1A0=01
DB 01010010B ;OUTA R0,PORT0
DB 00110000B ;SET R0,0AH ;将计数初值设为10
DB 00001010B ;
DB 01010000B ;OUT R0,PORT0
DB 00110000B ;SET R0,84H ;选中PC口
DB 10000100B ; ;A1A0=10
DB 01010010B ;OUTA R0,PORT0
DB 01001000B ;IN R2,PORT0 ;读入PC口,存入R2
DB 00101001B ;DEC R2 ;(PC1~PC7已经全部接地)
DB 00011000B ;JZ 27H(第39行)
DB 00100101B ;PC0=1则跳转回去继续查询,否则往下走
DB 01001000B ;IN R2,PORT0 ;读入PC口,存入R2
DB 00101001B ;DEC R2 ;(PC1~PC7已经全部接地)
DB 00011100B ;JS 2BH(第43行)结果为负就跳转
DB 00101001B ;PC0=0则跳转回去继续查询,否则继续往下走
DB 00110000B ;SET R0,82H ;选中PB口
DB 10000010B ; ;A1A0=01
DB 01010010B ;OUTA R0,PORT0
DB 01010100B ;OUT R1,PORT0 ;PB口输出
DB 10100111B ;LRC R1
DB 00010000B ;JMP 24H(第36行)
DB 00100010B ;开始下一轮循环
END
注:C口读入两次的原因是计数器产生一秒一个方波,需要检测上升沿才是一秒的时长,即使流水灯一秒跳一次。
如图:
文件放此处:声明未经允许禁止商业使用,内含纯仿真与仿真加实物两个版本。
链接:流水灯
提取码:king