單片機源程序如下:
- #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)
2019-3-28 15:26 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
|