1、基于51单片机的时钟设计 单片机时钟1.1 单片机定时器的基本概念和相关寄存器 51系列单片机片内有二个十六位定时/计数器:定时器0(T0)和定时器1(T1)。 两个定时器都有定时或事件计数的功能,可用于定时控制、延时、对外部事件计数和检测等场合,定时/计数器实际上是16位加1计数器。 T0由2个8位持殊功能寄存器TH0和TL0构成, T1由2个8位持殊功能寄存TH1和TL1构成。 每个定时器都可由软件设置为定时工作方式或计数工作方式。T0和T1受特殊功能寄存器TMOD和TCON控制。1.2 单片机中断系统和相关的寄存器51单片机有5个中断请求源,两个中断优先级,可两级嵌套。与中断有关的特殊功
2、能寄存器SFR有定时器控制寄存器TCON、串行口控制寄存器SCON、中断允许寄存器IE、中断优先权寄存器IP。1.3 具体设计1.3.1 任务要求、任务分析要求:应用定时器和中断系统,比如电子时钟,参考功能有:时间;年、月、日;闹钟;时间修改;年月日设置;闹钟时间设置。分析:运用中断系统实现定时器功能与显示。1.3.2 Proteus仿真原理图1.3.3 C语言程序算法分析与程序构架#include #define uchar unsigned char#define uint unsigned int/可位寻址单元的位定义sbit LE1= P20;sbit LE2= P21;sbit KE
3、Y1= P22;sbit KEY2= P23;sbit KEY3= P24;sbit SPEAK= P25;sbit P26= P26;sbit P27= P27;sbit P10= P10;sbit KEY4= P11;sbit P30= P30;sbit P31= P31;sbit P32= P32;sbit P33= P33;sbit P34= P34;sbit P35= P35;sbit P36= P36;sbit P37= P37;sbit P12= P12;/共阳LED显示代码uchar LED_Duanxuan=0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82
4、,0xF8, 0x80,0x90,0x88,0x83,0xC6,0xA1,0x86,0x8E;/共阴LED显示代码uchar LED_Duanxuan1=0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07, 0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71;/LED位选uchar LED_weixuan=0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80;/显示缓冲区uchar LED_DIS8=0,0,0,0,0,0,0,0;uchar LED_Saomiao =0;uchar time_50ms,i=0;
5、uchar second,minute,hour,minute1,day,mon,year,alhour,almin;uchar number_key;int n=0;void delay(void); /延时程序void display(void); /显示程序void key_process(void); /按键处理程序void Initialize(void); /初始化程序int Leepyear(unsigned int year);void Initialize(void) second = 0; /秒 minute = 0; /分 hour = 0; /时 day = 1; /日
6、 mon = 1; /月 year = 0; /年 number_key = 0; /按键次数 TH0=(65536-50000)/256; /定时50ms TL0=(65536-50000)%256; EA = 1; /开中断总开关; ET0 = 1; /允许定时器0中断开关; TR0 = 1; /启动定时器T0; LED_DIS0 = LED_Duanxuan0; /显示缓冲区初始化 LED_DIS1 = LED_Duanxuan1; LED_DIS2 = LED_Duanxuan2; LED_DIS3 = LED_Duanxuan3; LED_DIS4 = LED_Duanxuan4;
7、LED_DIS5 = LED_Duanxuan5; LED_DIS6 = LED_Duanxuan6; LED_DIS7 = LED_Duanxuan7; void key_process(void) KEY1 = 1; KEY2 = 1; KEY3 = 1; /IO口读之前先写1; if(P10=0&P12=1) if(KEY1 = 0) /时分修改 (minute =59)?(minute = 0):(minute+); while(KEY1 = 0) display(); /等待按键释放; if(KEY2 = 0) (hour =23)?(hour = 0):(hour+); while
8、(KEY2 = 0) display(); /等待按键释放; if(P10=1&P12=1) /年月日修改 if(KEY1 = 0) (day =31)?(day = 1):(day+); while(KEY1 = 0) display(); /等待按键释放; if(KEY2 = 0) (mon =12)?(mon= 1):(mon+); while(KEY2 = 0) display(); /等待按键释放; if(KEY3=0) (year=99)?(year=0):(year+); while(KEY3=0) display(); if(P12=0) if(KEY1 = 0) /闹钟时分修
9、改 (almin =59)?(almin = 0):(almin+); while(KEY1 = 0) display(); /等待按键释放; if(KEY2 = 0) (alhour =23)?(alhour = 0):(alhour+); while(KEY2 = 0) display(); /等待按键释放; void alarm() if(hour=alhour)&(minute=almin) / 当时钟与设定值 相同时 发出声音 SPEAK=1; if (KEY4=0) / 手动按键停止 while(KEY4=0) display(); SPEAK=0; /闹钟停止 void main
10、(void) Initialize(); while(1) display(); /调用显示程序 key_process(); /调用按键处理程序 alarm() ; /调用闹钟 void display(void) /动态扫描显示 uint temp=100; LED_Saomiao+; if(LED_Saomiao = 8) LED_Saomiao=0; P3 = LED_weixuanLED_Saomiao; /位选 LE2 = 1; LE2 = 0; P0 = LED_DISLED_Saomiao; /段选 LE1 = 1; LE1 = 0; while(temp-); void ti
11、ming(void) interrupt 1 /定时器T0中断,50ms中断一次 TH0=(65536-50000)/256; TL0=(65536-50000)%256; time_50ms+; if(time_50ms=200) time_50ms = 0; second+; /秒加1; if(second=60) second = 0; minute+; /分钟加1; if(minute=60) minute = 0; hour+; /小时+1 if(hour = 24) hour = 0; day+; /日期加1; if(mon=2&day=29&!Leepyear(year) /判断
12、是否2月 28天 且不为闰年 day=1; mon+; /月份+1 if(mon=2&day=30&Leepyear(year) /判断是否2月 29天 且为闰年 day=1; mon+; if(mon=4|mon=6|mon=9|mon=11)&day=31) day=1; mon+; if(mon=1|mon=3|mon=5|mon=7|mon=8|mon=10|mon=12)&day=32) day=1; if(mon=12) mon=1; year+; else mon+; if(year=100) year=0; if(P10=0&P12=1) LED_DIS0 = LED_Duan
13、xuanhour/10; /时 LED_DIS1 = LED_Duanxuanhour%10; LED_DIS2 = 0xBF; /- LED_DIS3 = LED_Duanxuanminute/10; /分 LED_DIS4 = LED_Duanxuanminute%10; LED_DIS5 = 0xBF; /- LED_DIS6 = LED_Duanxuansecond/10; /秒 LED_DIS7 = LED_Duanxuansecond%10; if(P10=1&P12=1) LED_DIS0 = LED_Duanxuanyear/10; /年 LED_DIS1 = LED_Duan
14、xuanyear%10; LED_DIS2 = 0xBF; /- LED_DIS3 = LED_Duanxuanmon/10; /月 LED_DIS4 = LED_Duanxuanmon%10; LED_DIS5 = 0xBF; /- LED_DIS6 = LED_Duanxuanday/10; /日 LED_DIS7 = LED_Duanxuanday%10; if(P12=0) LED_DIS0 = LED_Duanxuanalhour/10; /显示闹钟定时小时 LED_DIS1 = LED_Duanxuanalhour%10; LED_DIS2 = 0xBF; /- LED_DIS3
15、= LED_Duanxuanalmin/10; /显示闹钟定时分钟 LED_DIS4 = LED_Duanxuanalmin%10; LED_DIS5 = 0xBF; /- LED_DIS6 = 0xBF; /- LED_DIS7 = 0xBF; /- int Leepyear(unsigned int year) if (year%4=0) /判断是否为闰年 因为21世纪正好只要是4的倍数就为闰年.不支持其他世纪 return 1; else return 0; 1.3.4 任务编程与调试1 P10=1 P10=0时显示时间 KEY1调节分 KEY2调节时2 P10 =1 P12=0 显示日期 KEY1调节日 KEY2调节月 KEY3调节年3 闹钟 当P12=1时显示闹钟设置界面 KEY1 设置时 KEY2设置分图示设置8点时喇叭响起 图中STOP ALARM按键可以使闹钟停止