获取更多资源,请关注微信公众号:嵌入式基地
获取项目资源:公众号后台回复:单片机仿真
基于Proteus学习单片机系列(六)——I2C总线AT24C04
基于Proteus学习单片机系列(七)——实时时钟DS1302
基于Proteus学习单片机系列(八)——AD转换及其应用--TLC549
基于Proteus学习单片机系列(九)——DA转换及其应用--TLC5615
基于Proteus学习单片机系列(十一)——LCD12864
项目下载
1. 电路图
2. 程序
主函数
#include<reg51.h>
#include<DEFINE.c>
#include<KEY.c>
#include<DISPLAY.c>
void timer_isr()interrupt 1 //中断服务函数
{
TL0 = (65536-2000) %256; //TL0重置函数
TH0 = (65536-2000)/256; //TH0重置函数
cp++;
if(cp>=250) //0.5s
{
cp1++;
cp = 0;
flash = ~flash; //0.5s - 闪烁
if(cp1>=2) //1s
{
if(mode==0) //调整时,时间停止
sec++;
cp1 = 0;
if(sec>=60) //1min
{
min++;
sec = 0;
if(min>60) //1h
{
hour++;
min = 0;
if(hour>=24)hour = 0;
}
}
}
}
P0 = 0xff; //消隐
switch(mode)
{
case 0:dis_play0();break; //正常
case 1:dis_play1();break; //调时
case 2:dis_play2();break; //调分
case 3:dis_play3();break; //调秒
case 4:dis_play4();break; //调闹时
case 5:dis_play5();break; //调闹分
}
i++;
if(i>=8)i = 0;
}
void timer0_init() //中断初始化函数
{
TMOD = 0x01; //方式一
TL0 = (65536-2000)%256; //TL0 预置,65536十六进制低8位。
TH0 = (65536-2000)/256; //TH0 预置,65536十六进制高8位。
EA = 1; //CPU中断开放 ,总中断打开
ET0 = 1; //定时计数器T0的溢出终端控制位,T0中断打开
TR0 = 1; //定时计数器T0的启停控制位,启动T0
}
void main()
{
timer0_init(); //timer0初始化,为中断做准备
while(1)
{
key();
if(hour == hour_n && min == min_n) //闹钟到时间,蜂鸣器响
{
P3_2 = !P3_2;
delay(50);
}
}
}
定义
#define uchar unsigned char;
#define uint unsigned int;
sbit key_set = P2^0;
sbit key_up = P2^1;
sbit key_down = P2^2;
sbit P3_0 = P3^0;
sbit P3_2 = P3^2; //蜂鸣器
sbit P2_4 = P2^4;
uchar sec = 45,min = 12,hour;
uchar sec_t,min_t,hour_t;
uchar min_n = 13,hour_n;
uchar cp,cp1;
uchar flash,mode,i;
code uchar seven_seg[] ={0xc0,0xf9,0xa4,0xb0,0x99,0x92,
0x82,0xf8,0x80,0x90};
按键函数
void delay(unsigned int x) //延时函数
{
while(x--);
}
void key() //按键函数
{
P2_4 = 0;
if(key_set==0) //如果调整按键按下
{
delay(300); //消抖
if(key_set==0) //如果调整按键真的按下
{
while(key_set==0);
mode++;
if(mode>=6)mode = 0; //mode=0,退出调整
hour_t = hour;
min_t = min;
sec_t = sec;
}
}
if(key_up==0) //如果增加按键按下
{
delay(300); //消抖
if(key_up==0) //如果增加按键真的按下
{
while(key_up==0);
if(mode==1)hour_t++;if(hour_t>24)hour_t = 23;hour = hour_t;
if(mode==2)min_t++;if(min_t>60)min_t = 59;min=min_t;
if(mode==3)sec_t++;if(sec_t>60)sec_t = 59;sec = sec_t;
if(mode==4)hour_n++;if(hour_n>24)hour_n = 23;
if(mode==5)min_n++;if(min_n>60)min_n = 59;
}
}
if(key_down==0) //如果减小按键按下
{
delay(300); //消抖
if(key_down==0) //如果减小按键真的按下
{
while(key_down==0);
if(mode==1)hour_t--;if(hour_t<0)hour_t = 0;hour = hour_t;
if(mode==2)min_t--;if(min_t<0)min_t = 0;min=min_t;
if(mode==3)sec_t--;if(sec_t<0)sec_t = 0;sec = sec_t;
if(mode==4)hour_n--;if(hour_n<0)hour_n = 0;
if(mode==5)min_n--;if(min_n<0)min_n = 0;
}
}
}
显示函数
void display(unsigned char x1,x2)
{
P3_0 = 0; //锁存器关
P0 = x1; //输入位选
P3_0 = 1; //锁存器开
P3_0 = 0; //锁存器关
P0 = x2; //输入段选
}
void dis_play0() //mode = 0 正常 显示
{
switch(i)
{
case 0:display(0x01,seven_seg[sec%10]);break; //显示秒个位
case 1:display(0x02,seven_seg[sec/10]);break; //显示秒十位
case 2:display(0x04,0xbf|flash);break; //显示 - 闪烁
case 3:display(0x08,seven_seg[min%10]);break; //显示分个位
case 4:display(0x10,seven_seg[min/10]);break; //显示分十位
case 5:display(0x20,0xbf|flash);break; //显示 - 闪烁
case 6:display(0x40,seven_seg[hour%10]);break; //显示时个位
case 7:display(0x80,seven_seg[hour/10]);break; //显示时十位
}
}
void dis_play1() //mode = 1 调时
{
switch(i)
{
case 0:display(0x01,seven_seg[sec_t%10]);break; //显示调秒个位
case 1:display(0x02,seven_seg[sec_t/10]);break; //显示调秒十位
case 2:display(0x04,0xbf);break; //显示 -
case 3:display(0x08,seven_seg[min_t%10]);break; //显示调分个位
case 4:display(0x10,seven_seg[min_t/10]);break; //显示调分十位
case 5:display(0x20,0xbf);break; //显示 -
case 6:display(0x40,seven_seg[hour_t%10]|flash);break; //显示调时个位 闪烁
case 7:display(0x80,seven_seg[hour_t/10]|flash);break; //显示调时十位 闪烁
}
}
void dis_play2() //mode = 2 调分
{
switch(i)
{
case 0:display(0x01,seven_seg[sec_t%10]);break; //显示调秒个位
case 1:display(0x02,seven_seg[sec_t/10]);break; //显示调秒十位
case 2:display(0x04,0xbf);break; //显示 -
case 3:display(0x08,seven_seg[min_t%10]|flash);break; //显示调分个位 闪烁
case 4:display(0x10,seven_seg[min_t/10]|flash);break; //显示调分十位 闪烁
case 5:display(0x20,0xbf);break; //显示 -
case 6:display(0x40,seven_seg[hour_t%10]);break; //显示调时个位
case 7:display(0x80,seven_seg[hour_t/10]);break; //显示调时十位
}
}
void dis_play3() //mode = 3 调秒
{
switch(i)
{
case 0:display(0x01,seven_seg[sec_t%10]|flash);break; //显示调秒个位 闪烁
case 1:display(0x02,seven_seg[sec_t/10]|flash);break; //显示调秒十位 闪烁
case 2:display(0x04,0xbf);break; //显示 -
case 3:display(0x08,seven_seg[min_t%10]);break; //显示调分个位
case 4:display(0x10,seven_seg[min_t/10]);break; //显示调分十位
case 5:display(0x20,0xbf);break; //显示 -
case 6:display(0x40,seven_seg[hour_t%10]);break; //显示调时个位
case 7:display(0x80,seven_seg[hour_t/10]);break; //显示调时十位
}
}
void dis_play4() //mode = 4 调闹时
{
switch(i)
{
case 0:display(0x01,0xbf);break; //显示 -
case 1:display(0x02,0xbf);break; //显示 -
case 2:display(0x04,0xbf);break; //显示 -
case 3:display(0x08,seven_seg[min_n%10]);break; //显示闹分个位
case 4:display(0x10,seven_seg[min_n/10]);break; //显示闹分十位
case 5:display(0x20,0xbf);break; //显示 -
case 6:display(0x40,seven_seg[hour_n%10]|flash);break; //显示闹时个位 闪烁
case 7:display(0x80,seven_seg[hour_n/10]|flash);break; //显示闹时十位 闪烁
}
}
void dis_play5() //mode = 5 调闹分
{
switch(i)
{
case 0:display(0x01,0xbf);break; //显示 -
case 1:display(0x02,0xbf);break; //显示 -
case 2:display(0x04,0xbf);break; //显示 -
case 3:display(0x08,seven_seg[min_n%10]|flash);break; //显示闹分个位 闪烁
case 4:display(0x10,seven_seg[min_n/10]|flash);break; //显示闹分十位 闪烁
case 5:display(0x20,0xbf);break; //显示 -
case 6:display(0x40,seven_seg[hour_n%10]);break; //显示闹时个位
case 7:display(0x80,seven_seg[hour_n/10]);break; //显示闹时十位
}
}