数字时钟(数码管显示/键盘可调)
有关的硬件原理图:


c程序:
//温馨提示: /*程序还没有调试完成,实际电路板调节时间时时-分-秒都会有闪烁现象,其实我是不知道的,why,也求解释 #include<reg52.h> //包含头文件,一般情况不需要改动,头文件包含特殊功能寄存器的定义 #include<intrins.h> //与_nop_有关 sbit duan=P2^2; //定义锁存使能端口 段锁存 sbit wei=P2^3; // 位锁存 sbit key1 = P1^1; sbit key2 = P1^2; sbit key3 = P1^3; sbit key4 = P1^4; unsigned char code duanma[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f}; // 显示段码值0~9 unsigned char code weima[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f}; //分别对应相应的数码管点亮,即位码 unsigned char temp[8]; //存储显示值的全局变量 char hour; minute; second, num, t, i; //函数声明 void delay(unsigned int t); void initial(); void delay20ms(); void keyscan(); void caifen(); void display(); /*------------------------------------------------ 主函数 ------------------------------------------------*/ void main() { initial(); //调用初始化程序 while(1) { keyscan(); //调用键盘扫描 caifen(); //调用拆分以时-分-秒的形式 display(); //调用时间的显示程序 } } //初始化程序 void initial() { TMOD = 0x01; //设置T1工作于定时方式1(有16位计数) TH0 = (65536 - 2000)/256; //定时器1赋初值,是TH1而不是TH0噢(若要设置是定时器0的话,把1改为0,下同);计数了2000次,即为2ms TL0 = (65536 - 2000)%256; EA = 1; //开中断 TR0 = 1; //开定时器0 ET0 = 1; //开启定时器中断0 hour = 23; //赋初值 minute = 59; //赋初值 second = 57; //赋初值 } //中断服务程序 void time0(void) interrupt 1 { TH0 = (65536 - 2000)/256; //重新赋值 TL0 = (65536 - 2000)%256; num ++; //中断500次后 即2ms X 500 = 1000MS = 1S,(一般可计数久点如50000ms,中断20次,这样误差就不会太大) if (num == 500) { num = 0; second ++; if (second == 60) //秒为60则miao置0,minute加一 { second = 0; minute ++; if (minute == 60) //分为60则minute置0,hour加一 { minute = 0; hour ++; if (hour == 24) //小时为24则hour置0 { hour = 0; } } } } } //键盘扫描程序,可执行时分的加减 void keyscan() { if(key1 == 0) { delay20ms(); //延时20ms,去抖动 while(key1 == 0); //等待(上升沿则执行下一行,TRO = 0) TR0 = 0; //关定时器0 t ++; //t++与调节时分秒有关 } switch(t) //选择调节时分秒有关,与上面的t相关联 { case 1: if(key2 == 0) { delay20ms(); if(key2 == 0) { while(key2 == 0); hour ++; if(hour == 24) { hour = 0; } } } if(key3 == 0) { delay20ms(); if(key3 == 0) { while(key3 == 0); hour --; if(hour == -1) //因为hour是char型,所以可以有负数,若是unsigned char则不允许,下面的minute同理 { hour =23; } } } break; case 2: if(key2 == 0) { delay20ms(); if(key2 == 0) { while(key2 == 0); minute ++; if(minute == 60) { minute = 0; } } } if(key3 == 0) { delay20ms(); if(key3 == 0) { while(key3 == 0); minute --; if(minute == -1) { minute = 59; } } } break; case 3: TR0 = 1; //当t为3时,则开定时器,重新开始计数,又因为执行了caifen();所以数码管显示时分秒是由我们调节的数 t = 0; break; default: //default必须加,要养成良好的编程风格 break; //一般也是必须加的,详情请参考c语言书籍,以上所有的break同是 } } //数字拆分程序//数据的转换,因我们采用数码管0~9的显示,将数据分开 void caifen() { temp[0]=duanma[hour/10]; //时 temp[1]=duanma[hour%10]; temp[2]=0x40; //加入"-" temp[3]=duanma[minute/10];//分 temp[4]=duanma[minute%10]; temp[5]=0x40; temp[6]=duanma[second/10];//秒 temp[7]=duanma[second%10]; } //显示程序 void display() { for (i = 0; i < 8; i ++) { wei=1; //位锁存 P0=weima[i]; //取位码 wei=0; duan=1; //段锁存 P0=temp[i]; //取显示数据,段码 duan=0; delay(310); //具体最佳是多少不清楚,大家可自行修改,通过keil调试可具体知道执行时间是多少 } } //延时20ms,使用单片机小精灵生成的 void delay20ms(void) //误差 20us { unsigned char a,b; for(b=215;b>0;b--) for(a=45;a>0;a--); _nop_; //if Keil,require use intrins.h _nop_; //if Keil,require use intrins.h } //延时 void delay(unsigned int i) { while (i --); }
浙公网安备 33010602011771号