代碼和原理圖都是錯的,給你一個容易理解的不規則端口驅動數碼管的代碼參考。
無標題.jpg (58.89 KB, 下載次數: 14)
下載附件
2023-2-4 13:59 上傳
- #include <reg51.H>
- #define uchar unsigned char
- #define uint unsigned int
- #define key_S 3 //宏定義短按(約15ms)
- #define key_L key_S*40 //宏定義長按(約600ms)
- #define key_I key_S*20 //宏定義長按連+間隔(約300ms)
- sbit K1=P2^6;//連接按鍵
- sbit dula0=P0^2;
- sbit dula1=P0^1;
- sbit dula2=P0^5;
- sbit dula3=P2^1;
- sbit dula4=P2^4;
- sbit dula5=P0^3;
- sbit dula6=P0^4;
- sbit dula7=P2^0;//連接冒號
- sbit wela0=P0^0;
- sbit wela1=P2^5;
- sbit wela2=P2^7;
- sbit wela3=P1^7;
- uchar code table[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};//共陽LED段碼表
- uchar data dis_buf[4];//顯示數據緩存
- char shi=12,fen=30,sec=0;//時,分,秒
- uchar Cnt5ms;//5ms時基
- uchar KeySec;//鍵值
- uint num=0;//計數
- bit flashing=0;//閃爍標志
- //定時器初始化程序
- void Timer0Init(void) //5毫秒@12.000MHz
- {
- TMOD |= 0x01; //設置定時器模式
- TL0 = 0x78; //設置定時初始值
- TH0 = 0xEC; //設置定時初始值
- TF0 = 0; //清除TF0標志
- TR0 = 1; //定時器0開始計時
- }
- void keyscan()
- {
- static unsigned int time=0;//計數變量
- if(!K1)//按鍵按下
- {
- time++;
- if(time>=key_L)//長按
- {
- switch(KeySec)
- {
- case 1: shi++;if(shi>23)shi=0; break;
- case 2: fen++;if(fen>59)fen=0; break;
- }
- time=key_I;//連+間隔
- num=1000;//自復位變量賦值(5秒)
- }
- }
- else //松手
- {
- if(time>key_S && time<key_I)//短按
- {
- KeySec++;
- if(KeySec>2)
- {
- KeySec=0;
- Cnt5ms=0;
- sec=0;
- }
- num=1000;//自復位變量賦值(5秒)
- }
- time=0;
- }
- }
- void dula(uchar i) //寫入8位段碼
- {
- dula0=i&0x01;i>>=1;
- dula1=i&0x01;i>>=1;
- dula2=i&0x01;i>>=1;
- dula3=i&0x01;i>>=1;
- dula4=i&0x01;i>>=1;
- dula5=i&0x01;i>>=1;
- dula6=i&0x01;i>>=1;
- dula7=i&0x01;
- }
- void wela(uchar i) //寫入4位位碼
- {
- wela0=i&0x01;i>>=1;
- wela1=i&0x01;i>>=1;
- wela2=i&0x01;i>>=1;
- wela3=i&0x01;
- }
- void display()//數碼管動態顯示函數
- {
- static uchar i=0;
- switch(i)//分解數據
- {
- case 0: dis_buf[0] = table[shi/10%10];break;
- case 1: dis_buf[1] = table[shi%10]; break;
- case 2: dis_buf[2] = table[fen/10%10];break;
- case 3: dis_buf[3] = table[fen%10]; break;
- }
- wela(0x00);//位碼消隱
- switch(KeySec)//送段碼
- {
- case 0: if(KeySec==0)dula(dis_buf[i]);break; //正常走時
- case 1: if(flashing && (i==0||i==1) && K1)dula(0xff);
- else dula(dis_buf[i]);break; //調整時閃爍
- case 2: if(flashing && (i==2||i==3) && K1)dula(0xff);
- else dula(dis_buf[i]);break; //調整分閃爍
- default: break;
- }
- if(!KeySec && flashing)dula7=1;//冒號閃爍
- else dula7=0;
- wela(0x01<<i);//送位碼
- i=++i%4; //循環計數
- }
- void Timing()
- {
- Cnt5ms++;
- if(KeySec!=0)
- {
- num--;
- if(num==0)//按鍵停止操作5秒自動恢復正常顯示
- {
- KeySec=0;
- Cnt5ms=0;
- sec=0;
- }
- if(Cnt5ms%50==0) //0.25s 快閃調時
- flashing=~flashing;
- }
- else if(Cnt5ms%100==0)//0.5s 慢閃顯秒
- flashing=~flashing;
- if(Cnt5ms==200)//1s
- {
- Cnt5ms=0;
- sec++;
- if(sec>=60)
- {
- sec=0;
- fen++;
- if(fen>=60)
- {
- fen=0;
- shi++;
- if(shi>23)
- shi=0;
- }
- }
- }
- }
- void main()//主函數
- {
- Timer0Init();//初始化定時器
- while(1)
- {
- if(TF0)//查詢定時器中斷請求位
- {
- TF0=0;
- TL0 = 0x78; //設置定時初始值
- TH0 = 0xEC; //設置定時初始值
- Timing(); //計時函數
- keyscan(); //按鍵掃描函數
- display(); //數碼管顯示函數
- }
- }
- }
復制代碼
|