最近在做单片机系统的项目设计,自己的系统板还在厂家制作,要一段时间才能送来,借用同学的小开发板先写了一个简易数字钟程序! 基本情况如下: 硬件平台:单片机:华邦系列W78E516B40DL 晶振:12MHZ 8个二极管 四个数码管 四个按键 一个温度传感器 串口通信:MAX232 软件平台:Keil uVision2 开发语言:C语言 程序下载软件:8051IspWriter.exe 程序实现功能:4个数码管依次显示分钟和秒钟,4个按键,按SW1,SW2,SW3,SW4依次实现分钟,秒钟的十位,个位加一! 最终源程序如下: #include<reg51.h> #include<absacc.h> #define uchar unsigned char #define uint unsigned int uchar *dis_ptr; uchar data dis_buf[4]={0,0,0,0};//显示缓冲区 uchar data time_buf[2]={0x00,0x00};//显示数据 uchar code seg_tab[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82, 0xf8,0x80,0x90,0xff};//7段共阳极,依次为0-9 uchar code digit_tab[4]={1,2,4,8};//动态显示缓冲区 uint m=0; uint n=0; uint key_flag=0; sbit p24=P2^4; sbit p25=P2^5; sbit p26=P2^6; sbit p27=P2^7; void init_sys(); void disply_one(void); void dis_buf_flash(void); bit key_test(void); void key(void); void key_delay(); void main() {init_sys(); for(;;);} void init_sys(void)//T0工作于方式2,定时250um, { dis_ptr=dis_buf+3; TH0=6; TL0=6; TMOD=2; IE=0x82; IP=2; TR0=1; }
void disply_one(void)//动态显示1位 {uchar i; P0=seg_tab[*dis_ptr]; i=dis_ptr-dis_buf; P2=~digit_tab; if (dis_ptr>dis_buf) dis_ptr--; else dis_ptr=dis_buf+3; }
void dis_buf_flash(void)//显示数据送缓冲区 { dis_buf[0]=time_buf[0]/10; dis_buf[1]=time_buf[0]%10; dis_buf[2]=time_buf[1]/10; dis_buf[3]=time_buf[1]%10; }
void time0(void) interrupt 1 { TF0=0; m++; n++; if(key_test()==0) {key_delay(); if(key_test()==0) {key_flag=0;} } if ((n>=40)&&(key_flag==0))//10ms扫描键盘 {n=0; key_test();//扫描键盘 if(key_test()==1){ key_delay(); if(key_test()==1) {key();} } } if (m>=4000)//1秒处理 { m=0; time_buf[1]+=1; if (time_buf[1]>=60)//1分处理 {time_buf[1]=0; time_buf[0]+=1;} if (time_buf[0]>=60)//1时处理 {time_buf[0]=0; time_buf[1]=0;} } dis_buf_flash(); disply_one(); } bit key_test(void)//测试键盘有无键按下 { if ((p24==0)||(p25==0)||(p26==0)||(p27==0)) return ((bit)1); else return ((bit)0); }
void key(void)//按键处理 {key_flag=1; if(p24==0){ time_buf[0]+=10;} else if(p25==0){time_buf[0]+=1;} else if(p26==0){time_buf[1]+=10;} else time_buf[1]+=1;
}
void key_delay() {uchar i,s; for(i=10000,s=5;s>=1;i--) {s=i;} } 最终正常显示,按键可调!
中途遇到的问题: 按单键无反映!只有一起按紧SW1和SW2才出现分钟的两位一直向上加,但也不可控制加的大小! 解决1:在按键和释放键的时候加一个去抖动延迟函数 void key_delay() {uchar i,s; for(i=10000,s=5;s>=1;i--) {s=i;} 结果:
按每个按键都能改变相应的位数的数字,但不可控制。改变太快!
解决2:加一个扫描标志,当检测到有键按下时,停止扫描键盘,当键释放时,继续扫描键盘 这样就能保证按一次键被扫描一次,从而实现加一。
|