用AT89C51实现自设定时间控制

🏠 首页 《无线电》杂志 2001年 🔗 第5期 🔗 第29页 分类:电脑与单片机 🔗 马玉华 🔗, 滕世进 🔗

本期教程用一个可以人工设置控制时间、实现电器定时开关的小系统,详细讲解数据显示代码转换,简单介绍一下单片机中断原理的应用及相关指令等问题。

一、本系统实现的功能

本系统由AT89C51、LED数码管、按键、讯响器等部分构成,能实现计时时间的调整、控制时间的设定,对负载实现开关控制以及秒信号“嘀嗒”声提示等功能。系统的功能选择由SB1、SB2、SB3完成。SB1为功能切换键。第一轮按动SB1进入负载开关时间设置程序,接下来按动此键,依次进入“时”十位调整、“时”个位调整、“分”十位调整、“分”个位调整和负载开关设置状态。第二轮按动SB1是负载开关时间上、下限设置。第三轮按动SB1进入计时时间调整。不管是进入那种状态,按动SB2皆可以使被调整位进行不进位增量变化。各预置量设置完成后,可按动SB3确认,系统将所有的设置存入RAM中,立刻进入计时程序。上电后,系统自动进入计时状态,起始于“00”时“00”分。秒数字不显示,而是以一种模拟传统机械表的运行节奏,发出清脆的“嘀嗒”声做秒信号指示。本系统可将计时误差缩小至每日±0.18s。

二、电原理


1. 显示原理
电原理图见图1。P0口的8条数据线P0.0 至P0.7 分别与LED数码管的a、b、c、d、e、f、g、dp字段相接,P2口的P2.7至P2.4分别通过电阻R10至R13与VT1至VT4的基极相连接。这样通过P0口送出显示代码,通过P2口送出扫描选通代码轮流点亮LED1至LED4,就会将要显示的数据在数码管中显示出来。从P0口输出的代码就是段选码,从P2口输出的就是位选码。扫描显示原理与上期的“活动字符显示屏”相似。

j

图1
图1 🔍原图 (624×332)

2. 数码管结构及代码显示
共阴LED数码管结构、字段及引脚排列见图2(a),电原理见图2(b)。

图2
图2 🔍原图 (425×396)

由图可知,共阴LED数码管由8只发光二极管VD1至VD8共阴连接并按“8”字形结构排列而成。这样,我们将这些二极管的正极接高低不同的电位,把所有的负极接地,当正极为高电位时相应的二极管就会导通而发光,从而使数码管呈现不同的字符。比如,我们将数码管的a、c、d、f、g端接高电位,将GND端接低电位,VD1、VD3、VD4、VD6和VD7就会发光,数码管的a、c、d、f、g字段就会被点亮,数码管即显示出“5”字,在图1中,数码管的a、b、c、d、e、f、g、dp引脚分别与P0口的P0.0至P0.7相连接。若执行MOV P0,#6DH和MOV P2,#80H,P2口输出的位选码是“1000 0000B”,只有P2.7呈现高电位,VT1导通,LED1的GND与地相接,LED1位被选中因而具备发光的使能条件;P0口的段选码是0110 1101B”,P0.0、P0.2、P0.3、P0.5、P0.6呈现高电位,数码管的a、c、d、f、g字段被点亮,LED1就显示出“5”字,而LED2至LED4则不会被点亮。可见,在利用P2口送出位选码,使各位轮流得到发光使能条件的同时,通过P0口分别送出不同的段选码,就会在LED1至LED4中显示出不同的数字来。

三、程序设计思想和相关指令介绍

本系统的主程序主要完成时间控制和按键判断功能。而扫描、计时、显示和发声等功能全部在中断服务程序中完成。因此,主程序将完成按键判断、时间判断等功能,而中断服务程序中有代码转换及查表子程序、扫描子程序、计时子程序、显示子程序和发声子程序。


1.数据与代码转换及查表程序

由前述可知,从P2口输出位选码,从P0口输出段选码,LED就会显示出数字来。但P0口的段选码和要显示的数据,也就是显示出的字符表达的含义是不一致的。可见,CPU将要显示的数据直接送到P0口去驱动LED数码管显示是不能正确表达的,必须在系统内部将要显示的数据经过显示代码进行转换后,将数据的段选代码送入P0口,使数码管显示出正确的数据表达符,才能被准确识读。

要显示的数据与其段选码的转换,可以用一段简单的程序来实现,我们将所有需要显示的数据的显示代码放在一起组成代码表,使数据与其显示代码有一个准确的对应关系,以便查找转换。如附表所示,我们将0至9这10个数字的段选码存到RAM的70H至79H之中,利用一条间接寻址命令,就能很方便地实现显示数据与其段选码之间的转换。具体转换过程如下:我们先将要显示的数据装入累加器A中,再将A中的数据加上立即数#70H,再放回A中,然后将A中的值,放入间址寄存器R0中,这便得到了存放该数据段选码的存储地址,取出该单元内的内容,就得到了正确的显示代码,这个过程就是查表转换数据显示代码的过程。比如:我们要将“#05H”送LED显示,执行MOV A,#05H和ADD A,#70H,再执行MOV R0,A,结果是使R0中的值为#75H,这就得到了存放数据#05的段选码的存储单元地址,利用一条间接寻址指令,MOV P0,@R0,就将75H中的数据#05H的段选码#6DH送到了P0口中,于是“5”字就在LED中显示出来。

在该系统中,我们用LED1和LED2显示“时”,用LED3和LED4显示“分”,并将“时”、“分”数据转换后的段选码存于片内RAM的24H到27H组成的显示缓存区之中,利用扫描程序,将4个单元的内容送LED1至LED4中显示出来。


2.计时功能的实现与中断服务程序
作为时间控制系统,一定要保证在完成有关操作,比如扫描显示、按键状态检测、秒信号“嘀嗒”提示声输出等的同时,保证计时正常进行,这样,一定要一边进行操作,一边计算时间,当满1秒或一个更大或更小的计时单位时,及时地完成进位,并及时修改显示缓存区的段选码。上述过程,用中断来实现是最方便的。明白了重装定时方式的中断,计时功能的实现就容易理解了,我们将一些运行时间确定的程序统统放到中断服务程序中,如扫描、显示、“嘀嗒”提示声等功能子程序,然后再加上定时器定时时间,这样每次中断所需时间就是中断程序的运行时间与定时器溢出时间之和,它是个固定的值,即计时单位。因此,系统的计时就可以做得很准确,而在中断之外的主程序,则可以随便安放一些诸如按键判断等时间不确定的随机事件处理程序。整个中断程序运行时间与定时器溢出时间之和是1s。这样,当完成60次定时中断,即为1分钟,主程序就以此为基本计时单位进行计时显示操作。 进入中断服务程序以后,执行CLR TR0将定时器0关闭,执行PUSH PSW和PUSH A将程序状态寄存器PSW的内容和累加器A中的数据保存起来,这便是所谓的“保护现场”;之后,先调秒信号“嘀嗒”声子程序,完成机械表运行节奏的模拟,再调查表子程序将时间数据区20H~23H的数据经译码后存入显示缓存区24H~27H内,然后反复进行扫描显示;当进入中断连续扫描至999.526ms时,停止扫描,执行POP A和POP PSW 指令,将保护现场时存起来的数据重新送回到累加器A中和程序状态寄存器PSW中,恢复现场,再执行SETB TR0,开启定时器/计数器0,使之开始计时,然后返回主程序。自停止扫描到中断返回,执行了5条单机器周期指令,共用时间10μs,这样,整个中断的总时间为999.536ms,由于定时器/计数器0的定时时间为464μs,所以,定时时间与中断服务程序运行时间之和恰为1s,也就是说每次中断用时1s,这样,每次中断,将秒计数存储单元内的数加1 ,就可得计时秒数,然后根据进率,得到时、分的值,并将时、分值经译码后,通过扫描程序送LED中显示出来。秒的累加是用指令INC来实现的。用以保护现场和恢复现场时存取关键数据的存储区叫做堆栈。在软件的控制之下,堆栈可在片内RAM中的任一区间设定,而堆栈的数据存取与一般的RAM存取又有区别,对它的操作,要遵循“后进先出”的原则。堆栈的设定和堆栈的读写操作,主要靠一个特殊寄存器SP来完成,SP谓之堆栈指针,对堆栈的操作,其被操作数存储单元的地址是由SP中的内容决定的。如MOV SP,#2FH指令,能使SP中的内容修改为#2FH,2FH单元称之为“栈底”。这样当执行堆栈的写操作时,被操作数将从片内RAM的30H开始存放。在中断程序中为了保护现场,使用了PUSH指令,该指令是将被保护的数据存于堆栈的指令,利用该指令完成的操作叫做压栈。当栈底为2FH时,CPU执行PUSH PSW指令时,SP首先加1,使其中的值改为#30H,然后再将程序状态寄存器PSW中的数据存到RAM的30H单元之中,接着执行PUSH A,累加器A中的数据便被送到了31H之中,我们称31H为此时的栈顶。相反的,POP指令是将堆栈栈顶的数据送回指定地址的指令,我们称之为出栈指令,执行结果是将栈顶的数据送到直接地址的存储单元中,并将SP中内容减1,建立新栈顶。如前述,栈顶为31H,也就是说SP中的值为#31H,此时执行POP A指令,CPU先将31H单元内的数据送到累加器A中,再将SP中的值减1,使之变成#30H,此时栈指针SP必指向30H,新的栈顶也便是30H,然后执行POP PSW,30H中的数据又被送到了PSW之中。由于SP具备在压栈时使栈顶逐一上升,在出栈时使栈顶逐一下降的功能,才使栈操作具有“后进先出”的特征。所以,在中断程序的设计中,出栈数据的目的地址和压栈数据的源地址要严格对应,还必须遵循“后进先出”原则。


3.时间控制功能与比较指令
系统的另一功能就是实现对执行设备的定时开关控制,其主要控制思想是这样的:先将执行设备开启的时间和关闭时间置入RAM某一单元,在计时主程序当中执行几条比较指令,如果当前计时时间与执行设备的设定开启时间相等,就执行一条CLR P1.7指令,将P1 .7置为低电位,使光耦可控硅K导通,负载L开启;如果当前计时时间与执行设备设定的关闭时间相等,就执行SETB P1.7,将P1.7置高电位,光耦可控硅K截止,负载L关闭。实现此控制功能用到的比较指令为CJNE A,#direct,rel,其转移条件是累加器A中的值与立即数不等则转移。限于篇幅,本系统的源程序略,若读者需要,可到本刊网址上查找。本刊网址为:www.radio.com.cn。

(滕世进 马玉华)