可编程定时器8253(Programmable Interval Timer 8253)是一种常用的计时器芯片,主要用于计算机系统中的定时和计数功能。它通常被集成在主板或扩展卡上,与中央处理器通过内部总线相连接。
8253芯片具有三个计数器(Timer 0、Timer 1和Timer 2),每个计数器都可以独立地进行定时和计数操作。每个计数器可以设置为不同的工作模式,如内部定时、外部计数和脉冲产生等。除了计数功能外,8253还可以产生中断信号,以便CPU在计数器达到预设值时接收到相应的中断请求。
编程8253芯片需要进行一系列的操作,包括设置计数器的工作模式、预设计数器的初值和读取计数器的当前值等。通过编程定时器8253,计算机系统可以实现诸如系统定时器、任务调度、音频播放、脉冲控制等功能。
该芯片是一个接口,我们说如果一个芯片一头担着CPU,一头担着外设,那这个芯片就可以被称为接口,不一定是一个通道,8253就是一个非通道类型的接口,他不是一个用来传输数据的通道,而是一个实现对外部设备进行控制的接口。举个简单的例子,我们想要定时开关空调,那我们定一个时间,8253就开始计数,到了我们定的数,他就会对外设发出一个控制信号,空调就开了。
首先D0~D7说明8253芯片仍然是八位数据传输的,#CS,#RD,#WR分别是片选信号和读写信号,有两根地址总线说明上面有四个端口,CLK代表8253芯片的时钟输入端,即时钟信号的输入引脚。时钟信号是8253芯片的工作基准,它确定计数器的计数速度和定时精度。GATE是作为启动计数的控制信号。OUT端是输出端口,它用来输出通过编程设置而产生的计时器信号或脉冲信号。根据不同的工作模式,8253芯片的OUT端可以产生不同类型的输出信号。
写入一个初值到某计数器中会同时写到计数器里面的两个寄存器里,但是初值寄存器的值是一直不变的,计数寄存器里面的值会被从头减到尾。
8253有六种不同的工作方式,不同的工作方式会输出不同的波形
首先不自动重复计数说明方式0输出的波形不是连续的,不自动重复计数就是我们在写入初值的时候会同时把这个初值写入到初值寄存器和计数寄存器,开始计数之后每过一个周期计数寄存器中的值都减一,而初值寄存器中的值不变,一直到计数寄存器中的值减到0,输出一个波形,本次计数结束。而自动重复计数在计数寄存器的值减为0之后会自动把初值寄存器里面的内容再次写入到计数寄存器,这样就会输出连续的波形。
在方式0中,可以看见读写信号产生了两次负脉冲,也就说我们可以输入两次,第一次是输入命令字,第二次是输入初值,这里的输入指的是向端口输入,对于CPU来说是往端口输出的,因此肯定是用OUT指令,OUT , ,第一次输入端口号是控制寄存器的端口号,数据是命令字,第二次输入的端口号是要选中的计数寄存器的端口号,数据是初值。可以看见当输入初值后过一个周期才开始减,此后每过一个时钟周期都会使初值减一直到初值减到0。计数结束后输出高电平,可以用来做外部可屏蔽中断信号。
方式1与方式0的波形类似,唯一不同的是如果方式0想要重新产生一个波形,需要重新输入命令字和初值,而方式1只需要在GATE再产生一个上升沿即可。
方式2是自动重复计数的,因此他的输出波形是连续的。且在技术到最后一个脉冲的时候输出低电平。比如这里初值写的是3,在计数寄存器里面的值变成1的时候就会产生一个负脉冲,紧接着计数寄存器里面的值变为0并同时把初值寄存器里面的值赋给计数寄存器。
方式3与方式2的输出波形类似,只不过分频的方式不一样,当输入初值是一个偶数的前提下,方式2是在最后一个周期内变负脉冲,而方式3是当初值减为原来一半的时候就开始输出负脉冲直到初值为零,此时会自动把初值寄存器里面的内容送到计数寄存器,产生连续的周期波。
方式2和方式3这两种工作方式都可以用来做分频器。
这两种方式产生的波形可以用来做触发信号。
前两位是用来选择计数器的,再后面两位是用来选择计数长度的,如果前两位选择的是00,34位选择的也是00,则表示读计数器0的计数寄存器现在的值,34位选11,表示计数长度是16位,但是8253只有八根数据线,因此需要传两次,也就要输入两次,规定先输入的是低八位,后输入的是高八位,再往后三位是用来选择工作方式的,最后一位是用来选择计数制的。8253是减法计数器,规定他的最大初值是0。
8253有八根数据线分别于系统总线的低八位相连,读写信号的引脚分别连到CPU的读写信号,两根地址线分别连到系统总线的低两位,片选信号连到译码器上,根据高位地址区分选中哪一片芯片。CLK是有外部时钟产生的,GATE是由门控信号产生的,分别连起来,OUT连到外设上面以控制外设。
首先确定工作方式,第一个计数器要求连续产生负脉冲,工作方式是方式二,第二个计数器要求输出连续方波信号,工作方式是方式三,第三个计数器要求产生一个高电平,可以用方式一或方式零,因为软件启动要比硬件启动更加简单,因此我们这里选择方式零。
然后来确定每一个计数器的初值。即要计数的次数。时钟频率是2M赫兹意味着时钟周期是1/2M等于0.5微秒。10ms也就是20000个时钟周期,因此初值设置成20000,以此类推可以确定第二个和第三个计数器的初值。
然后确定控制字,第一个计数器假设是计数器0(当然也可以是别的),因此控制字前两位是00,20000已经超出了八位二进制所表示的范围,但是没有超出十六位二进制所表示的范围。因此控制字三四位是11,他的工作方式是方式2,因此567位是010,我们选择二进制计数,因此最后一位是0。第二个计数器假设是计数器1,因此前两位是01,第二个计数器的初值200并没有超出八位二进制表示的范围,因此用低八位计数值,所以控制字的三四位是01,他是工作方式3,因此控制字再后面三位是011,最后我们采用二进制计数,因此最后一位是0。第三个计数器是计数器2,因此前两位是10,初值10000已经超过了八位二进制所表示的范围,因此选择16位计数值,34位是11,采用工作方式0,紧接着三位是000,采用二进制计数,最后一位是0。
下面是硬件的连接
因为我们所有的计数器工作方式都是采用的软件启动,因此我们可以直接把GATE都连到电源让GARE始终保持高电平。CLK也是都连接到外部时钟上。左边的引脚都是对应连接即可。下面是软件控制,软件控制无非就是输入控制字和输入初值
题目中给了四个端口的地址,我们怎么确定哪个是控制寄存器呢?当然是根据所给寄存器的最后两位,最后两位是11就表示他是控制寄存器,00就表示是计数器0,MOV DX,0123H表示把控制寄存器的地址送到DX里面去,MOV AL,34H表示把控制字送到AL里面去,OUT DX,AL表示把控制字送到控制寄存器里去,MOV DX,0120H表示把计数器0的地址送到DX中去,MOV AX,20000表示把初值送到AX里面去,此时AL里面放的是低八位,AH里面放的是高八位,由于8253只有8根数据线,因此要传送超过八位二进制表示范围的数比如这里的20000就要分两次传送,规定先传低八位后传高八位,因此OUT DX,AL表示把低八位先传送给计数器0,由于OUT指令不允许用AH作为操作数,因此我们先MOV AL,AH把AH里面的内容送给AL,然后再送给计数器0。另外两个计数器的初始化类似。
可编程并行接口(Programmable Peripheral Interface,简称PPI)8255是一款常用的数字I/O芯片,广泛应用于计算机系统、嵌入式设备和实验室等领域。
PPI 8255芯片具有三个可编程I/O端口(Port A、Port B和Port C)和三个工作模式(模式0、模式1和模式2),方便用户自定义配置。
在模式0下,Port A、Port B和Port C分别成为一个8位的输入/输出端口。用户可以通过编程将特定的端口设置为输入或输出,并通过读写操作来进行数据的传送。
在模式1下,Port A被配置为8位的输入端口,Port B被配置为8位的输出端口,而Port C的高4位作为输出端口,低4位则作为输入端口。通过读取Port A的值和写入Port B和Port C的值,可以进行数据的输入和输出操作。
在模式2下,Port A被配置为8位的输出端口,Port B被配置为8位的输入端口,而Port C仍然被划分为高4位输出和低4位输入。通过写入Port A和Port C的值,并读取Port B的值,可以进行数据的输出和输入操作。
PPI 8255芯片支持可编程中断控制,可以通过编程控制中断功能的使能与禁止,以及中断的触发方式。
总的来说,PPI 8255芯片是一款功能强大、灵活可编程的数字I/O接口芯片,通过合理的编程配置,可以实现对外部设备的控制和通信。
前面的8253是一个非通道接口,只能实现对外设的控制,而8255是一个通道型接口,这意味着他可以进行数据的输入输出。
REAST是复位信号,可以直接与CPU的REAST连接,区分这四个端口也同样用A0和A1这两跟地址线,因为这四个端口都在同一片芯片上,因此他们的高位地址是相同的
D0~D7分别连接系统总线的D0~D7,读写信号分别连接到系统总线这边的读允许和写允许引脚信号,量根地址总线分别相连,片选信号连接到译码器上,译码器的输入就是高位地址。
假设这个外设是一个打印机,打印之前需要知道打印机的状态即他现在是否已经准备好了,那么我们可以把打印机的状态连接到PC0上面,现在PC0就反映了打印机的状态信息,输出数据可以用PA0~PA7,B口可以输入也可以输出,如果外设2也需要判断状态那就可以用C端口的高四位进行判断,但是不能用低四位了,因为低四位已经被用来作为判断外设1状态的依据而且不能拆分了,应该用C端口的高四位作为判断外设2是否准备好的依据,这是因为C端口可以被拆分为两个四位端口。
方式1下传输数据用A端口和B端口,C端口被专用于接收控制信号。但是如果C端口有空余的位也可以用来进行输入输出。如图A端口用C端口的C3 C6 C7三为来作为选通信号的传输。B口用C0 C1 C2,可以看出当A B口同时被用作输出的时候,C口的4 5位是空闲的,可以用来输出0~4之间的数据。下面以A端口作为输出接口举例
因为是CPU要把内存中的数据输出到外设,因此首先CPU会产生一个写允许信号,告诉外设数据已经准备好,可以接收。在写允许信号产生之后数据就被写到了A端口了,这时候CPU就要通知外部设备,利用的就是这里的OBF信号,当OBF信号低电平的时候表示外设可以来接收数据了,而当外设把信号读取完毕之后会发出一个应答信号ACK,该信号会同时使得OBF和INTR变为高电平。INTR是我们熟悉的外部可屏蔽中断信号,他变成高电平就说明他现在要告诉CPU,端口中的数据已经被读走了,你现在可以继续写入了。
这是A B口作为输入时候的连接图,可以看到A口用的是C口的第3 4 5位作为选通信号的传输,而B口用的是0 1 2位,但是顺序变了,这也是前面我们介绍方式1工作特点第三条的原因。
首先在STB有效期间也就是低电平的时候,外设会把数据写入端口,同时端口会产生一个IBF信号作为和外部设备的应答信号,IBF信号为高电平表示缓冲区满了,外设已经没法再写数据到端口了。当STB又无效的时候也就是数据已经被写入端口的时候会产生一个INTR即外部可屏蔽中断信号,告诉CPU数据已经写好了,你可以来读进去了,这时候CPU就会相应端口而产生一个读允许的信号,数据读完之后也就是IOR信号变成高电平的时候就会同时使得IBF变成低电平表示外设又可以向端口写入数据了。
虽然我们说8255同时具有对数据的控制和锁存能力,可以做输入接口也可以做输出接口,但是一旦被连接到电路中,就只能选择其中一种来做,如果要改变成另一种,需要用软件进行初始化。但是在工作方式2下只需要通过时序的控制就能使得8255在输入和输出接口之间完成身份的互换。由于工作方式2用到的选通信号比较多,有5位,而C端口只有8位,如果要让A B端口同时在方式2下工作至少要10位,显然被作为选通信号传输的C端口位数不够用了,因此我们规定只有A端口可以工作在方式2下。
可以看到方式2其实就是把前面方式1作为输入和输出的引脚信号集成了。
首先CPU发出写允许信号表示可以往端口写数据了,此时IOW变成低电平同时发出中断信号,OBF信号也会变成低电平告诉外部设备可以来取数据了,外部设备把数据取完会有ACK信号,表示数据已经成功接收。如果数据输出完成之后又产生了一个STB信号,STB信号表示外设要把数据写入要A口中,同时产生一个IBF信号作为和外部设备的应答信号,用来表示外设向端口输入的时候,缓冲区是不是满了。当缓冲区满了也就是IBF是高电平的时候表示外设已经无法再向端口输入数据,当STB无效的时候表示数据已经被写入端口,此时会产生一个INTR中断信号告诉CPU可以来取数据了,这时候CPU就会产生读允许信号,当数据读完之后也就是IOR变成高电平的时候就会同时使得IBF变成低电平说明外设又可以向端口A写入数据了。
注意并不是每次都是先输出再输入的,如果先产生IOW那就是先输出,如果先产生STB就是先输入。
在8255芯片的工作方式2下,以下是OBF、STB、ACK和IBF这四个信号的作用:
值得注意的是,OBF和IBF只是用来表明缓冲区是否满了,并不会影响CPU对数据的读写,只是表明CPU应该干啥,换句话说,如果IBF是高电平表示缓冲区已经满了,说明外设已经不能往端口输入数据了,这时候CPU应该进行读操作了,这只是个建议,决定CPU进行读操作的信号是INTR。而IBF是低电平的时候如果STB是低电平了,表示缓冲区并没满而外设要输入的数据已经输入完成了,这时候CPU仍然可以进行读操作。
总之三个端口都能工作于方式0,AB端口可以工作于方式1,只有A端口可以工作于方式2.
解释一下位控制字:我们设置C口某位的初始状态显然是要把它作为信息输出出去,也就是说如果这一位没有用到或者是作为输入用,就没有必要把这一位进行初始化。因为C口在作为输入口的时候,虽然我们把某一位的状态初始化了,但是紧接着就会被外设输入进来的信息覆盖掉。那C端口作为输出端口时我们对他的某一位进行初始化就没有任何的意义。
方式控制字第7位(最开始那一位)肯定是1,紧接着的两位是用来选择A端口的工作方式,再下一位是用来控制A口是输入还是输出,再下一位是用来控制C口是输入还是输出,再下一位是选择B端口的工作方式,再下一位是控制B口是输入还是输出,最后一位是控制C口是输入还是输出
位控制字第一位一定是零,紧接着三位无关,通常我们会设置成零,也就是说位控制字的前四位一般都是0,由于我们选择位控制字就是为了对C口某一位进行初始化,因此我们要知道是对哪一个位进行初始化,所以位控制字的123位就是用来选择要初始化的位。最后一位是0表示我们要把选中的这一位初始化成0,最后一位是1表示我们要把选中的这一位初始化成1。
方式控制字在软件控制中一定要有,位控制字只有在需要时才有。
译码电路的设计是根据高位地址,译码器用的是74LS138,硬件连接如上图所示。
之所以要延迟是为了防止高低电平切换频率过快导致看起来还是一直亮着的效果。
先进行8255的初始化,初始化第一步要输入控制字,因此应该先选中控制寄存器,最后两位是11表示这个端口是控制寄存器,因此这里1023H是控制寄存器,我们把他的地址送到DX里面,然后要做的就是把控制字输入到该端口去,先进行方式选择,题目中明确说了A端口是用来输出的,因此我们让A端口在方式0下进行输出,因此最高四位应该是1001剩下四位随便。因为OUT指令不允许用AH作为操作数,因此我们先把这个控制字送到AL里面,然后OUT DX,AL把对A端口的控制信息输出到A端口,题目中还说要用PC0控制信号灯报警,而且我们在初始化的时候希望刚上来灯泡是不亮(低电平),因此位控制字是八个0,题目中还希望让我们用PB7控制报警系统的启动,而且是高电平才启动,因此还要选中B端口,把一个PB7为高电平的信息输入进去,因为我们现在要测试,如果初始化就把PB7设置成低电平就没法测试了。这里只要是最高的那位是1就行,不一定非要80H,OUT DX,AL就启动了报警系统。启动之后开始通过端口A监控每个监控点的状态,因此要MOV DX,1020H选中端口A,实际上我们并不需要分别去看每个监控点是否异常,而是只要有一个监控点异常我们就要报警,因此这里我们直接八位同时监控即可。也就是把A端口的数据信息送到AL里面去,然后CMP AL,0,这样只要A的八位全是0(均无异常),执行完CMP后下一句由于ZF=0,就会再次跳到A那里去再次开始查询一遍。而当有一位不是0,那么执行完CMP AL,0之后会把ZF置1,就不会执行JZ A这一句了,而是说明有异常,现在我们要开始灯的亮灭了,灯泡亮灭是通过PC来控制的,而且是要闪烁三次,因此先把循环次数3送到CX里面,然后MOV DX,1022H选中C端口,题目中说PC0高电平灯亮,因此我们MOV AL,然后OUT DX,AL就会让C端口的最后一位是1,灯泡随之亮起。但是我们要求的是闪烁,因此我们紧接着要让C端口的最后一位变成0,只需要把AL中的内容取反即可。我们可能有疑问:这里只是把AL里面内容改变了,并没有把C端口里面的内容改变啊,那灯泡还亮着呢,我们是不是应该加一句OUT DX,AL呢?其实不用,因为后面有LOOP B,会跳到B那里进行OUT DX,AL。中间的两句CALL DELAY是为了不让亮灭的频率过快,不然给我们的视觉效果就是灯泡在一直亮着。每执行完一遍 亮和灭就要重新来一遍,直到CX为0也就是说闪烁了三次,报警完成之后并不是说报警系统就不用再工作了,而是应该再次跳到A代码那里重新开始进行监控点异常的检查工作,因此需要JMP A。