用AT89C51实现自设定时间控制
本期教程用一个可以人工设置控制时间、实现电器定时开关的小系统,详细讲解数据显示代码转换,简单介绍一下单片机中断原理的应用及相关指令等问题。
一、本系统实现的功能
本系统由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口输出的就是位选码。扫描显示原理与上期的“活动字符显示屏”相似。
2. 数码管结构及代码显示
共阴LED数码管结构、字段及引脚排列见图2(a),电原理见图2(b)。
由图可知,共阴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中的值与立即数不等则转移。
四、程序清单
ORG 0000
地址 机器码 指令 注释
0000 02003B LJMP 003b ;跳转至003B
ORG 000b
地址 机器码 指令 注释
000B 020100 LJMP 0100 ;跳转至0100
ORG 003b
地址 机器码 指令 注释
003B 752000 MOV 20H,#00H ;初始化
003E 752100 MOV 21H,#00H ;
0041 752200 MOV 22H,#00H ;
0044 752300 MOV 23H,#00H ;
0047 75B0FF MOV P3,#FFH ;
004A 7590BF MOV P1,#BFH ;
004D C291 CLR P1.1 ;
004F D296 SETB P1.6 ;
0051 D297 SETB P1.7 ;
0053 75803F MOV P0,#3FH ;
0056 75A00F MOV P2,#0FH ;
0059 75812F MOV SP,#2FH ;修改栈指针
005C 75703F MOV 70H,#3FH ;装字形代码
005F 757106 MOV 71H,#06H ;
0062 75725B MOV 72H,#5BH ;
0065 75734F MOV 73H,#4FH ;
0068 757466 MOV 74H,#66H ;
006B 75756D MOV 75H,#6DH ;
006E 75767D MOV 76H,#7DH ;
0071 757707 MOV 77H,#07H ;
0074 75787F MOV 78H,#87H ;
0077 75796F MOV 79H,#6FH ;
007A 756001 MOV 60H,#01H ;设定负载开启时间
007D 756108 MOV 61H,#08H ;
0080 756203 MOV 62H,#03H ;
0083 756408 MOV 64H,#08H ;设定负载关闭时间
0086 756500 MOV 65H,#00H ;
0089 756601 MOV 66H,#01H ;
008C 00 NOP ;备用字节,可安放判键
008D 00 NOP ;设置程序引导指令
008E 00 NOP ;
008F 00 NOP ;
0090 7C00 MOV R4,#00H ;计时程序
0092 75B802 MOV IP,#02H ;设定定时器0高优先级
0095 758902 MOV TMOD,#02H ;定时器0工作于模式2 0098 75A882 MOV IE,#82H ;设定中断允许
009B 758C18 MOV TL1,#18H ;设定定时重装载值
009E D28C SETB TR0, ;开启定时器0
00A0 BC3CFD CJNE R4,#3CH,00A0;判断秒累计数
00A3 7C00 MOV R4,#00H ;清秒累计寄存器
00A5 0523 INC 23H ;分个位加1
00A7 E520 MOV A,20H ;负载开时间判断
00A9 B5600C CJNE A,60H,00B8;
00AC E521 MOV A,21H ;
00AE B56107 CJNE A,61H,00B8;
00B1 E522 MOV A,22H ;
00B3 B56202 CJNE A,62H,00B8;
00B6 C297 CLR P1.7 ;接通负载
00B8 E520 MOV A,20H ;负载关时间判断
00BA B5640C CJNE A,64H,00C9;
00BD E521 MOV A,21H ;
00BF B56507 CJNE A,65H,00C9;
00C2 E522 MOV A,22H ;
00C4 B56602 CJNE A,66H,00C9;
00C7 D297 SETB P1.7 ;关闭负载
00C9 E523 MOV A,23H ;计时进位处理
00CB B40AD2 CJNE A,#0A,00A0;
00CE 752300 MOV 23H,#00H ;
00D1 0522 INC 22H ;
00D3 E522 MOV A,22H ;
00D5 B406D8 CJNE A,#06,00B0;
00D8 752200 MOV 22H,#00H ;
00DB 0521 INC 21H ;
00DD E520 MOV A,20H ;
00DF B4020E CJNE A,#02,00F0;
00E2 E521 MOV A,21H ;
00E4 B404C9 CJNE A,#04,00B0;
00E7 752100 MOV 21H,#00H ;
00EA 752000 MOV 20H,#00H ;
00ED 0200A0 LJMP 00A0 ;
00F0 E521 MOV A,21H ;
00F2 B40ABB CJNE A,#0A,00B0;
00F5 752100 MOV 21H,#00H ;
00F8 0520 INC 20H ;
00FA 0200A0 LJMP 00A0 ;
00FD 00 NOP ;
00FE 00 NOP ;
00FF 00 NOP ;定时中断子程序
0100 C28C CLR TR0 ;关闭定时器0
0102 C0D0 PUSH PSW ;将PSW内容压入栈中
0104 C0E0 PUSH ACC ;将A的内容压栈中
0106 7F30 MOV R7,#30H ;设扫描常数
0108 12017D LCALL 017D ;调“嘀嗒”声子程序
010B 120174 LCALL 0174 ;调快慢调整子程序
010E 120120 LCALL 0120 ;调查表译码显示子程序0111 DFFB DJNZ R7,010E ;
0113 0C INC R4 ;
0114 D0E0 POP ACC ;出栈
0116 D0D0 POP PSW ;
0118 D28C SETB TR0 ;开计时器0
011A 32 RETI ;中断返回
011B 00 NOP ;备用字节
011C 00 NOP ;
011D 00 NOP ;
011E 00 NOP ;
011F 00 NOP ;
0120 7A70 MOV R2,#70H ;查表译码显示子程序
0122 E520 MOV A,20H ;时十位译码
0124 2A ADD A,R2 ;
0125 F8 MOV R0,A ;
0126 8624 MOV 24H,@R0 ;
0128 7A70 MOV R2,#70H ;时个位译码
012A E521 MOV A,21H ;
012C 2A ADD A,R2 ;
012D F8 MOV R0,A ;
012E 8625 MOV 25H,@R0 ;
0130 7A70 MOV R2,#70H ;分十位译码
0132 E522 MOV A,22H ;
0134 2A ADD A, R2 ;
0135 F8 MOV R0, A ;
0136 8626 MOV 26H, @R0 ;
0138 7A70 MOV R2, #70H ;分个位译码
013A E523 MOV A,23H ;
013C 2A ADD A,R2 ;
013D F8 MOV R0,A ;
013E 8627 MOV 27H,@R0 ;
0140 758000 MOV P0,#00H ;
0143 75A080 MOV P2,#80H ;扫描时十位
0146 852480 MOV 24H,P0 ;送时十位显示代码
0149 120191 LCALL 0191 ;显示延时
014C 758000 MOV P0,#00H ;
014F 75A040 MOV P2,#40H ;扫描时个位
0152 852580 MOV 25H,P0 ;
0155 120191 LCALL 0191 ;
0158 758000 MOV P0,#00H ;
015B 75A020 MOV P2,#20H ;扫描分十位
015E 852680 MOV 26H,P0 ;
0161 120191 LCALL 0191 ;
0164 758000 MOV P0,#00H ;
0167 75A010 MOV P2,#10H ;扫描分个位
016A 852780 MOV 27H,P0 ;
016D 120191 LCALL 0191 ;
0170 758000 MOV P0,#00H ;
0173 22 RET ;显示子程序返回
0174 7808 MOV R0,#08H ;秒脉长短调整子程序
0176 79CE MOV R1,#CEH ;
0178 D9FE DJNZ R1,0178 ;
017A D8FA DJNZ R0,0176 ;
017C 22 RET ;子程序返回
017D 792D MOV R1,#2DH ;嘀嗒声子程序
017F D291 SETB P1.1 ;
0181 788F MOV R0,#8FH ;
0183 D8FE DTNZ R0,0183 ;
0185 C291 CLR P1.1 ;
0187 788F MOV R0,#8FH ;
0189 D8FD DJNZ R0,0189 ;
018B D9F2 DJNZ R1,017F ;
018D 12019A LCALL 019A ;
0190 22 RET ;子程序返回
0191 7808 MOV R0,#08H ;2ms延时子程序
0193 798F MOV R1,#8FH ;
0195 D9FE DJNZ R1,0195 ;
0197 D8FA DJNZ R0,0193 ;
0199 22 RET ;子程序返回
019A 784F MOV R0,#4FH ;20ms延时子程序
019C 798F MOV R1,#8FH ;
019E D9FE DJNZ R1,019E ;
01A0 D8FA DJNZ R0,019C ;
01A2 22 RET ;子程序返回
评论