赞
踩
用51单片机完成一个数字钟的计时及校时功能。
1、设置8个数码管的显示缓冲区为DISPBUFF[8],并初始化为02,02,-,04,08,-,03,06.
2、定时器0每隔5ms刷新一次数码管显示缓冲区,并显示时间(中断来做)
3、定时器1负责精确定时,计时1s,每隔50ms中断一次,中断20次即为1s
4、用图中两个按键实现时分和小时的校时功能,MODE按键实现小时校准、分校准及正常显示的3个模式切换,ADD按键实现对应时间加一,按键采用外部中断方式实现功能。在校准小时及分钟的时候,对应两位数码管的小数点必须亮,正常模式时所有小数点全灭.
5、秒脉冲由51单片机的定时器来提供。
按要求上交实验报告(校准小时、分钟及正常模式的对应Proteus仿真截图及开发板下载图一定要)。
定义一个数码管显示模块,起名为dis_seg7()
定时器0每隔5ms刷新一次数码管显示缓冲区,并显示时间(中断来做)
定时器1负责精确定时,计时1s,每隔50ms中断一次,中断20次即为1s
外部中断0实现模式切换
外部中断1实现hour/min自增
#include<reg52.h> //共阳极数码管 unsigned char code segCodeTable[12] = {0xc0,0xf9,0xa4,0xb0, 0x99,0x92,0x82,0xf8, 0x80,0x90,0xbf,0x7f}; //0-9,-,., //带小数点的共阳极数码管段码表 unsigned char code segCodeTable1[10] = {0x40,0x79,0x24,0x30, 0x19,0x12,0x02,0x78, 0x00,0x10};//0-9 //位码表 unsigned char code posCodeTable[8] = { 0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01}; //数码管显示缓冲区 unsigned char LEDBuffer[8] = {0x82,0xb0,0xbf,0x80,0x99,0xbf,0xa4,0xa4,}; void display_seg7(); void TIMER0_INIT(); void TIMER1_INIT(); void EXT_INTR0_INIT(); void EXT_INTR1_INIT(); unsigned char sec = 36,min = 48,hour = 22; //定义一个变量,记录状态 unsigned char stat = 0; void main() { //定时器0初始化配置 TIMER0_INIT(); //定时器1初始化配置 TIMER1_INIT(); //外部中断0初始化 EXT_INTR0_INIT(); //外部中断1初始化 EXT_INTR1_INIT(); EA = 1;//开启总中断 while(1); } //定时器1初始化配置 void TIMER1_INIT() { TMOD = (TMOD & 0x0f) | 0x10; PT1 = 1; ET1 = 1; TH1 = 0x3c; TL1 = 0xb0; TR1 = 1; } //定时器1负责精确定时,计时1s,每隔50ms中断一次,中断20次即为1s void TIMER1_INTR() interrupt 3 { static unsigned char cnt = 0; TH1 = 0x3c; TL1 = 0xb0; cnt++; if(cnt >= 20) { cnt = 0; sec++; if(sec == 60) { sec = 0; min++; if(min == 60) { min = 0; hour++; if(hour == 24) { hour = 0; } } } } } //定时器0初始化配置 void TIMER0_INIT() { //定时器0初始化配置 TMOD = (TMOD & 0xf0) | 0x01; ET0 = 1;//使能定时器0中断 PT0 = 0;//设置中断优先级 TL0 = 0x78; //设置定时初值 TH0 = 0xEC; //设置定时初值 TR0 = 1; } //定时器0每隔5ms刷新一次数码管显示缓冲区 void TIMER0_INTR() interrupt 1 { TL0 = 0x78; //设置定时初值 TH0 = 0xEC; //设置定时初值 if(stat == 0) //正常显示 { LEDBuffer[0] = segCodeTable[sec%10]; //更新数码管显示缓冲区 LEDBuffer[1] = segCodeTable[sec/10]; LEDBuffer[3] = segCodeTable[min%10]; LEDBuffer[4] = segCodeTable[min/10]; LEDBuffer[6] = segCodeTable[hour%10]; LEDBuffer[7] = segCodeTable[hour/10]; } else if(stat == 1) //校分 { LEDBuffer[0] = segCodeTable[sec%10]; //更新数码管显示缓冲区 LEDBuffer[1] = segCodeTable[sec/10]; LEDBuffer[3] = segCodeTable1[min%10]; LEDBuffer[4] = segCodeTable1[min/10]; LEDBuffer[6] = segCodeTable[hour%10]; LEDBuffer[7] = segCodeTable[hour/10]; } else if(stat == 2) //校时 { LEDBuffer[0] = segCodeTable[sec%10]; //更新数码管显示缓冲区 LEDBuffer[1] = segCodeTable[sec/10]; LEDBuffer[3] = segCodeTable[min%10]; LEDBuffer[4] = segCodeTable[min/10]; LEDBuffer[6] = segCodeTable1[hour%10]; LEDBuffer[7] = segCodeTable1[hour/10]; } display_seg7(); } //数码管显示模块 void display_seg7() { unsigned char j = 0,i = 0; for(i = 0;i<8;i++) { P2 = LEDBuffer[i]; //段码 P1 = posCodeTable[i]; //位码 for(j = 0;j<200;j++); //延时 P2 = 0xff; //清除余晖 } } //外部中断0初始化 void EXT_INTR0_INIT() { EX0 = 1; PX0 = 1; //设置中断优先级 IT0 = 1; //脉冲下降沿中断 } //外部中断0 void intr0() interrupt 0 { stat++; if(stat == 3) //正常显示 { stat = 0; TR1 = 1;//定时器T1开启 } if(stat == 1)//校分 { TR1 = 0;//定时器T1停止 } if(stat == 2)//校时 { TR1 = 0;//定时器T1停止 } } //外部中断1初始化 void EXT_INTR1_INIT() { EX1 = 1; PX1 = 1; //设置中断优先级 IT1 = 1; //脉冲下降沿中断 } //外部中断1 void intr1() interrupt 2 { if(stat == 1) //校分 { min++; if(min == 60) { min = 0; hour++; if(hour == 24) { hour = 0; } } } if(stat == 2) //校时 { hour++; if(hour == 24) { hour = 0; } } }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。