一、实验目的 (一)进一步掌握数码管的显示控制; (二)进一步掌握单片机的定时器中断的应用; (三)进一步掌握定时器工作方式的控制及各种寄存器的应用; (四)掌握独立按键的使用方法。 二、主要仪器设备及耗材: (一)电脑一台; (二)单片机开发板一套。 三、实验原理 参照实验二数码管的电路原理图,利用数码管的显示原理以及定时器的工作原理,结合按键的应用,编程实现数码管显示时钟,并具有时钟调节功能。
四、实验内容及步骤 (一)实验内容利用所学的单片机定时器中断知识及电路知识,通过单片机编程控制数码管显示时钟,并具有调节时钟的功能。利用定时器中断的知识,通过编程控制数码管显示时钟,显示格式为XX—XX—XX,分别为小时、分钟、秒,并将矩阵键盘的第二行的前三个按键设置为独立按键,第一个按键控制调节时钟的小时、分钟、秒,第二个按键控制调节小时、分钟、秒的加,第三个按键控制调节小时、分钟、秒的减。 五. 工作原理 (一)80C51中断系统 80C51的中断系统有5个中断源(8052有6个),2个优先级,可实现二级中断嵌套。 80C51中断系统的结构如图5.1所示。 (二)定时/计数器的结构和工作原理 1.定时/计数器的结构定时/计数器的实质是加1计数器(16位),由高8位和低8位两个寄存器组成。TMOD是定时/计数器的工作方式寄存器,确定工作方式和功能;TCON是控制寄存器,控制T0、T1的启动和停止及设置溢出标志。定时/计数器的结构如图5.2所示。 2.定时/计数器的工作原理 加1计数器输入的计数脉冲有两个来源,一个是由系统的时钟振荡器输出脉冲经12分频后送来;一个是T0或T1引脚输入的外部脉冲源。每来一个脉冲计数器加1,当加到计数器为全1时,再输入一个脉冲就使计数器回零,且计数器的溢出使TCON中TF0或TF1置1,向CPU发出中断请求(定时/计数器中断允许时)。如果定时/计数器工作于定时模式,则表示定时时间已到;如果工作于计数模式,则表示计数值已满。可见,由溢出时计数器的值减去计数初值才是加1计数器的计数值。 (三)定时/计数器的控制 80C51单片机定时/计数器的工作由两个特殊功能寄存器控制。TMOD用于设置其工作方式;TCON用于控制其启动和中断申请。 1.工作方式寄存器TMOD工作方式寄存器TMOD用于设置定时/计数器的工作方式,低四位用于T0,高四位用于T1。其格式如图5.3所示。 2.控制寄存器TCONTCON的低4位用于控制外部中断,已在前面介绍。TCON的高4位用于控制定时/计数器的启动和中断申请。其格式如图5.4所示。 实现代码如下:
#include <reg51.h> #define smg_1 c=1;b=1;a=1 //选中第一个数码管 #define smg_2 c=1;b=1;a=0 #define smg_3 c=1;b=0;a=1 #define smg_4 c=1;b=0;a=0 #define smg_5 c=0;b=1;a=1 #define smg_6 c=0;b=1;a=0 #define smg_7 c=0;b=0;a=1 #define smg_8 c=0;b=0;a=0 sbit k1=P3^1;//独立按键1 sbit k2=P3^0; sbit k3=P3^2; sbit a=P2^2;//引脚位声明,用于选中数码管 sbit b=P2^3; sbit c=P2^4; int t=0,count=0,h=11,m=1,s=50;//h,m,s可以初始化时间,此时的时间表示:11:01:50 char code number[] = {0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f};//用于数码管显示0-9 void delay(unsigned int ms) { char i; while(ms--) for(i=0; i<110; i++); } void init() { //补充:51单片机有2个定时器,0和1,TH0、TL0和ET0是管定时器0, //TH1、TL1和ET1是管定时器1,要用那个定时器就要用相应参数设置 //我们这里使用的是定时器0,工作方式0,定时间隔5ms TMOD = 0x00; //选用工作方式0 TH0 = (8192-5000)/32; //设置高8位, 8192=2^13; 5000表示计时间隔为5ms TL0 = (8192-5000)%32; //设置低5位 EA=1; //EA标志位置1,允许所有中断,相当于打开总开关 ET0=1; //ET0标志位置1,打开定时器0的中断开关,相当于打开支线开关 T0 TR0=1; //开启TR0计数,即开启定时器0计数 } void time0() interrupt 1 { TH0 = (8192-5000)/32; TL0 = (8192-5000)%32; //计时到达5ms时,即高8位和低五位时,计数器溢出,自动向CPU发送溢出中断请求 t++; //hh-mm-ss if(t==200) //5ms*200=1s { t=0; s++; if(s==60) { s=0; m++; if(m==60) { m=0; h++; if(h==24) { h=0; } } } } } void display() { smg_1; P0 = number[h/10];//h delay(1); smg_2; P0 = number[h%10];//h delay(1); smg_3; P0 = 0x40; //- delay(1); smg_4; P0 = number[m/10];//m delay(1); smg_5; P0 = number[m%10];//m delay(1); smg_6; P0 = 0x40;//- delay(1); smg_7; P0 = number[s/10];//s delay(1); smg_8; P0 = number[s%10];//s delay(1); } void keyDown() { if(!k1)//第一个键按下时 { delay(10); if(!k1) { TR0=0; count++; while(!k1); // if(count==4) { TR0=1; count=0; } } } if(!k2)//第二个键按下时 { while(!k2);//第二个键按下后松手时,跳出该循环 if(count==1) { h++; if(h==24) h=0; } if(count==2) { m++; if(m==60) m=0; } if(count==3) { s++; if(s==60) s=0; } } if(!k3)//第三个键按下时 { while(!k3);//第三个键按下后松手时,跳出该循环 if(count==1) { h--; if(h==-1) h=23; } if(count==2) { m--; if(m==-1) m=59; } if(count==3) { s--; if(s==-1) s=59; } } } void main() { init();//初始化工作 while(1) { display(); keyDown(); } }