51單片機學(xué)習(xí)筆記:可對時電子鐘
本篇是對上一篇的改進,昨天學(xué)習(xí)了第4章 中的獨立鍵盤的使用
獨立鍵盤擁有自己獨有的IO口,所以比較簡單,我上一篇寫的電子鐘程序只能燒程序?qū)r,
不能手動按鍵對時,這肯定是最差勁的做法,所以學(xué)習(xí)了按鍵之后,就立馬動手改進我的電子鐘了
同時改進了數(shù)碼管小數(shù)點的顯示,消除了疊影
使用芯片STC89C52RC, 2個鎖存器
6個帶小數(shù)點共陰極數(shù)碼管顯示一個24時制時鐘
沒有時鐘芯片,所以掉電后時間會復(fù)位
原理圖為TX-1C開發(fā)板
==============================
最終顯示的<時.分.秒>是 16.31.37 形式
使用3個按鍵, S2 S3 S5
其中S2和S3是加減數(shù)值,S5是切換對時狀態(tài),
- #include <reg52.h>
- #include "MY51.H"
-
- void show();
- int8 shi=22; //初識時間22:45:00 按S5鍵進入對時模式
- int8 fen=45;
- int8 miao=0;
- uint8 timeFlag=0;//0計時模式,1校對時鐘,2校對分鐘,3校對秒鐘
- void main()
- {
- startT0(1000); //開始定時器
- while(1)
- {
- show(); //送入數(shù)碼管顯示
- if(keyS5==keyDown) //按下S5鍵
- {
- delayms(5);//消抖處理
- if(keyS5==keyDown)
- {
- while(1)
- {
- show();
- if(keyS5==keyUp)//放開按鈕
- {
- delayms(5); //消抖處理
- if(keyS5==keyUp)
- {
- break;
- }
- }
- }
- timeFlag=(++timeFlag)%4; //按S5鍵進行狀態(tài)切換
- while(timeFlag)
- {
- if(timeFlag==1)
- {
- led=0xff;
- led7=0; //進入對時鐘模式,且打開7號指示燈
- }
- else if(timeFlag==2)
- {
- led=0xff;
- led5=0; //進入校對分鐘模式,且打開5號指示燈
- }
- else if(timeFlag==3)
- {
- led=0xff;
- led3=0; //進入校對秒鐘模式,且打開3號指示燈
- }
-
- show(); //刷新數(shù)碼管
- if(keyS2==keyDown)//S2和S3用于調(diào)整數(shù)值,加減運算
- {
- delayms(5);//消抖處理
- if(keyS2==keyDown)
- {
- if(timeFlag==1)
- {
- shi--;
- if(shi<0)
- {
- shi=23;
- }
- }
- else if(timeFlag==2)
- {
- fen--;
- if(fen<0)
- {
- fen=59;
- }
- }
- else if(timeFlag==3)
- {
- miao--;
- if(miao<0)
- {
- miao=59;
- }
- }
- while(1)
- {
- show(); //就算S2鍵被按著,也要刷新數(shù)碼管
- if(keyS2==keyUp)
- {
- delayms(10);
- if(keyS2==keyUp)
- {
- break;
- }
- }
- }
-
- }
- }
-
- if(keyS3==keyDown)
- {
- delayms(5);//消抖處理
- if(keyS3==keyDown)
- {
- if(timeFlag==1)
- {
- shi++;
- if(shi>23)
- {
- shi=0;
- }
- }
- else if(timeFlag==2)
- {
- fen++;
- if(fen>59)
- {
- fen=0;
- }
- }
- else if(timeFlag==3)
- {
- miao++;
- if(miao>59)
- {
- miao=0;
- }
- }
- while(1)
- {
- show();
- if(keyS3==keyUp)
- {
- delayms(5);
- if(keyS3==keyUp)
- {
- break;
- }
- }
- }
-
- }
- }
-
- if(keyS5==keyDown)
- {
- delayms(5);//消抖處理
- if(keyS5==keyDown)
- {
- timeFlag=(++timeFlag)%4;//按S5鍵切換狀態(tài)
- while(1)
- {
- show();
- if(keyS5==keyUp)
- {
- delayms(5);
- if(keyS5==keyUp)
- {
- break;
- }
- }
- }
- }
- }
- }
- led=0xff; //對時結(jié)束,指示燈滅
- }
- }
- }
- }
-
-
- void show() //顯示時鐘
- {
- uint8 oneWela,twoWela,threeWela,foreWela,fiveWela,sixWela; //oneWela是最左邊的數(shù)碼管
- sixWela =miao%10;
- fiveWela=miao/10;
- foreWela=fen%10;
- threeWela=fen/10;
- twoWela=shi%10;
- oneWela=shi/10;
- displaySMG(oneWela,twoWela,threeWela,foreWela,fiveWela,sixWela,0xf5); //0xf5是小數(shù)點的位置
- }
-
- void T0_Work() //T0定時器調(diào)用的工作函數(shù)
- {
- miao++;
- if(miao>59)
- {
- miao=0;
- fen++;
- }
-
- if(fen>59)
- {
- fen=0;
- shi++;
- }
-
- if(shi>23)
- {
- shi=0;
- }
- }
復(fù)制代碼
- #ifndef _MY51_H_
- #define _MY51_H_
- #include <math.h>
- #include <intrins.h>
-
- typedef int int16 ;
- typedef int INT16 ;
- typedef unsigned int uint16 ;
- typedef unsigned int UINT16 ;
- typedef unsigned short uint ;
- typedef unsigned short UINT ;
- typedef unsigned short word ;
- typedef unsigned short WORD ;
- typedef unsigned long uint32 ;
- typedef unsigned long UINT32 ;
- typedef unsigned long DWORD ;
- typedef unsigned long dword ;
- typedef signed long int32 ;
- typedef signed long INT32 ;
- typedef float float32 ;
- typedef double double64 ;
- typedef signed char int8 ;
- typedef signed char INT8 ;
- typedef unsigned char byte ;
- typedef unsigned char BYTE ; //WINDOWS的windef.h里面是這么定義的
- typedef unsigned char uchar ;
- typedef unsigned char UCHAR ;
- typedef unsigned char UINT8 ;
- typedef unsigned char uint8 ;
- typedef unsigned char BOOL ; //windows中定義BOOL為int
- typedef unsigned char bool ; //bool是c++的內(nèi)置類型
-
- #define TRUE 1
- #define true 1
- #define FALSE 0
- #define false 0
-
- #define open 1 //open和close用于 標志打開和關(guān)閉狀態(tài)
- #define OPEN 1
- #define close 0
- #define CLOSE 0
- #define lock 0
- #define start 1
- #define START 1
- #define stop 0
- #define STOP 0
- #define keyDown 0
- #define keyUp 1
-
- sbit dula =P2^6; //段選鎖存器控制 控制筆段
- sbit wela =P2^7; //位選鎖存器控制 控制位置
-
- #define led P1 //燈總線控制
- sbit led0=P1^0; //8個led燈,陰極送低電平點亮
- sbit led1=P1^1;
- sbit led2=P1^2;
- sbit led3=P1^3;
- sbit led4=P1^4;
- sbit led5=P1^5;
- sbit led6=P1^6;
- sbit led7=P1^7;
-
- sbit keyS2=P3^4; //4個獨立按鍵
- sbit keyS3=P3^5;
- sbit keyS4=P3^6;
- sbit keyS5=P3^7;
-
- void displaySMG(uint8 one,uint8 two,uint8 three,uint8 four,uint8 five,uint8 six,uint8 dot);
- void delayms(uint16 ms);
- void T0_Work();
-
- void delayms(uint16 ms) //軟延時函數(shù)
- {
- uint16 i,j;
- for(i=ms;i>0;i--)
- {
- for(j=113;j>0;j--)
- {}
- }
- }
- ///////////////////////////////////////////////////////////////////////////
- #define dark 0x11 //在段中,0x11是第17號元素,為0是低電平,數(shù)碼管不亮
- #define dotDark 0xff //小數(shù)點全暗時
- uint8 code table[]= { //0~F外加小數(shù)點和空輸出的數(shù)碼管編碼
- 0x3f , 0x06 , 0x5b , 0x4f , // 0 1 2 3
- 0x66 , 0x6d , 0x7d , 0x07 , // 4 5 6 7
- 0x7f , 0x6f , 0x77 , 0x7c , // 8 9 A B
- 0x39 , 0x5e , 0x79 , 0x71 , // C D E F
- 0x80 , 0x00 // . 空 空時是第0x11號也就是第17號元素
- };
-
- /////////////////////////////////////////////////////////////////////////////
- uint8 TH0Cout=0 ; //初值
- uint8 TL0Cout=0 ;
- uint16 T0IntCout=0; //中斷計數(shù)
- uint16 T0IntCountAll=0; //(N-1)/65536+1; //總中斷次數(shù)
- bool bT0Delay=false; //使用延時函數(shù)標志,初始未用
- bool bT0Over=false; //中斷處理函數(shù)執(zhí)行結(jié)果之一
-
- void startT0(uint32 ms) //開啟定時器
- {
- float32 t=ms/1000.0; //定時時間
- double64 fox =11.0592*(pow(10,6)); //晶振頻率
- uint32 N=(t*fox)/12 ; //定時器總計數(shù)值
-
- TH0Cout =(65536-N%65536)/256; //裝入計時值零頭計數(shù)初值
- TL0Cout =(65536-N%65536)%256;
- T0IntCountAll=(N-1)/65536+1; //總中斷次數(shù)
- TMOD=TMOD | 0x01; //設(shè)置定時器0的工作方式為1
-
- EA =open; //打開總中斷
- ET0=open; //打開定時器中斷
-
- TH0=TH0Cout; //定時器裝入初值
- TL0=TL0Cout;
- TR0=start; //啟動定時器
- }
-
- void delayT0(uint32 ms) //硬延時函數(shù),自己亂寫的不好用,求指點
- {
- startT0(ms); //啟動定時器
- bT0Delay=true; //告訴T0定時器,起用延時模式
- while(bT0Over==false); //時間沒到的話繼續(xù)檢測
- bT0Over=false; //時間到了,讓標志復(fù)位
- }
-
- void T0_times() interrupt 1 //T0定時器中斷函數(shù)
- {
- T0IntCout++;
- if(T0IntCout==T0IntCountAll) //達到總中斷次數(shù)值
- {
- T0IntCout=0; //中斷次數(shù)清零,重新計時
- bT0Over=true; //時間真的到了
- if(bT0Delay) //本次中斷是用來延時的嗎
- {
- TR0=stop; //如果是由延時函數(shù)開啟T0的話,關(guān)閉T0
- return;
- }
-
- TH0=TH0Cout; //循環(huán)定時的話要重裝初值,每次定時1秒,重裝一次
- TL0=TL0Cout;
- T0_Work(); //工作函數(shù)
- }
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- void displaySMG(uint8 oneWela,uint8 twoWela,uint8 threeWela,uint8 fourWela,uint8 fiveWela,uint8 sixWela,uint8 dot)
- { //控制6位數(shù)碼管顯示函數(shù),不顯示的位用參數(shù) dark
- P0=0;
- dula=1;
- dula=0; //段選數(shù)據(jù)清空并鎖定
- //////////////////////////
- P0=0xff; //送位數(shù)據(jù)前關(guān)閉所有顯示
- wela=1;
- P0=0xfe;
- wela=0;
-
- P0=0; //低電平輸?shù)綌?shù)碼管陽極,避免數(shù)碼管吳亮
- dula=1;
- P0=table[oneWela]|((0x01&dot)?0x00:0x80); //送段數(shù)據(jù),小數(shù)點可選顯示 dula=0;
- delayms(2);
- /////////////////////////
- P0=0xff;
- wela=1;
- P0=0xfd;
- wela=0;
-
- P0=0;
- dula=1;
- P0=table[twoWela]|((0x02&dot)?0x00:0x80);
- dula=0;
- delayms(2);
- /////////////////////////
- P0=0xff;
- wela=1;
- P0=0xfb;
- wela=0;
- P0=0;
- dula=1;
- P0=table[threeWela]|((0x04&dot)?0x00:0x80);
- dula=0;
- delayms(2);
- /////////////////////////
- P0=0xff;
- wela=1;
- P0=0xf7;
- wela=0;
-
- P0=0;
- dula=1;
- P0=table[fourWela]|((0x08&dot)?0x00:0x80);
- dula=0;
- delayms(2);
- /////////////////////////
- P0=0xff;
- wela=1;
- P0=0xef;
- wela=0;
-
- P0=0;
- dula=1;
- P0=table[fiveWela]|((0x10&dot)?0x00:0x80);
- dula=0;
- delayms(2);
- /////////////////////////
- P0=0xff;
- wela=1;
- P0=0xdf;
- wela=0;
-
- P0=0;
- dula=1;
- P0=table[sixWela]|((0x20&dot)?0x00:0x80);
- dula=0;
- delayms(2);
- }
-
- #endif
復(fù)制代碼
|