/*硬件连接:段选码P0.0~P0.7(a,b,c,d,e,f,g,h,dp),位选码P2.0~P2.5(高到低) K1--P3.5;K2--P3.4;K3--P3.3;K4--P3.2*/
#include "reg52.h" #include "intrins.h" #define uchar unsigned char #define uint unsigned int uchar code BitTab[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf}; uchar code DispTab[]={0xc0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90}; uchar DispBuf[6]; //6字节的显示缓冲区 bit Sec; //1s到的标记 bit Minute; //1m到的标记 bit Hour; //1h到的标记 bit H_up; bit H_down; bit M_up; bit M_down; sbit P2_7=P2^7; //周期测试位 uchar SecValue; //秒计数 uchar MinuteValue; //分计数 uchar HourValue; //时计数
uchar code TH0Val=63075/256; uchar code TL0Val=63075%256;//晶振为12M,定时2.5ms定时器初值(计算值为63036,校准值为63075)
void Timer0() interrupt 1 { uchar tmp; static uchar dCount; //计数器,显示程序通过它得知现在显示那个数码管 static uint Count; //秒计数器 const uint CountNum=400; //预置值(400*2.5ms=1minute) P2_7=~P2_7; //外部测试位,用于调整定时器初值 TH0=TH0Val; TL0=TL0Val; tmp=BitTab[dCount]; //根据当前的计数值取位值 P2=P2|0x3f; //P2与00111111相或,将低6位置1 P2=P2&tmp; //P2与取出的值相与,将某一位清0 tmp=DispBuf[dCount]; //根据当前的计数值,取显示缓冲区的待显示值 tmp=DispTab[tmp]; //取字形码 P0=tmp; //送出字形码 dCount++; //计数值加1 if(dCount==6) //如果计数值为6,归0 dCount=0; //以下为秒计数 Count++; //计数值加1 if(Count>=CountNum) //到达预置计数值 { Count=0; //清零 Sec=1; //置1秒到标志位 SecValue++; //秒值加1 if(SecValue>=60) { SecValue=0; Minute=1; //置1分到标志位 MinuteValue++; //分值加1 } if(MinuteValue>=60) { Hour=1; //置1小时到标志位 MinuteValue=0; HourValue++; //小时值加1 if(HourValue>=24) {HourValue=0;} } } }
void Init() { TMOD=0x01; TH0=TH0Val; TL0=TL0Val; ET0=1; //开T0中断 EA=1; //开总中断 TR0=1; //T0开始运行 }
void mDelay(unsigned int Delay) //延时程序,用于键盘消抖 { unsigned int i; for(;Delay>0;Delay--) { for(i=0;i<124;i++) {;} } }
uchar Key() //键盘程序,获得键值 { uchar KValue; uchar tmp; P3|=0x3c; //将P3口接键盘的4位置1 KValue=P3; KValue|=0xc3; //将未接的四位置1 if(KValue==0xff) //中间4位均为1,无键按下 return(0); //返回 mDelay(10); //延时10mS消抖 KValue=P3; KValue|=0xc3; //再次读键盘 if(KValue==0xff) return(0); for(;;) { tmp=P3; if((tmp|0xc3)==0xff) //等待按键释放 break; } return(KValue); }
void KProce(uchar KValue) //键值处理程序 { if((KValue&0x20)==0) //K1 H_up=1; if((KValue&0x10)==0) //K2 H_down=1; if((KValue&0x08)==0) //K3 M_up=1; if((KValue&0x04)==0) //K4 M_down=1; }
void main() { uchar KValue; //存放键值 Init(); //初始化 DispBuf[4]=SecValue/10; DispBuf[5]=SecValue%10; for(;;) { DispBuf[2]=MinuteValue/10; DispBuf[3]=MinuteValue%10; DispBuf[0]=HourValue/10; DispBuf[1]=HourValue%10;
if(Sec) //1s时间到 { DispBuf[4]=SecValue/10; DispBuf[5]=SecValue%10; if(DispBuf[4]==0) Sec=0; //清除1s到标志位 }
if(Minute) { if(DispBuf[2]==0) Minute=0; //清除1m到标志位 }
if(Hour) { if(DispBuf[0]==0) Hour=0; //清除1h到标志位 }
KValue=Key(); //调键盘程序获得键值 if(KValue) //该值不等于0 { KProce(KValue); //调键盘处理程序 } if(H_up) //小时值调整 { HourValue++; if(HourValue>=24) { HourValue=0; } H_up=0; } if(H_down) { HourValue--; H_down=0; } if(M_up) //分值调整 { MinuteValue++; if(MinuteValue>=60) {MinuteValue=0; } M_up=0; } if(M_down) { MinuteValue--; M_down=0; } } }
一个51时钟程序, 有个地方不明白, P0与P2口输出电平不对应的? 我的意思是说:当PO口送出一个相应的字段码,而相对应字段码的位的电平确是不对的,搞不明白。 例如, Dcount=1, Dispbuf[0]=0, 则得 P2=oxfe, p0=oxc0, 两者的极性不会在共阳数码管对应的位上显示0的啊, 可是模拟的时候又是显示正常的,难道动态显示可以这么搞? |