单片机源程序如下:
- #include<stc15.h>
- #include<intrins.h>
- #define uchar unsigned char
- #define uint unsigned int
- uint bdata key; //定义变量,键状态
- uint bdata edgk; //定义变量,键状态变化前沿
- uchar data kcode; //定义变量,键编号
- sbit ESET=edgk^4; //重定义KC键为设置键(触发型)
- sbit EINC=edgk^6; //定义K17键为加1键(触发型)
- sbit EDEC=edgk^7; //定义K18键为减1键(触发型)
- sbit SETK=key^4; //重定义KC键为设置键(开关型)
- sbit ALA=key^5;
- sbit ALARM=edgk^5;
- sbit EKF=edgk^7;
- sbit EKE=edgk^6;
- sbit K17=P3^2;
- sbit K18=P3^3;
- uchar data state; //定义变量,工作状态
- uchar data timer; //定义变量,0.5秒计时器
- uchar data KeyOnTmr; //定义变量,调整键长键计时
- uchar data Keytmr;
- uchar data hour=0x0c; //定义变量,时变量,二进制
- uchar data min=0x00; //定义变量,分变量,二进制
- uchar data sec=0x00; //定义变量,秒变量,二进制
- uchar data set_num; //定义变量,当前调整位,0~"时"十位,3~"分"个位
- uchar data clock_flag;
- uchar beeftmr;
- uchar data ktmr;
- sbit BEEF=P2^7;
- sbit LED7=P1^7;
- sbit LED8=P1^6;
- sbit P_HC595_SER=P4^0;
- sbit P_HC595_RCLK=P5^4;
- sbit P_HC595_SRCLK=P4^3;
- uchar code SEG7[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71,0x00};
- uchar code Scon_bit[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};
- uchar data dis_buf[]={16,16,16,16,16,16,16,16};
- uchar data alarm_clock[]={0,0,0,0,0,0,0,0};
- void Delay1ms(){
- uchar i,j;
- _nop_();
- _nop_();
- _nop_();
- i=11;
- j=190;
- do{
- while(--j);
- }while(--i);
- }
- void F_Send_595(uchar x){
- uchar i;
- for(i=0;i<8;i++){
- x=x<<1;
- P_HC595_SER=CY;
- P_HC595_SRCLK=1;
- P_HC595_SRCLK=0;
- }
- }
- void display(void){
- uchar i;
- for(i=2;i<8;i++){
- F_Send_595(Scon_bit[i]);
- if((state==1||state==2)&&i==set_num&&(sec&1)==1)
- F_Send_595(SEG7[16]);
- else
- F_Send_595(SEG7[dis_buf[i]]);
- P_HC595_RCLK=1;
- P_HC595_RCLK=0;
- //Delay1ms();
- }
- }
- void readkey()
- { uchar i;
- P0=0x7f;
- for(i=0;i<20;i++);
- edgk=(~P0<<4)&0xf0;
- P0=0xbf;
- for(i=0;i<20;i++);
- edgk|=(~P0)&0x0f;
- edgk<<=8;
- P0=0xdf;
- for(i=0;i<20;i++);
- edgk|=(~P0<<4)&0xf0;
- P0=0xef;
- for(i=0;i<20;i++);
- edgk|=(~P0)&0x0f;
- EKE=0;EKF=0; //放弃矩阵键盘的KE、KF键状态
- if(!K17)EKE=1; //K17键状态存入edgk^6,或K17取代KE
- if(!K18)EKF=1; //K18键状态存入edgk^7,或K18取代KF
- }
- void keytrim()
- { uint temp;
- if(edgk==0)ktmr=0;
- else
- { if(ktmr<255)ktmr++;
- if(ktmr<8)edgk=0;
- }
- temp=edgk;
- edgk=(key^edgk)&edgk;
- key=temp;
- if(edgk!=0)
- { temp=edgk;
- for(kcode=0;(temp&0x1)==0;kcode++)temp>>=1;
- }
- else kcode=0x10;
- }
- void keysound()
- { if(edgk!=0)beeftmr=40;
- if(beeftmr!=0){beeftmr--;BEEF=0;}
- else BEEF=1;
- }
- void Timer0Init(void) //2500ms@11.0592MHz
- {
- AUXR |= 0x80;
- TMOD &= 0xF0;
- TL0 = 0x00;
- TH0 = 0x94;
- TF0 = 0;
- TR0 = 1;
- }
- void clock() //时钟走时函数
- { timer++; //计时,500ms回0
- if(timer>=200) //0.5秒到则
- { timer=0;sec++; //走秒
- if(sec>=120){sec=0;min++;} //60秒到则秒回0、走分
- if(min>=60){min=0;hour++;} //60分到则分回0、走时
- if(hour>=24)hour=0; //24时到则时回0
- }
- }
- void wrdisb() //设置显示缓冲器函数
- { dis_buf[2]=hour/10; //数码左第1位显示时"十"位
- dis_buf[3]=hour%10; //数码左第2位显示时"个"位
- dis_buf[4]=min/10; //数码左第3位显示分"十"位
- dis_buf[5]=min%10; //数码左第4位显示分"个"位
- dis_buf[6]=sec/20;
- dis_buf[7]=(sec/2)%10;
- }
- void inputcheck() //时分秒数值合理性检查
- {
- if(dis_buf[7]==255)dis_buf[7]=9; //秒个位-1
- if(dis_buf[7]==10)dis_buf[7]=0; //秒个位+1
- if(dis_buf[6]==255)dis_buf[6]=5; //秒十位-1
- if(dis_buf[6]==6)dis_buf[6]=0; //秒十位+1
- if(dis_buf[5]==255)dis_buf[5]=9; //分个位由0减1则回9
- if(dis_buf[5]==10)dis_buf[5]=0; //分个位由9加1则回0
- if(dis_buf[4]==255)dis_buf[4]=5; //分十位由0减1则回5
- if(dis_buf[4]==6)dis_buf[4]=0; //分十位由5加1则回0
- if(dis_buf[3]==255) //时个位由0减1则
- { if(dis_buf[2]==2)dis_buf[3]=3; //如时十位为2则时个位为3
- else dis_buf[3]=9; //否则时个位为9
- }
- if(dis_buf[3]==10)dis_buf[3]=0; //时个位由9加1则回0
- if(dis_buf[2]==255)dis_buf[2]=2; //时十位由0减1则回2
- if(dis_buf[2]==2&&dis_buf[3]>=4)dis_buf[3]=0; //时十位为2,个位超3则回0
- if(dis_buf[2]==3)dis_buf[2]=0; //时十位由2加1则回0
- }
- void compare(){
- uchar i;
- uchar flag=0;
- for(i=2;i<8;i++){
- if(dis_buf[i]!=alarm_clock[i]){
- flag=1; break;
- }
- }
- if(!flag) clock_flag=0x01;
- if(!LED7&&clock_flag==0x01){
- beeftmr=10;
- }else
- beeftmr=0;
- }
- void gpio(){
- P0M1=0; P0M0=0;
- P1M1=0; P1M0=0;
- P2M1=0; P2M0=0;
- P3M1=0; P3M0=0;
- P4M1=0; P4M0=0;
- P5M1=0; P5M0=0;
- }
- void main(void)
- { uchar i;
- BEEF=0; //初始化,上电时P3.0(BEEF)为高电平
- state=0; //默认待机态
- set_num=2;
- clock_flag=0x00;
- Timer0Init(); //调用T0定时器初始化函数
- gpio();
- while(1)
- { while(!TF0); //2.5mS定时未到则等待
- TF0=0; //清定时器溢出标志
- readkey(); //调用扫描键盘存键状态函数
- display(); //调用显示扫描函数
- keytrim(); //调用键状态消抖等处理函数
- keysound(); //调用有键发出"嘀"声响函数
- clock(); //时钟走时
- compare();
- switch(state) //根据状态转移
- { case 0: //时钟显示态
- {
- LED8=1;
- wrdisb(); //显示时分秒
- if(clock_flag==0x01&&(ESET||EINC||EDEC||ALARM)) clock_flag=0x00;
- if(!SETK)KeyOnTmr=0; //无SETK则键计时器清0
- else if(timer==0)KeyOnTmr++; //有SETK则键计时(时基0.5秒)
- if(KeyOnTmr==10) //判断长键达5秒?
- { KeyOnTmr=0;state=1;set_num=2; //长键计时复位,转时间调整态
- }
- if(!ALA) Keytmr=0;
- else if(timer==0)Keytmr++;
- if(Keytmr==10){
- Keytmr=0; state=2; set_num=2;
- }
- if(ALARM)LED7=!LED7;
- break;
- }
- case 1: //时间调整态
- { LED8=0; //LED8指示常亮
- if(ESET) //点按SET键则
- { set_num++; //调整位后移
- if(set_num==8) //4位都调整完则结束
- {
- min=dis_buf[4]*10+dis_buf[5];
- hour=dis_buf[2]*10+dis_buf[3];
- sec=dis_buf[6]*10+dis_buf[7];
- set_num=2;timer=0;state=0; //转时钟显示态
- }
- }
- if(EINC) //点按加1键则调整位+1,检查合理性
- { dis_buf[set_num]++;inputcheck();
- }
- if(EDEC) //点按减1键则调整位-1,检查合理性
- { dis_buf[set_num]--;inputcheck();
- }
- break;
- }
- case 2:
- {
- if(timer==0) LED8=!LED8;
- if(ALARM)
- {
- set_num++;
- if(set_num==6)
- {
- for(i=2;i<6;i++)
- alarm_clock[i]=dis_buf[i];
- wrdisb();
- LED7=0;
- set_num=2; state=0;
- }
- }
- if(EINC) //点按加1键则调整位+1,检查合理性
- { dis_buf[set_num]++;inputcheck();
- }
- if(EDEC) //点按减1键则调整位-1,检查合理性
- { dis_buf[set_num]--;inputcheck();
- }
- break;
- }
- }
- }
- }
复制代码
所有资料51hei提供下载:
shiyan5.zip
(72.78 KB, 下载次数: 14)
|