標(biāo)題: 電子時(shí)鐘_秒表_按鍵計(jì)數(shù)的單片機(jī)設(shè)計(jì) C語言程序代碼及仿真圖 [打印本頁]
作者: 1103687038 時(shí)間: 2017-5-8 17:41
標(biāo)題: 電子時(shí)鐘_秒表_按鍵計(jì)數(shù)的單片機(jī)設(shè)計(jì) C語言程序代碼及仿真圖
一、 電子時(shí)鐘、秒表和計(jì)數(shù)器的設(shè)計(jì)
1、 實(shí)現(xiàn)的功能:
1)有key0,key1兩個(gè)功能按鍵,復(fù)位后,數(shù)碼管會(huì)默認(rèn)顯示時(shí)鐘模式 HH.MM 。
(HH表示小時(shí),MM表示分鐘),
key0短按一次就進(jìn)入到了秒表模式,數(shù)碼管顯示格式S.SS.S,(分別表示百秒,秒,毫秒)
key0再短按一次就進(jìn)入到了計(jì)數(shù)器模式,數(shù)碼管顯示格式CCCC(分別為千位百位十位個(gè)位)。
key0再短按一次,又進(jìn)入到了時(shí)鐘顯示模式,就這樣由key0控制模式的轉(zhuǎn)換。
2)有RST復(fù)位鍵,本身電路設(shè)計(jì)有上電自動(dòng)復(fù)位功能,按下RST后,電路復(fù)位。
3)有ckey0,ckey1 兩個(gè)計(jì)數(shù)按鍵,按下ckey0,計(jì)數(shù)加一,按下ckey1,計(jì)數(shù)減一。
4) 電子時(shí)鐘和秒表時(shí)間計(jì)時(shí)方法是采用89S52內(nèi)部計(jì)時(shí)器0的一種工作方式(詳見后面的代碼分析),通過計(jì)時(shí)器0中斷來控制時(shí)間的運(yùn)行。
5)計(jì)數(shù)器是采用外部中斷0和外部中斷1這兩個(gè)外部中斷實(shí)現(xiàn)加1和減1的操作。
(1) 電子時(shí)鐘模式:(以下“長按”表示按下按鍵的時(shí)間大于1秒,“短按”表示按下的時(shí)間小于0.7 秒)
1)長按key1一次,會(huì)進(jìn)入到調(diào)整分鐘的模式,短按key1一次,分鐘會(huì)加一。
第二次長按key1,會(huì)進(jìn)入到調(diào)整小時(shí)的模式,短按key1一次,小時(shí)加一。
第三次長按key1,重新回到時(shí)鐘顯示模式,這時(shí)再短按key1,時(shí)間不會(huì)變化
2)長按key0一次,會(huì)進(jìn)入到顯示秒的模式
(2) 秒表模式:
1) 由key0控制進(jìn)入秒表模式后,短按key1一次,秒表計(jì)時(shí)開始,再短按key1一次計(jì)時(shí)結(jié)束
2) 長按key1一次,秒表清零
(3) 計(jì)數(shù)器模式
1) 按ckey0一下,計(jì)數(shù)加一,數(shù)碼管相應(yīng)的顯示的數(shù)值加一,
按ckey1一下,計(jì)數(shù)減一,數(shù)碼管相應(yīng)的顯示的數(shù)值減一,
由于數(shù)碼管的位數(shù)限制,最大只能顯示到9999,此時(shí)按下ckey0無反應(yīng);考慮到
實(shí)際計(jì)數(shù)功能,沒有設(shè)置負(fù)數(shù),所以最小顯示0000,這時(shí)按下ckey1 ,無反應(yīng)。
2) 長按key1一次計(jì)數(shù)器清零。
2、 電路原理圖
0.png (34.04 KB, 下載次數(shù): 120)
下載附件
2017-5-8 20:14 上傳
(1) 使用片內(nèi)振蕩器
0.png (61.39 KB, 下載次數(shù): 101)
下載附件
2017-5-8 20:14 上傳
單片機(jī)源程序:
- #include <reg51.h>
- sbit key0=P1^0;
- sbit key1=P1^1; //定義key0,key1接口
- unsigned char flag,con,mcount; //flag為計(jì)數(shù)到一秒時(shí)給時(shí)鐘發(fā)的信號(hào)
- unsigned char count = 0;
- unsigned char seccount =0; //作為時(shí)鐘的秒的計(jì)量單位
- unsigned char hour = 0; //時(shí)鐘的時(shí)
- unsigned char min = 0; //時(shí)鐘的分
- unsigned char sec = 0; //時(shí)鐘的秒
- unsigned char keypress0,keypress1,mode,ms,s,ss,start;
- unsigned char
- Displaynum[]={0x14,0xd7,0x4c,0x45,0x87,0x25,0x24,0x57,0x04,0x05, 0x10,0xd3,0x48,0x41,0x83,0x21,0x20,0x53,0x00,0x01,0xff,0xfb};
- //數(shù)碼管十六進(jìn)制譯碼表
- unsigned char controlnum[]={0x08,0x04,0x02,0x01}; //控制四個(gè)數(shù)碼管顯示
- unsigned char DisplayBuff[]={0x00, 0x00, 0x00, 0x00}; //每個(gè)數(shù)碼管的值
- void display_state(); //數(shù)碼管顯示子程序
- void keyscan(); //鍵盤掃描子程序
- void timer(); //秒表子程序
- unsigned char count1,flag1,t_adjust=0,tm_adjust=0;
- unsigned char bKey0Pressed = 0, bKey1Pressed = 0;
- unsigned char ucStatus = 0;
- void main()
- {
- TMOD = 0x01; //定時(shí)器0工作在模式1,GATE=0,C/t=0,16位模
- TH0= (2^16-5000)/256;//定時(shí)器0 預(yù)存值,
- TL0= (2^16-5000)%256;
- TR0= 1; //定時(shí)器0 啟動(dòng)
- ET0= 1; //定時(shí)器中斷0 允許
- EA= 1; //開中斷
- IT0=1; //外部中斷0下降沿觸發(fā)
- IT1=1; //外部中斷1 下降沿觸發(fā)
- EX0=1; //外部中斷0允許
- EX1=1; //外部中斷1允許
- PX1=1; //外部中斷1 為高優(yōu)先級(jí)中斷
- while(1) //死循環(huán),
- {
- if(flag == 1) //時(shí)鐘顯示
- {
- flag = 0;
- sec++;
- if(sec ==60)
- {sec = 0;
- min++;
- if(min ==60)
- {min = 0;
- hour ++;
- if(hour == 24)
- {
- hour = 0;
- }
- }
- }
- }
- display_state();
- keyscan();
- timer();
- }
- }
- //////////////////////////////////ISR中斷服務(wù)程序,每5ms產(chǎn)生一個(gè)定時(shí)器0 中斷
- void Display() interrupt 1
- {
- TH0 = (2^16-5000)/256;
- TL0 = (2^16-5000)%256;
-
- seccount ++;
- mcount ++;
- keypress0++;
- keypress1++;
- P2=0x00; //P2口先清零
- P0 = Displaynum[DisplayBuff[count]]; //P0口輸出
- P2 = controlnum[count]; //P2口輸出
- count++;
- if(count==4)
- count=0;
- if(seccount == 200) //200*5ms=1s
- { seccount =0;
- flag =1; //每過1秒給時(shí)鐘信號(hào)加一秒
- }
-
- }
- ///////////////////////////////////////////
- void display_state()
- {
- if(mode == 0) //時(shí)鐘模式,顯示時(shí)間
- {
- DisplayBuff[0] = hour/10;
- DisplayBuff[1] = (hour%10)+10; //"+10"是為了顯示加點(diǎn)的數(shù)字
- DisplayBuff[2] = min/10;
- DisplayBuff[3] = min%10;
- }
- if(mode == 1) //秒表模式,顯示秒表
- {
- DisplayBuff[0] = ss +10; //"+10"是為了顯示加點(diǎn)的數(shù)字
- DisplayBuff[1] = s/10;
- DisplayBuff[2] = (s%10)+10;
- DisplayBuff[3] = ms;
- }
- if(mode == 2) // 計(jì)數(shù)器模式,顯示計(jì)數(shù)
- {
- DisplayBuff[0] = count1/1000; //千位
- DisplayBuff[1] = (count1-(count1/1000)*1000)/100; //百位
- DisplayBuff[2] = (count1-(count1/100)*100)/10; //十位
- DisplayBuff[3] = count1%10; //個(gè)位
- }
- if(mode==3) //顯示時(shí)鐘的秒,
- {
- DisplayBuff[0] = 20; //第一位不顯示
- DisplayBuff[1] = 21; //第二位顯示一個(gè)點(diǎn)
- DisplayBuff[2] = sec/10;//顯示秒的十位
- DisplayBuff[3] = sec%10;//顯示秒的個(gè)位
- }
- }
-
- //**************//
- //鍵盤掃描子程序//
- //**************//
- void keyscan()
- {
- if(!key0 && bKey0Pressed == 0) //檢測到key0按下
- {
- keypress0 = 0;
- bKey0Pressed = 1; //防止重入此判斷
- while(!key0); //如果沒放開,就等下去
- }
- if(key0 && bKey0Pressed == 1) //檢測到key0放開
- {
- bKey0Pressed = 0; //防止重入此判斷
- if (keypress0<120) //如果是短按
- {
- if(ucStatus == 0x02)
- {
- ucStatus = 0x00;
- mode = 0; //時(shí)鐘模式
- t_adjust=0;
- }
- else if(ucStatus == 0x00)
- {
- ucStatus = 0x01;
- mode = 1; //秒表模式
- }
- else if(ucStatus == 0x01)
- {
- ucStatus = 0x02;
- mode = 2; //計(jì)數(shù)模式
- }
- }
- else if(keypress0>200) //如果是長按
- mode=3; //顯示時(shí)鐘的秒的模式
- }
- ////////////////////////////////
- if(mode == 0) //進(jìn)入時(shí)鐘模式后
- {
- if(!key1 && (bKey1Pressed == 0))
- { keypress1 = 0;
- bKey1Pressed = 1;
- while(!key1);
- }
- if(key1 && (bKey1Pressed == 1))
- {
- bKey1Pressed = 0;
- if(keypress1 >= 200) //如果是長按
- {
- t_adjust++;
- if(t_adjust==3)
- t_adjust=0;
- }
- else if(keypress1 < 120)
- switch (t_adjust)
- {
- case 1:{ //調(diào)整分
- min++;
- sec = 0;
- if(min == 60)
- min = 0;
- }
- break;
- case 2: { //調(diào)整時(shí)
- hour ++ ;
- sec = 0;
- if(hour == 24)
- hour = 0;
- }
- break;
- default:break;
- }
- }
- }
-
- else if(mode == 1) //進(jìn)入秒表模式
- {
- if(!key1 && bKey1Pressed == 0)
- {
- keypress1 = 0;
- bKey1Pressed = 1;
- while(!key1);
- }
- if(key1 && bKey1Pressed == 1)
- {
- bKey1Pressed = 0;
- if(keypress1 < 120) //短按
- {
- if(flag1==0) { start=2;flag1=1;} //start=2代表秒表開始計(jì)時(shí)
- else {start=0;flag1=0;} //start=0,秒表停止計(jì)時(shí)
- }
- else if(keypress1>200) //長按
- start=1; //秒表清零
- }
- }
- }
- void timer() //秒表子程序
- {
- if(mode==1) //進(jìn)入秒表模式才執(zhí)行
- {
- if(start==1) //清零
- {
- ms = 0;
- s = 0;
- ss = 0;
- mcount=0;
- }
- if(start==2) //秒表開始計(jì)時(shí)
- {
- if(mcount==20) //20*5ms=0.1s
- {
- mcount=0;
- ms++;
- if(ms == 10) // 10*0.1s=1s,s++
- {ms = 0;
- s ++;
- if(s == 100) //100s
- {s = 0;
- ss ++;
- if(ss == 10)
- {ss = 0;
- s = 0;
- ms = 0;
- }
- }
- }
- }
- }
- if (start==0);//秒表停止
- }
- }
- //////////////////////
- void it0(void) interrupt 0 using 1 //外部中斷0 服務(wù)程序
- {
- if(mode==2) //只有在計(jì)數(shù)模式才執(zhí)行
- {
- count1++; //每響應(yīng)一次,計(jì)數(shù)加一
- if(count1==10000) //超出四位時(shí),不能再加
- count1 =9999;
- }
- }
- void it2(void) interrupt 2 using 2 //外部中斷0 服務(wù)程序
- {
- if(mode==2) //只有在計(jì)數(shù)模式才執(zhí)行
- {
- if(count1!=0)
- …………限于本文篇幅 余下代碼請(qǐng)從51黑下載附件…………
復(fù)制代碼
全部資料打包下載:
miaob.rar
(63.09 KB, 下載次數(shù): 269)
2017-5-8 17:36 上傳
點(diǎn)擊文件名下載附件
89C51單片機(jī)最小系統(tǒng)設(shè)計(jì)(電子時(shí)鐘_秒表_按鍵計(jì)數(shù)的單片機(jī)設(shè)計(jì))_C語言程序代碼及仿真圖
下載積分: 黑幣 -5
作者: 51busy 時(shí)間: 2017-10-30 07:31
可以 先先
作者: guboy 時(shí)間: 2018-5-14 09:05
不錯(cuò)的設(shè)計(jì)很好啊
作者: 12345abcde678 時(shí)間: 2018-6-19 20:44
你能不能發(fā)我一份
作者: wl020807 時(shí)間: 2018-9-12 13:46
樓主,計(jì)數(shù)在259就歸0了是怎么回事?
作者: wl020807 時(shí)間: 2018-9-12 16:22
你好,你發(fā)的時(shí)鐘和計(jì)數(shù)器程序?yàn)槭裁粗荒苡?jì)數(shù)到255就歸零了
作者: L仔 時(shí)間: 2019-12-5 21:54
沒現(xiàn)象啊
作者: 單純 時(shí)間: 2019-12-12 09:43
我也想要
作者: snaiodiwa 時(shí)間: 2019-12-13 14:57
很棒的設(shè)計(jì)
作者: L走走停停L 時(shí)間: 2019-12-13 16:28
謝謝!好評(píng)!
作者: lanv 時(shí)間: 2019-12-13 16:39
挺全面的,學(xué)習(xí)用
作者: xcz882004 時(shí)間: 2022-10-11 12:36
資料很全面,現(xiàn)在準(zhǔn)備學(xué)C,需要一個(gè)參考案例
作者: 2290145679 時(shí)間: 2022-10-11 16:30
看起來感覺不錯(cuò)哦
| 歡迎光臨 (http://www.denmoz.com/bbs/) |
Powered by Discuz! X3.1 |