單片機(jī)課程設(shè)計(jì)項(xiàng)目:智能秒表的設(shè)計(jì)與制作 一、項(xiàng)目任務(wù):智能秒表的設(shè)計(jì)與制作 用四位LED數(shù)碼管制作帶小數(shù)顯示的秒表,前兩位顯示整數(shù)部分(秒),后兩位顯示小數(shù)部分(百分之一秒)。 所設(shè)計(jì)的秒表最大計(jì)時(shí)時(shí)間為99秒99。 開始時(shí),數(shù)碼管顯示“00. 00”,表明從0開始計(jì)時(shí)。 本智能秒表有兩種時(shí)間計(jì)時(shí)模式。(注意:模式1與模式2用同一個(gè)程序?qū)崿F(xiàn),即當(dāng)程序下載至單片機(jī)芯片后,只需要按下相應(yīng)按鍵,該秒表可工作在任意一種模式下) (一)基本部分: 1、模式1:累積計(jì)時(shí)模式 (1)按按鍵1可實(shí)現(xiàn)秒表開始、停止、再開始、再停止計(jì)時(shí)(時(shí)間累計(jì)); (2)計(jì)時(shí)完畢,按按鍵2計(jì)時(shí)歸零。 2、模式2:間隔計(jì)時(shí)模式 (1) 按按鍵1開始計(jì)時(shí); (2) 按按鍵2一次暫停秒表并顯示當(dāng)前時(shí)間。間隔時(shí)間顯示2秒后秒表將持續(xù)計(jì)時(shí)。(例如在3秒鐘時(shí)秒表被暫停,2秒鐘后秒表從5秒開始繼續(xù)計(jì)時(shí)。顯示2秒是為了方便記錄當(dāng)前時(shí)間); (3) 在下一點(diǎn)終止時(shí)再按按鍵2記錄此時(shí)相關(guān)信息,如此重復(fù); (4) 當(dāng)計(jì)時(shí)停止時(shí)按按鍵1; (5)可通過按鍵3查看前面操作所記錄的時(shí)間,最多可查看10個(gè)記錄; (6) 計(jì)時(shí)完畢,按按鍵2鍵計(jì)時(shí)歸零。 (二)發(fā)揮部分 (1)用電腦時(shí)間校準(zhǔn)秒表的時(shí)間,保證秒表走時(shí)的準(zhǔn)確性(100秒的誤差小于0.1秒),思考如何修改程序? (2)利用內(nèi)部E2PROM存儲(chǔ)器(STC89C52自帶),使智能秒表具有掉電數(shù)據(jù)不丟失的功能,思考如何修改程序? (3)仿真無誤后,購(gòu)買元件制作該智能秒表,從商業(yè)價(jià)值考慮該智能秒表的美觀性和實(shí)用性。 二、硬件電路及仿真效果圖 三、STC90C52RC單片機(jī)引腳排列圖 四、四位共陰極數(shù)碼管引腳排列圖 五、元器件清單 七、調(diào)試方法和步驟 1、通電前先用萬(wàn)用表歐姆檔(1KΩ檔)測(cè)量電源兩端正反向電阻,正向電阻約80KΩ,反向電阻約6.5KΩ。如果電阻很小,則說明有短路性故障,不能通電,排除短路故障后才能通電,如果電阻為無窮大,則有開路性故障。 2、通電后,測(cè)量單片機(jī)40腳與20腳之間的電壓應(yīng)該有5V左右,如果電壓不正常,則說明單片機(jī)供電不正常,應(yīng)重點(diǎn)檢查單片機(jī)供電電路。 3、測(cè)量單片機(jī)晶振引腳18和19腳電壓,應(yīng)該在1.9~2.3V左右,兩個(gè)引腳電壓相差0.2V左右,如果這兩個(gè)引腳電壓不正常,說明晶振電路沒有起振,重點(diǎn)檢查晶振和補(bǔ)償電容是否焊接好。 4、測(cè)量單片機(jī)復(fù)位引腳9腳,正常工作時(shí)電壓為0V,按復(fù)位鍵時(shí)為5V,松開手后由5V逐漸降至0V。如果該腳電壓不正常,說明復(fù)位電路有故障,需要檢查該腳的電阻、電容的連接和焊接是否正確。 5、以上步驟的測(cè)量如果正常,則多數(shù)是單片機(jī)的軟件問題,可以通過編寫幾個(gè)小程序單獨(dú)調(diào)試I/O口、按鍵、數(shù)碼管和存儲(chǔ)器的功能,測(cè)試到底是軟件問題還是硬件問題。 六、C語(yǔ)言程序 - /********************************/
- /* 智能秒表(使用內(nèi)部EEPROM)*/
- /*--------------------------------------------*/
- /**(1)啟動(dòng)/停止功能 **/
- /**(2)復(fù)位/間隔功能 **/
- /**(3)兩種工作模式 **/
- /**(4)查看數(shù)據(jù)功能 **/
- /**(5)斷電記憶功能 **/
- /********************************/
- #include <reg52.h>
- #include <intrins.h>
- #define uint unsigned int
- #define uchar unsigned char
-
- #define RdCommand 0x01 //定義內(nèi)部EEPROM存儲(chǔ)器部分
- #define PrgCommand 0x02
- #define EraseCommand 0x03
- #define Error 1
- #define Ok 0
- #define WaitTime 0x01
- sfr ISP_DATA=0xe2;
- sfr ISP_ADDRH=0xe3;
- sfr ISP_ADDRL=0xe4;
- sfr ISP_CMD=0xe5;
- sfr ISP_TRIG=0xe6;
- sfr ISP_CONTR=0xe7;
-
- sbit key1=P2^0; //定義"啟動(dòng)/暫停"按鈕
- sbit key2=P2^1; //定義"復(fù)位"按鈕
- sbit key3=P2^2; //定義"模式"按鈕
- sbit key4=P2^3; //定義"查看"按鈕
- sbit key5=P1^5; //定義"清除"按鈕
-
- sbit wei1=P2^4; //定義位選
- sbit wei2=P2^5;
- sbit wei3=P2^6;
- sbit wei4=P2^7;
-
- bit flag_start,flag_mode,flag_2sec,flag_CLR;
- uchar temp,temp1,aa,aa1,shi,ge,shifen,baifen,num,i=0;
- uchar time_data1[11],time_data2[11];
- uchar code table[]={ //共陰極數(shù)碼管編碼
- 0x3f,0x06,0x5b,0x4f,
- 0x66,0x6d,0x7d,0x07,
- 0x7f,0x6f,0x77,0x7c,
- 0x39,0x5e,0x79,0x71,0x40};
-
- void display(uchar shi,uchar ge,uchar shifen,uchar baifen); //聲明顯示子函數(shù)
- void delay(uint z); //聲明延時(shí)子函數(shù)
- void init(); //聲明初始化函數(shù)
- void key(); //聲明鍵掃描函數(shù)
- void display_process(); //聲明顯示處理函數(shù)
- void delayus(); //聲明延時(shí)微秒函數(shù)
- void data_read(); //聲明內(nèi)部EEPROM數(shù)據(jù)讀出函數(shù)
- void clear(); //聲明清除EEPROM數(shù)據(jù)函數(shù)
-
- void ISP_IAP_enable(void); //聲明EEPROM操作函數(shù)
- void ISP_IAP_disable(void);
- void ISPgoon(void);
- uchar byte_read(uint byte_addr);
- void SectorErase(uint sector_addr);
- void byte_write(uint byte_addr, uchar original_data);
- void memory_read(); //聲明EEPROM讀函數(shù)
- void memory_write(); //聲明EEPROM寫函數(shù)
-
- void main() //主函數(shù)
- {
- init(); //調(diào)用初始化子程序
- while(1)
- {
- key(); //調(diào)用按鍵掃描函數(shù)
- if(num==0&&i!=0) //如果一開機(jī)就按查看鍵
- memory_read(); //調(diào)用EEPROM數(shù)據(jù)讀出函數(shù)
- if(flag_CLR==1) //如果按了清除鍵
- clear(); //調(diào)用清除EEPROM數(shù)據(jù)函數(shù)
- display_process(); //調(diào)用顯示處理函數(shù)
- display(shi,ge,shifen,baifen); //調(diào)用顯示函數(shù)
- }
- }
-
- void delay(uint z) //延時(shí)毫秒函數(shù)
- {
- uint x,y;
- for(x=z;x>0;x--)
- for(y=110;y>0;y--);
- }
-
- void display(uchar shi,uchar ge,uchar shifen,uchar baifen) //顯示程序
- {
- P0=table[shi]; //使用動(dòng)態(tài)掃描的方法實(shí)現(xiàn)數(shù)碼管顯示
- wei1=0;
- delay(1);
- wei1=1;
-
- if(flag_CLR==0) //正常顯示時(shí),第二位顯示小數(shù)點(diǎn)
- P0=table[ge]|0x80;
- else //按清除鍵時(shí),不顯示小數(shù)點(diǎn)
- P0=table[ge];
- wei2=0;
- delay(1);
- wei2=1;
-
- P0=table[shifen]; //使用動(dòng)態(tài)掃描的方法實(shí)現(xiàn)數(shù)碼管顯示
- wei3=0;
- delay(1);
- wei3=1;
-
- P0=table[baifen];
- wei4=0;
- delay(1);
- wei4=1;
- }
-
- void init() //初始化子程序
- {
- temp=0;
- TMOD=0x01; //使用定時(shí)器T0的方式1
- TH0=(65536-10000)/256;
- TL0=(65536-10000)%256; //定時(shí)10ms中斷一次
- EA=1; //中斷總允許
- ET0=1; //允許定時(shí)器T0中斷
- }
-
- void key() //按鍵掃描函數(shù)
- {
- uchar j;
- if(key1==0) //檢測(cè)"啟動(dòng)"按鈕是否按下
- {
- delay(5); //延時(shí)去抖動(dòng)
- if(key1==0) //再次檢測(cè)"啟動(dòng)"按鈕是否按下
- {
- while(!key1) //松手檢測(cè)(按下時(shí)數(shù)碼管不滅)
- {
- display_process(); //調(diào)用顯示處理函數(shù)
- display(shi,ge,shifen,baifen); //調(diào)用顯示函數(shù)
- }
- flag_start=~flag_start;
- if(flag_start==1)
- TR0=1; //啟動(dòng)定時(shí)器開始工作
- else
- TR0=0;
- }
- }
- if(key2==0) //檢測(cè)"間隔"按鈕是否按下
- {
- delay(5);
- if(key2==0)
- {
- while(!key2) //松手檢測(cè)
- {
- display_process(); //調(diào)用顯示處理函數(shù)
- display(shi,ge,shifen,baifen); //調(diào)用顯示函數(shù)
- }
- if(flag_mode==0||i!=0)
- {
- shi=0;
- ge=0;
- shifen=0;
- baifen=0;
- aa=0;
- temp=0;
- TR0=0;
- i=0;
- num=0;
- for(j=0;j<=10;j++)
- {
- time_data1[j]=0;
- time_data2[j]=0;
- }
- }
- else
- {
- num++;
- if(num==11)
- num=1;
- memory_write();
- }
- }
- }
- if(key3==0)
- {
- delay(5);
- if(key3==0)
- {
- while(!key3) //松手檢測(cè)
- {
- display_process(); //調(diào)用顯示處理函數(shù)
- display(shi,ge,shifen,baifen); //調(diào)用顯示函數(shù)
- }
- flag_mode=~flag_mode;
- }
- }
- if(key4==0)
- {
- delay(5);
- if(key4==0)
- {
- while(!key4) //松手檢測(cè)
- {
- display_process(); //調(diào)用顯示處理函數(shù)
- display(shi,ge,shifen,baifen); //調(diào)用顯示函數(shù)
- }
- TR0=0;
- i++;
- if(i==11)
- i=1;
- data_read();
- }
- }
- if(key5==0)
- {
- delay(5);
- if(key5==0)
- {
- while(!key5) //松手檢測(cè)
- {
- display_process(); //調(diào)用顯示處理函數(shù)
- display(shi,ge,shifen,baifen); //調(diào)用顯示函數(shù)
- }
- flag_CLR=~flag_CLR;
- }
- }
- }
-
- void display_process() //顯示處理函數(shù)
- {
- shifen=aa%100/10; //正常走秒的處理
- baifen=aa%10;
- shi=temp%100/10;
- ge=temp%10;
- if(flag_mode==1&&num!=0&&flag_2sec==0) //間隔2秒停頓的處理
- {
- shi=time_data2[num]/10;
- ge=time_data2[num]%10;
- shifen=time_data1[num]/10;
- baifen=time_data1[num]%10;
- if(temp-time_data2[num]==2)
- flag_2sec=~flag_2sec;
- }
- if(i!=0) //查看存儲(chǔ)數(shù)據(jù)的處理
- {
- shi=time_data2[i]/10;
- ge=time_data2[i]%10;
- shifen=time_data1[i]/10;
- baifen=time_data1[i]%10;
- }
- }
-
- void timer0() interrupt 1 //定時(shí)器T0中斷服務(wù)函數(shù)
- {
- TH0=(65536-10000)/256; //重新賦初值
- TL0=(65536-10000)%256;
- aa++; //中斷一次10ms變量aa的值加1
- if(aa==100) //中斷100次后,定時(shí)時(shí)間100*10ms=1000ms=1s,變量temp的值加1
- {
- aa=0;
- temp++;
- if(temp==100) //秒表到達(dá)100s后回零
- temp=0;
- }
- }
-
- /* EEPROM存儲(chǔ)器操作函數(shù) */
- /* ================================= */
- void ISP_IAP_enable(void)
- {
- EA = 0;
- ISP_CONTR = ISP_CONTR & 0x18;
- ISP_CONTR = ISP_CONTR | WaitTime;
- ISP_CONTR = ISP_CONTR | 0x80;
- }
- /* ================================= */
- void ISP_IAP_disable(void)
- {
- ISP_CONTR=ISP_CONTR&0x7f;
- ISP_TRIG=0x00;
- EA=1;
- }
- /* ==================================== */
- void ISPgoon(void)
- {
- ISP_IAP_enable();
- ISP_TRIG = 0x46;
- ISP_TRIG = 0xb9;
- _nop_();
- }
- /* ============================================ */
- uchar byte_read(uint byte_addr)
- {
- ISP_ADDRH = (uchar)(byte_addr >> 8);
- ISP_ADDRL = (uchar)(byte_addr & 0x00ff);
- ISP_CMD = ISP_CMD & 0xf8;
- ISP_CMD = ISP_CMD | RdCommand;
- ISPgoon();
- ISP_IAP_disable();
- return (ISP_DATA);
- }
- /* ========================================== */
- void SectorErase(uint sector_addr)
- {
- uint iSectorAddr;
- iSectorAddr = (sector_addr & 0xfe00);
- ISP_ADDRH = (uchar)(iSectorAddr >> 8);
- ISP_ADDRL = 0x00;
- ISP_CMD = ISP_CMD & 0xf8;
- ISP_CMD = ISP_CMD | EraseCommand;
- ISPgoon();
- ISP_IAP_disable();
- }
- /* ============================================ */
- void byte_write(uint byte_addr, uchar original_data)
- {
- ISP_ADDRH = (uchar)(byte_addr >> 8);
- ISP_ADDRL = (uchar)(byte_addr & 0x00ff);
- ISP_CMD = ISP_CMD & 0xf8;
- ISP_CMD = ISP_CMD | PrgCommand;
- ISP_DATA = original_data;
- ISPgoon();
- ISP_IAP_disable();
- }
-
- void data_read() //讀數(shù)組數(shù)據(jù)函數(shù)
- {
- aa=time_data1[i];
- temp=time_data2[i];
- }
-
- void memory_write() //寫EEPROM數(shù)據(jù)函數(shù)
- {
- aa1=aa;
- temp1=temp;
- time_data1[num]=aa1;
- time_data2[num]=temp1;
- if(num==1)
- SectorErase(0x2000); //擦除扇區(qū)
- byte_write(0x2000+num,aa1); //重新寫入數(shù)據(jù)
- byte_write(0x2000+num+10,temp1); //重新寫入數(shù)據(jù)
- flag_2sec=0;
- …………限于本文篇幅 余下代碼請(qǐng)從51黑下載附件…………
復(fù)制代碼
完整論文下載(word格式 可編輯)還帶仿真和源碼:
|