|
手工做了個萬年歷放在工作臺前,仔細揀選ds1302模塊,竟然挺準,大約快一年不要校準。其中四個按鍵:1增鍵,2減鍵,3移位鍵,4設(shè)置鍵。長按4鍵進入設(shè)置,從年開始,設(shè)置位閃爍,1和2鍵點按增減,長按連續(xù)增減。短按4鍵切換到鬧鈴設(shè)置,時分位閃爍1,2鍵修改。再點按4鍵正常顯示并保存。在正常顯示時,短按4鍵,鬧鈴靜音,不按延時靜音。此按鍵只一個函數(shù)就完成四個鍵的長短和連發(fā),以狀態(tài)機編寫,來源于網(wǎng)上大咖,妙極。
電路原理圖如下:
單片機源程序如下:
- #include "REG52.H"
- #include<intrins.h>
- #include "key.h"
- extern struct sTime pdata CurTime; //ds1302定義 當(dāng)前日期時間
- extern struct sTime pdata CurTimeDec; //ds1302定義
- struct sTime pdata SetTimeBcd; //ds1302定義 日期時間設(shè)置緩沖區(qū)
- struct sTime pdata SetTimeDec; //本定義 轉(zhuǎn)換成十進制日期時間設(shè)置緩沖區(qū)
- extern enum eStaSystem staSystem ; //定義枚舉并賦予初值系統(tǒng)運行狀態(tài)
- extern code uchar SEGweek[];
- extern code uchar SEG[];
- extern uchar SetIndex=0 ; //main.c定義 設(shè)置位索引
- extern uchar pdata DigShow[16]; //main.c定義 顯示中間變量
- extern uchar pdata DisplayData[16]; //main.c定義 顯示緩沖區(qū)
- uchar FlashLock=0; //設(shè)置閃爍原子鎖
- uint FlashCnt=0; //設(shè)置閃爍計數(shù)器
- #define Flash_half 100 //閃爍計數(shù)的半值
- #define Flash_all 200 //閃爍計數(shù)的全值 一定要比 半值大
- bit staMute = 0; //靜音標志位
- uint8 AlarmHour = 7; //鬧鐘時間的小時數(shù)
- uint8 AlarmMin = 30; //鬧鐘時間的分鐘數(shù)
- uint8 pdata SetAlarmHour; //鬧鐘小時數(shù)設(shè)置緩沖
- uint8 pdata SetAlarmMin; //鬧鐘分鐘數(shù)設(shè)置緩沖
- bit staBuzzer = 0; //蜂鳴器狀態(tài)控制位,1-鳴叫、0-關(guān)閉
- void DS1302SingleWrite(uchar reg, uchar dat);//ds1302.c定義的函數(shù)
- void WritinTime(struct sTime *time);
- void RefreshTime();
- sbit key1 = P3^0 ;
- sbit key2 = P3^1 ;
- sbit key3 = P3^2 ;
- sbit key4 = P3^3 ;
- #define key_value1 0x0e //1110
- #define key_value2 0x0d //1101
- #define key_value3 0x0b //1011
- #define key_value4 0x07 //0111
- #define key_null 0x0f
- #define key_long_period 10
- #define key_continue_period 1
- #define key_down 0x80 //定義按鍵返回值狀態(tài)(按下,長按,連發(fā),釋放)
- #define key_long 0x40
- #define key_continue 0x20
- #define key_up 0x10
- enum key_state
- {
- key_state_init ,
- key_state_wobble ,
- key_state_press ,
- key_state_long ,
- key_state_continue ,
- key_state_release
- };
-
- enum key_state KeyState = key_state_init ;
-
- uchar KeyScan(void) //執(zhí)行按鍵掃描
- {
- if(key1 == 0)
- return key_value1 ;
- if(key2 == 0)
- return key_value2 ;
- if(key3 == 0)
- return key_value3 ;
- if(key4 == 0)
- return key_value4 ;
- return key_null ; //無效
- }
- void KeyInit(void)
- {
- key1 = 1 ;
- key2 = 1 ;
- key3 = 1 ;
- key4 = 1 ;
- }
- void GetKey(uint8 *pKeyValue)
- {
- static uint8 KeyTimeCount = 0 ;
- static uint8 LastKey = key_null ; //保存按鍵釋放時候的鍵值
- uint8 KeyTemp = key_null ; //鍵值變量賦初值 無效鍵值
- KeyTemp = KeyScan() ; //獲取鍵值
- switch(KeyState)
- {
- case key_state_init : //初始態(tài)S1
- {
- if( key_null != (KeyTemp)) //鍵值不為無效 有鍵按下
- {
- KeyState = key_state_wobble ; //進入消抖態(tài) state_init,
- }
- }
- break ;
- case key_state_wobble : //在消抖態(tài)S2
- {
- KeyState = key_state_press ; // 依舊按下態(tài)
- }
- break ;
- case key_state_press : //在按下態(tài)S3
- {
- if( key_null != (KeyTemp)) //鍵按下
- {
- LastKey = KeyTemp ; //保存鍵值,以便在釋放按鍵狀態(tài)返回鍵值
- KeyTemp |= key_down ; //////////////////0x80
- KeyState = key_state_long ;//長按態(tài) S4
- }
- else
- {
- KeyState = key_state_init ; //初始態(tài)
- }
- }
- break ;
- case key_state_long : ////長按態(tài)
- {
- if( key_null != (KeyTemp)) //
- {
- if(++KeyTimeCount > key_long_period )//時間計數(shù)大于閥值300 3s
- {
- KeyTimeCount = 0 ; //計數(shù)清零
- KeyTemp |= key_long ; ////////////////////// //長按鍵事件發(fā)生0x40
- KeyState = key_state_continue ; //連發(fā)
- }
- }
-
- else
- {
- KeyState = key_state_release ; //釋放態(tài)
- }
- }
-
- break ;
- case key_state_continue : // //連動態(tài)S5
- {
- if( key_null != (KeyTemp)) ///
- {
-
- if(++KeyTimeCount >key_continue_period ) //連發(fā)態(tài)25階段一段時間
- {
- KeyTimeCount = 0 ; //
- KeyTemp |= key_continue ; /////////////////////////連發(fā)事件發(fā)生0x20
- }
- }
-
-
- else
- {
- KeyState = key_state_release ; ////釋放態(tài)
- }
- }
- break ;
- case key_state_release : ////釋放態(tài)S6
- {
- LastKey |= key_up ; /////////////////////////鍵彈起
- KeyTemp = LastKey ; //
- KeyState = key_state_init ; //初始化
- }
- break ;
- default : break ;
- }
- *pKeyValue = KeyTemp ; //返回鍵值
- }
-
-
- void RefreshTime()
- {
- DigShow[0] =SEG[ CurTimeDec.year/10 ]; //年份
- DigShow[1] = SEG[CurTimeDec.year %10];
- DisplayData[0] =DigShow[0] ;
- DisplayData[1]=DigShow[1];
-
- DigShow[2] = SEG[CurTimeDec.mon/10] ; //月份
- DigShow[3] = SEG[CurTimeDec.mon %10];
- if(CurTimeDec.mon/10==0) DisplayData[2]=0xff;
- DisplayData[2] =DigShow[2] ;
- DisplayData[3]=DigShow[3];
-
- DigShow[4] = SEG[CurTimeDec.day /10] ; //日期
- DigShow[5] = SEG[CurTimeDec.day %10];
- if(CurTimeDec.day /10==0) DisplayData[4]=0xff;
- DisplayData[4] =DigShow[4] ;
- DisplayData[5]=DigShow[5];
-
- DigShow[10]=SEGweek[CurTimeDec.week%10];
- DisplayData[10]=DigShow[10];
-
- DigShow[6]=SEG[CurTimeDec.hour/10 ]; //時
- DigShow[7]=SEG[CurTimeDec.hour%10];
- ……………………
- …………限于本文篇幅 余下代碼請從51黑下載附件…………
復(fù)制代碼
Keil代碼下載(不含仿真和原理圖):
Keil代碼.7z
(38.71 KB, 下載次數(shù): 45)
2022-1-13 00:08 上傳
點擊文件名下載附件
keil文件
|
評分
-
查看全部評分
|