这周我做了一个用51单片机的时钟,下面介绍一下具体实用功能 。仿真一开始,时间显示的是20:30:00
当按下第二个开关时 即可调节"分"如图,按一下便调整为31分。
再按一下第二个键,此时可调节"时"如图。
按一下以后,时间为21时。
代码放在附件,有需要可以下载。
单片机源程序如下:
- #include <reg51.h>
- sbit key1 = P1^0;
- bit flag1s = 0;
- bit KeySta = 1;
- unsigned char hour = 20;
- unsigned char minute = 30;
- unsigned char second = 00;
- unsigned char mode = 0;
- void FreshTime();
- void TimeInit();
- void IntInit();
- void InitLedBuff();
- void keyscan();
-
- unsigned char code LedChar[] = { //共阴数码管显示字符转换表
- 0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,
- 0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0x40,0x00};
- unsigned char LedBuff[6] = { //数码管显示缓冲区
- 0xff,0xff,0xff,0xff,0xff,0xff};
- void main()
- {
- TimeInit();
- IntInit();
- InitLedBuff();
- while(1)//显示内容处理
- {
- if(flag1s&&!mode) //时间显示模式
- {
- flag1s = 0;
- FreshTime();
- }
- else if(mode == 1) //校准分钟
- {
- LedBuff[0] = 17;
- LedBuff[1] = 17;
- LedBuff[4] = 17;
- LedBuff[5] = 17;//不显示
- LedBuff[2] = minute/10;
- LedBuff[3] = minute%10;
- }
- else if(mode == 2) //校准小时
- {
- LedBuff[2] = 17;
- LedBuff[3] = 17;
- LedBuff[4] = 17;
- LedBuff[5] = 17;//不显示
- LedBuff[0] = hour/10;
- LedBuff[1] = hour%10;
- }
- else if(mode == 3) //校准完成重新显示
- {
- InitLedBuff();
- mode = 0;
- }
- keyscan();
- }
- }
- void InitLedBuff()//初始化时间到显示缓冲区
- {
- LedBuff[0] = hour/10;
- LedBuff[1] = hour%10;
- LedBuff[2] = minute/10;
- LedBuff[3] = minute%10;
- LedBuff[4] = second/10;
- LedBuff[5] = second%10;
- }
- void FreshTime()//刷新时间到显示缓冲区
- {
- second++;
- if(second == 60)//进位
- {
- second = 0;
- minute++;
- LedBuff[2] = minute/10;
- LedBuff[3] = minute%10;
- if(minute == 60)//进位
- {
- minute = 0;
- hour++;
- if(hour == 24)
- hour = 0;
- LedBuff[0] = hour/10;
- LedBuff[1] = hour%10;
- }
- }
- LedBuff[4] = second/10;
- LedBuff[5] = second%10;
- }
- void TimeInit()//定时器初始化
- {
- TMOD = 0X11; //设置定时器为模式1
- TL0 = 0xB0;
- TH0 = 0x3C; //定时初值 50ms
- TL1 = 0x18; //
- TH1 = 0xFC; //定时初值 1ms
- TR0 = 1; //定时器0开始计时
- TR1 = 1; //定时器1开始计时
- ET1 = 1; //使能定时器1
- ET0 = 1; //使能定时器0
- PT0 = 1; //提高计时准确性,提高定时器0中断优先级
- EA = 1; //打开总中断
- }
- void IntInit()//外部中断初始化
- {
- IT0 = 1; //下降沿触发
- EX0 = 1; //使能外部中断0
- }
- void keyscan() //按键扫描及处理
- {
- static bit backup = 1;
- if (KeySta != backup) //当前值与前次值不相等说明此时按键有动作
- {
- if (backup == 0) //如果前次值为0,则说明当前是弹起动作
- {
- if(mode == 1) //校准分钟时,分钟加一
- {
- minute++;
- if(minute==60)
- minute = 0;
- }
- else if(mode == 2) //校准小时,小时加一
- {
- hour++;
- if(hour==24)
- hour = 0;
- }
- }
- backup = KeySta; //更新备份为当前值,以备进行下次比较
- }
- }
- void Int0() interrupt 0
- {
- mode++;
- if(mode == 4)
- {
- mode = 0;
- }
- }
- void Ledfresh() //数码管显示刷新
- {
- static unsigned char i = 0;
- switch(i)
- {
- case 0 : P2 = ~(0x01<<i);P0 = LedChar[LedBuff[i]];i++;break;
- case 1 : P2 = ~(0x01<<i);P0 = LedChar[LedBuff[i]];i++;break;
- case 2 : P2 = ~(0x01<<i);P0 = LedChar[LedBuff[i]];i++;break;
- case 3 : P2 = ~(0x01<<i);P0 = LedChar[LedBuff[i]];i++;break;
- case 4 : P2 = ~(0x01<<i);P0 = LedChar[LedBuff[i]];i++;break;
- case 5 : P2 = ~(0x01<<i);P0 = LedChar[LedBuff[i]];i=0;break;
- }
- }
- void Time0() interrupt 1 //12MHz 50ms
- {
- static unsigned char n = 0;
- TL0 = 0xB0;
- TH0 = 0x3C;
- n++;
- if(n==20)
- {
- n=0;
- flag1s = 1;//1s标志位
- }
- }
- void Time1() interrupt 3 //12MHz 1ms
- {
- static unsigned char keybuff = 0xff;
- TL1 = 0x18; //
- TH1 = 0xFC; //定时初值 1ms
- Ledfresh();
- keybuff = (keybuff<<1)|key1;
- if (keybuff == 0x00)
- { //连续8次扫描值都为0,即16ms内都只检测到按下状态时,可认为按键已按下
- KeySta = 0;
- }
- else if (keybuff == 0xFF)
- { //连续8次扫描值都为1,即16ms内都只检测到弹起状态时,可认为按键已弹起
- KeySta = 1;
- }
- else
- {} //其它情况则说明按键状态尚未稳定,则不对KeySta变量值进行更新
- }
复制代码 请自行画图
|