最近刚学了数码管动态扫描和矩阵键盘,正好把这两个内容合并在一起写了这个可调时钟
仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)
单片机源程序如下:
- #include<at89x51.h>
- #define uint unsigned int
- #define uchar unsigned char
- uint time_t;//毫秒统计值
- char hour_now,min_now,sec_now,// 实时时间
- hour_a1,min_a1,sec_a1,
- hour_a2,min_a2,sec_a2;//闹钟时间
- uchar key,key_num,time_cdk;//键盘扫描值,键盘键值
- uchar code led[10]={0xfc,0x60,0xda,0xf2,
- 0x66,0xb6,0xbe,0xe0,0xfe,0xf6};//数码管显示0-9
- sbit beep=P3^7;//定义P3.7口为蜂鸣器控制口
- /********************************************************************/
- //函数名:delay_1ms(uint x)
- //功能:利用定时器0精确定时1ms; 自加 time_t的值为后面时间调整函数服务
- //调用函数:
- //输入参数:x,1ms计数
- //输出参数:
- //说明:延时的时间为1ms乘以x
- /********************************************************************/
- void delay_1ms(uint x)
- {
- TMOD=0X01;//开定时器0,工作方式为1
- TR0=1;//启动定时器0;
- while(x--)
- {
- TH0=0Xfc;//定时1ms初值的高8位装入TH0
- TL0=0X18;//定时1ms初值的低8位装入TL0
- while(!TF0);//等待,直到TF0为1
- TF0=0;
- time_t++;//毫秒统计值自加1
- }
- TR0=0;//停止定时器0;
- }
- /**********************************************************/
- //函数名:display_num(uchar num,dis_w)
- //功能:2位数码管显示
- //调用函数:delay_1ms(uint x)
- //输入参数:num,dis_w
- //输出参数:
- //说明:P0口做数码管段选,P2口做位选
- //通过dis_w的值确定num值在数码管上显示的位置
- /**********************************************************/
- void display_num(uchar num,dis_w)
- {
- uchar j;
- for(j=0;j<2;j++)
- {
- P0=0xff;//段选口置高,消影
- P2=~dis_w;//装入位选值
- if(j>0)
- P0=~led[num/10];//显示num个位
- else
- P0=~led[num%10];//显示num十位
- dis_w=dis_w<<1;
- delay_1ms(5);//延时5ms
- }
- }
- /**********************************************************/
- //函数名:display_char()
- //功能:显示时间分隔符“-”
- //调用函数:delay_1ms(uint x)
- //输入参数:
- //输出参数:
- //说明:
- /**********************************************************/
- void display_char()
- {
- P0=0xff;//段选口置高,消影
- P2=~0x24;
- P0=~0x02;//显示字符“-”
- delay_1ms(5);//延时5ms
- }
- /**********************************************************/
- //函数名:display(uchar sec,min,hour)
- //功能:8位数码管显示
- //调用函数:display_num(uchar num,dis_w),display_char()
- //输入参数:sec,min,hour
- //输出参数:
- //说明:数码管显示完整的时间
- /**********************************************************/
- void display(uchar sec,min,hour)
- {
- display_num(sec,0x01);//显示秒
- display_num(min,0x08);//显示分
- display_num(hour,0x40);//显示小时
- display_char();//显示分隔符“-”
- }
- /**********************************************************/
- //函数名:time_take()
- //功能:时间调整
- //调用函数:
- //输入参数:
- //输出参数:
- //说明:通过time_t的值调整个时间单位,24小时制,定时报警
- /**********************************************************/
- void time_take()
- {
- if(((hour_now==hour_a1&min_now==min_a1)|(hour_now==hour_a2&min_now==min_a2))&
- ((sec_now<6&time_cdk==0)|(sec_now>55&time_cdk==1)))//判断是否到定时值
- beep=0;//到定时值,启动蜂鸣器
- else
- beep=1;//未到定时值,关蜂鸣器
- if(time_t>=1000)//当总延时数为1s时
- {
- time_t=0;//time_t清零
- if(time_cdk==0)
- {
- sec_now++;//秒加1
- if(sec_now>=60)//当秒值等于60时
- {
- sec_now=0;//秒值清零
- min_now++;//分加1
- if(min_now>=60)//当分等于60时
- {
- min_now=0;//分清零
- hour_now++;//小时加1
- if(hour_now>=24)//当小时等于24时
- hour_now=0;//小时清零
- }
- }
- }
- else
- sec_now--;//秒加1
- if(sec_now<0)//当秒值等于60时
- {
- sec_now=59;//秒值清零
- min_now--;//分加1
- if(min_now<0)//当分等于60时
- {
- min_now=59;//分清零
- hour_now--;//小时加1
- if(hour_now<0)//当小时等于24时
- hour_now=23;//小时清零
- }
- }
- }
- }
- /**********************************************************/
- //函数名:keyscan()
- //功能:得出4x4键盘的行列扫描值
- //调用函数:delay_1ms(uint x)
- //输入参数:
- //输出参数:
- //说明:通过P1口的扫描得出扫描值key,无键按下key为0
- /**********************************************************/
- uchar keyscan()
- {
- uchar code_h;//行编码
- uchar code_l;//列编码
- P1=0XF0;
- if((P1&0xF0)!=0XF0)
- {
- delay_1ms(5);//调用定时函数
- if((P1&0xF0)!=0XF0)
- {
-
- code_h=0xfe;
- while((code_h&0x10)!=0x00)
- {
- P1=code_h;
- if((P1&0xF0)!=0XF0)
- {
- code_l=(P1&0xF0|0x0F);
- return((~code_h)+(~code_l));
- }
- else
- code_h=(code_h<<1)|0x01;
- }
- }
- }
- return(0);//无键按下返回0
- }
- /**********************************************************/
- //函数名:keynum()
- //功能:得出4x4按键的键值
- //调用函数:keyscan()
- //输入参数:
- //输出参数:
- //说明:通过key的值确定安键键值
- /**********************************************************/
- void keynum()
- {
- uchar i,j;
- uchar code tab[4][4]={{1,2,3,4},{5,6,7,8},{9,0,11,12},{13,14,15,16}};
- //4x4键盘各键值标注
- key=0;
- key=keyscan();//引入key值
- if((key&0x01)!=0) i=0;
- if((key&0x02)!=0) i=1;
- if((key&0x04)!=0) i=2;
- if((key&0x08)!=0) i=3;
- if((key&0x10)!=0) j=0;
- if((key&0x20)!=0) j=1;
- if((key&0x40)!=0) j=2;
- if((key&0x80)!=0) j=3;
- if(key!=0) key_num=tab[i][j];//通过比较得出4x4键盘的键值
- }
- /**********************************************************/
- //函数名:keyplay(uchar sec,min,hour,tkey)
- //功能:时间调整,包括定时时间
- //调用函数:display(uchar sec,min,hour);keynum()
- //输入参数:
- //输出参数:
- //说明:tkey的值确定调整的时间类型,带除错功能
- /**********************************************************/
- void keyplay(uchar sec,min,hour,tkey)
- {
- uchar data timenum[]={0,0,0,0,0,0};//建立时间各单位数组
- uchar i=0,take_key;
- keynum();//调用键值程序
- if(key_num==16)//按键值为16时
- {
- time_cdk=1;//倒计时开关置1
- }
- if(key_num==15)//按键值为15时
- {
- time_cdk=0;//倒计时开关置0
- }
- if(key_num==tkey)//判断调整键有无按下
- {
- take_key=1;//循环开关值设1
- timenum[0]=hour/10;
- timenum[1]=hour%10;
- timenum[2]=min/10;
- timenum[3]=min%10;//将原时间引入修改模式
- while(take_key)//判断是否在设定模式中
- {
- keynum();
- while(key!=0)//键盘松手检测
- keynum();
- if(key_num<11)//判断键值是否为0-9数字键
- {
- i++;
- timenum[i-1]=key_num;//键值赋值于数组
- key_num=17;//键值清空
- }
- if(key_num==12)//判断有无按下确定键
- take_key=0;//开关值置0,跳出循环
- if(i==6)
- take_key=0;//6位数调整结束,自动跳出循环
- hour=timenum[0]*10+timenum[1];
- min=timenum[2]*10+timenum[3];
- sec=timenum[4]*10+timenum[5];//调整值赋值于调整时间
- display(sec,min,hour);
- }
- if(sec>59)
- sec=0;
- if(min>59)
- min=0;
- if(hour>23)
- hour=0;//时间溢出排错
- if(tkey==11)//调整键11为实时时间调整
- {
- sec_now=sec;
- min_now=min;
- hour_now=hour;
- }
- if(tkey==13)//调整键13为定时值a1调整
- {
- sec_a1=sec;
- min_a1=min;
- hour_a1=hour;
- }
- if(tkey==14)//调整键14为定时值a2调整
- {
- sec_a2=sec;
- min_a2=min;
- hour_a2=hour;
- }
- }
- }
- /**********************************************************/
- /**********************************************************/
- void main()
- {
- sec_now=57;
- min_now=59;
- hour_now=23;
- sec_a1=0;
- min_a1=0;
- hour_a1=0;
- sec_a2=1;
- min_a2=1;
- hour_a2=1; //各时间初始化
- time_cdk=0;
- while(1)
- {
- display(sec_now,min_now,hour_now);//显示实时时间
- time_take();//调用时间调整程序
- keyplay(sec_now,min_now,hour_now,11);//调整的时间为实时时间
- keyplay(sec_a1,min_a1,hour_a1,13);//调整的时间为定时值a1
- keyplay(sec_a2,min_a2,hour_a2,14);//调整的时间为定时值a2
- }
- }
复制代码 全部资料51hei下载地址:
八位一体时钟加矩阵键盘.zip
(58.54 KB, 下载次数: 38)
|