目錄
1、項(xiàng)目需求分析 2
11、項(xiàng)目目標(biāo)意義 2
12、功能需求分析 2
13、系統(tǒng)開發(fā)環(huán)境、工具需求分析與選擇 2
14、非功能性需求分析 2
2、項(xiàng)目硬件系統(tǒng)結(jié)構(gòu) 2
21、 系統(tǒng)方案原理圖 2
22、AT89C51原理介紹 2
23 、光電開關(guān)模塊原理 3
24、報(bào)警模塊原理 4
25、按鍵模塊原理 4
26、數(shù)碼管顯示模塊原理 5
27、存儲(chǔ)模塊原理 5
28、傳送帶電機(jī)驅(qū)動(dòng)模塊原理 6
3、系統(tǒng)軟件體系架構(gòu) 6
31 項(xiàng)目軟件系統(tǒng)總架構(gòu)圖 6
32 顯示子模塊流程圖 9
33 重要的數(shù)據(jù)結(jié)構(gòu)、參數(shù)和函數(shù)分析 12
4、項(xiàng)目運(yùn)行效果展示 13
5、總結(jié)與心得體會(huì) 14
6、附錄 15
1、項(xiàng)目需求分析 1.1、項(xiàng)目目標(biāo)意義 工業(yè)生產(chǎn)中,很多領(lǐng)域需要自動(dòng)統(tǒng)計(jì)產(chǎn)品的數(shù)量,基于光電開關(guān)和AT89C51單片機(jī)開發(fā)的傳送帶計(jì)數(shù)器完美解決了傳送帶上面運(yùn)送的產(chǎn)品需要人工計(jì)數(shù)的煩惱,通過該計(jì)數(shù)器的應(yīng)用,企業(yè)無論是計(jì)數(shù)效率和準(zhǔn)確度方面都有了質(zhì)的提升而普及自動(dòng)計(jì)數(shù)器也具有非常實(shí)際的意義,受到廣大企業(yè)的青睞。 1.2、功能需求分析 通過光電開關(guān)檢測(cè)傳送帶傳送過來的產(chǎn)品,每過一個(gè)產(chǎn)品,單片機(jī)計(jì)數(shù)加1,由此實(shí)現(xiàn)自動(dòng)計(jì)數(shù)功能;設(shè)置蜂鳴器在出現(xiàn)異常時(shí)可實(shí)現(xiàn)報(bào)警功能;添加數(shù)碼管實(shí)現(xiàn)計(jì)數(shù)的顯示功能;通過EEPROM存儲(chǔ)器,實(shí)現(xiàn)計(jì)數(shù)的存儲(chǔ)功能;添加按鍵實(shí)現(xiàn)相關(guān)設(shè)置功能。 1.3、系統(tǒng)開發(fā)環(huán)境、工具需求分析與選擇 本系統(tǒng)是基于Keil C51的單片機(jī)開發(fā)環(huán)境進(jìn)行的開發(fā),Keil C51是美國(guó)Keil Software公司出品的51系列兼容單片機(jī)C語(yǔ)言軟件開發(fā)系統(tǒng),與匯編相比,C語(yǔ)言在功能上、結(jié)構(gòu)性、可讀性、可維護(hù)性上有明顯的優(yōu)勢(shì),因而易學(xué)易用,基于此我們選擇C語(yǔ)言進(jìn)行編程。 1.4、非功能性需求分析 在電子技術(shù)飛速發(fā)展的今天,電子產(chǎn)品的智能化和自動(dòng)化的發(fā)展已越來越成熟,每個(gè)行業(yè)都在尋求自動(dòng)化來代替人工,基于光電開關(guān)和AT89C51單片機(jī)開發(fā)的傳送帶計(jì)數(shù)器使用簡(jiǎn)單,操作方便,有效節(jié)省了人工成本,單位時(shí)間內(nèi)提高了工作效率,給企業(yè)帶來更大的收益。 2、項(xiàng)目硬件系統(tǒng)結(jié)構(gòu) 2.1、系統(tǒng)方案原理圖
如圖是整個(gè)系統(tǒng)實(shí)現(xiàn)的框圖,從圖中我們可以看到整個(gè)系統(tǒng)包括單片機(jī)模塊、按鍵輸入模塊、計(jì)數(shù)模塊、存儲(chǔ)模塊、數(shù)碼管顯示模塊、傳送帶電機(jī)模塊、蜂鳴器和指示燈報(bào)警模塊。整個(gè)系統(tǒng)通過這幾個(gè)模塊協(xié)同工作實(shí)現(xiàn)傳送帶計(jì)數(shù)器的功能。
2.2、AT89C51原理介紹 AT89C51是一種帶4K字節(jié)閃爍可編程可擦除只讀存儲(chǔ)器(FPEROM—Falsh Programmable and Erasable Read Only Memory)的低電壓,高性能CMOS8位微處理器,俗稱單片機(jī)。該器件采用ATMEL高密度非易失存儲(chǔ)器制造技術(shù)制造,與工業(yè)標(biāo)準(zhǔn)的MCS-51指令集和輸出管腳相兼容。由于將多功能8位CPU和閃爍存儲(chǔ)器組合在單個(gè)芯片中,ATMEL的AT89C51是一種高效微控制器,為很多嵌入式控制系統(tǒng)提供了一種靈活性高且價(jià)廉的方案。 本系統(tǒng)應(yīng)用到的AT89C51的I/O輸入輸出功能:在32個(gè)I/O口中選擇,實(shí)現(xiàn)按鍵、顯示、驅(qū)動(dòng)等功能,I/O口分為P0、P1和P3三大類;P0可以作普通IO口,也可以在讀寫外部存儲(chǔ)器作低8位的地址總線和8位的數(shù)據(jù)總線;P1口只作為一般IO口;P2作為一般IO口還在在讀寫外部存儲(chǔ)器作高8位的地址總線;P3口除作為一般IO口還為第二輸入/輸出功能(P3.0 串行數(shù)據(jù)接入端;P3.1 串行數(shù)據(jù)發(fā)送端;P3.2外中斷0輸入端 ;P3.3 外中斷1輸入端;P3.4 定時(shí)或計(jì)數(shù)器TO 的外部輸入端;P3.5 定時(shí)或計(jì)數(shù)器T1的外部輸入端;P3.6 外部數(shù)據(jù)存儲(chǔ)器寫選通信號(hào);P3.7 外部數(shù)據(jù)存儲(chǔ)器讀選通信號(hào);) 本系統(tǒng)應(yīng)用到的定時(shí)器功能:實(shí)現(xiàn)定時(shí)中斷功能,AT89C51有T0和T1兩個(gè)定時(shí)/計(jì)數(shù)器,分別有定時(shí)和計(jì)數(shù)兩種模式、4種(T1為3種)工作方式,方式0-方式3,方式0下、計(jì)數(shù)工作方式時(shí),計(jì)數(shù)范圍是1-8192,定時(shí)工作方式時(shí),定時(shí)時(shí)間的計(jì)算公式是:(2^13-計(jì)數(shù)初值)*機(jī)器周期;方式1下,與方式0的差別僅在于計(jì)數(shù)位數(shù)不同,方式1為16位計(jì)數(shù),作為定時(shí)方式使用時(shí),定時(shí)時(shí)間的計(jì)算公式是:(2^16-計(jì)數(shù)初值)*機(jī)器周期,計(jì)數(shù)范圍是1-65536;方式2下,計(jì)數(shù)滿后自動(dòng)裝入計(jì)數(shù)初值,精確定時(shí)并簡(jiǎn)化定時(shí)初值;方式3只適用于T0,T1不能工作在方式3。 2.3 、光電開關(guān)模塊原理 光電開關(guān)即光電傳感器,是光電接近開關(guān)的簡(jiǎn)稱,它主要是利用被檢測(cè)物對(duì)光束的遮擋或反射,由同步回路選通電路,從而檢測(cè)物體有無的。光電開關(guān)是傳感器的一種,它把發(fā)射端和接收端之間光的強(qiáng)弱變化轉(zhuǎn)化為電流的變化以達(dá)到探測(cè)的目的。例當(dāng)光電開關(guān)被產(chǎn)品遮擋時(shí),輸出引腳變低電平,單片機(jī)檢測(cè)到低電平計(jì)數(shù)一次代表一個(gè)產(chǎn)品,當(dāng)光電開關(guān)無遮擋是,輸出引腳變高電平,單片機(jī)檢測(cè)到高電平不予計(jì)數(shù),代表無產(chǎn)品通過。我們這里使用一個(gè)開關(guān)模擬他的信號(hào),這個(gè)開關(guān)接入單片機(jī)的P3.4口,當(dāng)按鍵按下一次表示檢測(cè)到一個(gè)商品。 2.4、報(bào)警模塊原理 本系統(tǒng)采用蜂鳴器和LED指示燈做報(bào)警元件,蜂鳴器一端接電源,另一端通過三級(jí)管接到單片機(jī)I/O口進(jìn)行控制,當(dāng)需要報(bào)警時(shí),單片機(jī)控制蜂鳴器的I/O口置高,三極管導(dǎo)通,將蜂鳴器另一端拉低,蜂鳴器導(dǎo)通并鳴響,實(shí)現(xiàn)報(bào)警。另外LED串聯(lián)一個(gè)限流電阻,一端連接電源,一端連接單片機(jī)的P1.1引腳,單片機(jī)控制LED亮滅進(jìn)行指示作用。 2.5、按鍵模塊原理 本系統(tǒng)采用獨(dú)立按鍵和矩陣按鍵結(jié)合的方式,獨(dú)立按鍵直接用I/O口線構(gòu)成的單個(gè)按鍵電路,其特點(diǎn)式每個(gè)按鍵單獨(dú)占用一根I/O口線,每個(gè)按鍵的工作不會(huì)影響其他I/O口線的狀態(tài)。獨(dú)立式按鍵電路配置靈活,軟件結(jié)構(gòu)簡(jiǎn)單,但每個(gè)按鍵必須占用一個(gè)I/O口線,因此,在按鍵較多時(shí),I/O口線浪費(fèi)較大,不宜采用。獨(dú)立按鍵的軟件常采用查詢式結(jié)構(gòu)。先逐位查詢沒跟I/O口線的輸入狀態(tài),如某一根I/O口線輸入為低電平,則可確認(rèn)該I/O口線所對(duì)應(yīng)的按鍵已按下,然后,再轉(zhuǎn)向該鍵的功能處理程序。矩陣按鍵是逐行掃描,然后判斷有沒有按鍵按下,有按下的時(shí)候再判斷列,最終確定按鍵的數(shù)值。
2.6、數(shù)碼管顯示模塊原理 數(shù)碼管也稱LED數(shù)碼管,晶美、光電、不同行業(yè)人士對(duì)數(shù)碼管的稱呼不一樣,其實(shí)都是同樣的產(chǎn)品。數(shù)碼管按段數(shù)可分為七段數(shù)碼管和八段數(shù)碼管,八段數(shù)碼管比七段數(shù)碼管多一個(gè)發(fā)光二極管單元(多一個(gè)小數(shù)點(diǎn)顯示);按能顯示多少個(gè)“8”可分為1位、2位、3位、4位、5位、6位、7位等數(shù)碼管;按發(fā)光二極管單元連接方式可分為共陽(yáng)極數(shù)碼管和共陰極數(shù)碼管。共陽(yáng)數(shù)碼管是指將所有發(fā)光二極管的陽(yáng)極接到一起形成公共陽(yáng)極(COM)的數(shù)碼管,共陽(yáng)數(shù)碼管在應(yīng)用時(shí)應(yīng)將公共極COM接到+5V,當(dāng)某一字段發(fā)光二極管的陰極為低電平時(shí),相應(yīng)字段就點(diǎn)亮,當(dāng)某一字段的陰極為高電平時(shí),相應(yīng)字段就不亮。共陰數(shù)碼管是指將所有發(fā)光二極管的陰極接到一起形成公共陰極(COM)的數(shù)碼管,共陰數(shù)碼管在應(yīng)用時(shí)應(yīng)將公共極COM接到地線GND上,當(dāng)某一字段發(fā)光二極管的陽(yáng)極為高電平時(shí),相應(yīng)字段就點(diǎn)亮,當(dāng)某一字段的陽(yáng)極為低電平時(shí),相應(yīng)字段就不亮,本系統(tǒng)采用共陽(yáng)數(shù)碼管。 2.7、存儲(chǔ)模塊原理 本系統(tǒng)采用AT24C02存儲(chǔ)芯片,AT24C02芯片是以IIC接口的EEPROM器件。所謂EEPROM即電可擦除可編程只讀存儲(chǔ)器,是ROM的一種。它是只讀存儲(chǔ)器,即掉電可繼續(xù)存儲(chǔ)數(shù)據(jù),而同時(shí)又可以在高于普通電壓的作用下擦除和重寫,這就方便了單片機(jī)對(duì)其的開發(fā),現(xiàn)在電腦上的ROM很多都是用的EEPROM。 2.8、傳送帶電機(jī)驅(qū)動(dòng)模塊原理 本系統(tǒng)采用單片機(jī)通過三極管控制繼電器驅(qū)動(dòng)直流電機(jī),根據(jù)傳送帶直流電機(jī)的功率等參數(shù)選用相應(yīng)的繼電器,當(dāng)單片機(jī)控制電機(jī)的I/O口為低時(shí),三極管導(dǎo)通,繼電器吸合,電機(jī)電源端導(dǎo)通,電機(jī)運(yùn)轉(zhuǎn)傳送,當(dāng)單片機(jī)控制電機(jī)的I/O口為高時(shí),三極管截止,繼電器斷開,電機(jī)電源端斷開,電機(jī)停止運(yùn)轉(zhuǎn)。 3、系統(tǒng)軟件體系架構(gòu) 3.1 項(xiàng)目軟件系統(tǒng)總架構(gòu)圖 整個(gè)系統(tǒng)的實(shí)現(xiàn)流程圖如圖,從圖中我們可以看到程序首先對(duì)外設(shè)進(jìn)行了初始化,然后讀取存儲(chǔ)在芯片中的設(shè)定數(shù)值,接著初始化定時(shí)器之后就進(jìn)入了主循環(huán)。主循環(huán)首先讀取了按鍵,然后根據(jù)按鍵進(jìn)行設(shè)定和啟停等操作,同時(shí)判斷計(jì)數(shù)數(shù)值是否大于等于設(shè)置數(shù)值,如果到了就報(bào)警提示。最后根據(jù)不同的模式顯示不同的數(shù)值。
/******************************************************************** * 名稱 : Main() * 功能 : 主函數(shù) * 輸入 : 無 * 輸出 : 無 ***********************************************************************/ void Main(void) { uchar press_sure_num=0; uchar Key_num=0; uchar temp=0;
moto=0; //關(guān)閉電機(jī) BUZZ=1; //關(guān)閉報(bào)警 Read_set_num(); //讀取設(shè)定的數(shù)值 Time0_init(); // 定時(shí)器初始化
while(1) { Key_num=KEY_Scan(); //掃描按鍵
if(set_mode==0) //非設(shè)定模式 { if(Key_num==12) //啟動(dòng) { counter_buf[0]=0;counter_buf[1]=0;counter_buf[2]=0;counter_buf[3]=0; //清除顯示 counter_num=0; //計(jì)數(shù)清零 moto=1; //打開電機(jī) LED=1; BUZZ=1; //關(guān)閉報(bào)警 EA=1; //打開計(jì)數(shù) } else if(Key_num==13)//停止 { moto=0; //關(guān)閉電機(jī) LED=1; BUZZ=1;//關(guān)閉報(bào)警 EA=0; //關(guān)閉計(jì)數(shù) } if(Key_num==14) //設(shè)置 { set_mode=1; //設(shè)置模式置一 set_position=1; moto=0; //關(guān)閉電機(jī) EA=0; //關(guān)閉計(jì)數(shù)
} } else//設(shè)定模式 { if(Key_num==11)//按下了確定鍵 { set_mode=0;//退出設(shè)定 set_position=0; counter_buf[0]=0;counter_buf[1]=0;counter_buf[2]=0;counter_buf[3]=0; //set_num=(dis_data_buf[0]*1000)+(dis_data_buf[1]*100)+(dis_data_buf[2]*10)+dis_data_buf[3]; //計(jì)算出計(jì)數(shù)的數(shù)值 Write_set_num(); } else if(Key_num<10)//顯示的設(shè)定值 {
dis_data_buf[4-set_position]=Key_num; set_position++; if(set_position>4)set_position=4; } else if(Key_num==10)//清除設(shè)定 { set_position=1; dis_data_buf[0]=0; dis_data_buf[1]=0; dis_data_buf[2]=0; dis_data_buf[3]=0; } }
set_num=(dis_data_buf[0]*1000)+(dis_data_buf[1]*100)+(dis_data_buf[2]*10)+dis_data_buf[3]; //計(jì)算出計(jì)數(shù)的數(shù)值
if(counter_num>=set_num) //如果計(jì)數(shù)數(shù)值大于等于設(shè)定的數(shù)值就停止 { moto=0; //關(guān)閉電機(jī) BUZZ=0; //打開報(bào)警 LED=0;//
} if(set_mode==0) //正常模式下顯示計(jì)數(shù)值 { diplay(counter_buf); } else //設(shè)定模式下顯示設(shè)定值 { diplay(dis_data_buf); }
} }
3.2 顯示子模塊流程圖 這里我們介紹的是顯示子函數(shù),子函數(shù)首先是關(guān)閉數(shù)碼管的顯示,這一步稱為消引。然后把顯示的數(shù)據(jù)送給其中一個(gè)數(shù)碼管,最后點(diǎn)亮這個(gè)數(shù)碼管,等到下一次輪尋就再調(diào)用下一個(gè)數(shù)碼管。
//數(shù)碼管的顯示函數(shù) void diplay(uchar *dis_p) { static uchar temp_num=0; static uint flash_time=0; //全部關(guān)閉消引 seg_1=0; seg_2=0; seg_3=0; seg_4=0; SEG_DATA=SEG_Table[*(dis_p+temp_num)]; //把數(shù)據(jù)發(fā)送給數(shù)碼管的數(shù)據(jù)接口 switch(temp_num) //動(dòng)態(tài)一次掃描各個(gè)數(shù)碼管 { case 0: if(set_position==4) { if(flash_time<50) //如果社說的時(shí)間小于50那么就打開心事 {seg_1=1;seg_2=0;seg_3=0;seg_4=0;} else if(flash_time<100)//小于100就關(guān)閉顯示 {seg_1=0;seg_2=0;seg_3=0;seg_4=0;} else //大于等于100就重新開始閃爍 {flash_time=0;} } else { seg_1=1; seg_2=0; seg_3=0; seg_4=0; } break; case 1: if(set_position==3) { if( flash_time<50) {seg_1=0;seg_2=1;seg_3=0;seg_4=0;} else if(flash_time<100) {seg_1=0;seg_2=0;seg_3=0;seg_4=0;} else {flash_time=0;} } else { seg_1=0; seg_2=1; seg_3=0; seg_4=0; } break; case 2: if(set_position==2) { if( flash_time<50) {seg_1=0;seg_2=0;seg_3=1;seg_4=0;} else if(flash_time<100) {seg_1=0;seg_2=0;seg_3=0;seg_4=0;} else {flash_time=0;} } else { seg_1=0; seg_2=0; seg_3=1; seg_4=0; } break; case 3: if(set_position==1) { if( flash_time<50) {seg_1=0;seg_2=0;seg_3=0;seg_4=1;} else if(flash_time<100) {seg_1=0;seg_2=0;seg_3=0;seg_4=0;} else {flash_time=0;} } else { seg_1=0; seg_2=0; seg_3=0; seg_4=1; } break; } Delay_1ms(2);
temp_num++; if(temp_num>3) temp_num=0;//循環(huán)四次
flash_time++; if(set_position==0)flash_time=0; //閃爍
} 3.3 重要的數(shù)據(jù)結(jié)構(gòu)、參數(shù)和函數(shù)分析 //讀取設(shè)定的目標(biāo)數(shù)值 void Read_set_num(void) { uchar i=0; for(i=0;i<4;i++) { dis_data_buf[ i]=read_rom(i); [ i] if(dis_data_buf[ i]>9)break; } if(i==4) { set_num=(dis_data_buf[0]*1000)+(dis_data_buf[1]*100)+(dis_data_buf[2]*10)+dis_data_buf[3]; //計(jì)算出計(jì)數(shù)的數(shù)值 } else { for(i=0;i<4;i++) { dis_data_buf[ i]=0; write_rom(i,dis_data_buf[ i]); } } } 這里我們分析一下讀取設(shè)定目標(biāo)數(shù)值的子函數(shù),這個(gè)子函數(shù)在程序的一開始調(diào)用一次,主要是讀取上一次存儲(chǔ)的數(shù)據(jù),防止其掉電丟失。首選讀24C02得到不同地址內(nèi)的數(shù)據(jù),然后根據(jù)存入的順序把數(shù)據(jù)拼接成設(shè)定值給后面使用。 4、項(xiàng)目運(yùn)行效果展示 這是初始狀態(tài)沒有進(jìn)行操作的時(shí)候,如圖 然后我們點(diǎn)擊啟動(dòng)按鈕,可以看到電機(jī)開始轉(zhuǎn)動(dòng)了,如圖 我們按下模擬光電的開關(guān),實(shí)際數(shù)值增加到設(shè)定值,此時(shí)電機(jī)停止并報(bào)警,如圖 5、總結(jié)與心得體會(huì) 這個(gè)設(shè)計(jì)過程中,我們通過在原有的計(jì)數(shù)器系統(tǒng)進(jìn)行了改進(jìn),使之增添了設(shè)置、啟動(dòng)、停止等的三個(gè)控制功能,并添加了報(bào)警、顯示、存儲(chǔ)等功能,使之成為一個(gè)更加適用,功能更加完備的屬于自己的一個(gè)系統(tǒng)。設(shè)計(jì)結(jié)果能夠符合題意,成功完成了此次設(shè)計(jì)要求,這個(gè)過程中,我們花費(fèi)了大量的時(shí)間和精力,更重要的是,我們?cè)趯W(xué)會(huì)創(chuàng)新的基礎(chǔ)上,同時(shí)還懂得合作精神的重要性,學(xué)會(huì)了與他人合作。我們掌握的僅僅是理論知識(shí),如何去鍛煉我們的實(shí)踐能力?如何把我們所學(xué)的專業(yè)基礎(chǔ)課理論知識(shí)運(yùn)用到實(shí)踐中去呢?我想做類似設(shè)計(jì)就為我們提供了良好的實(shí)踐平臺(tái)。
在這次設(shè)計(jì)中,我們運(yùn)用到了以前所學(xué)的專業(yè)知識(shí),如:C語(yǔ)言、模擬和數(shù)字電路知識(shí)等。雖然過去從未獨(dú)立應(yīng)用過它們,但在學(xué)習(xí)的過程中帶著問題去學(xué)效率很高,這是我做這次設(shè)計(jì)的又一收獲。 基于Keil C51的單片機(jī)開發(fā)環(huán)境應(yīng)用范圍廣泛,功能強(qiáng)大,但由于自己應(yīng)用不夠熟悉,出現(xiàn)了很多不規(guī)范的情況,使得在調(diào)試過程中遇到很多困難,這是自己軟件開發(fā)能力不足的表現(xiàn),有待提高。本系統(tǒng)通過按鍵進(jìn)行設(shè)定計(jì)數(shù)功能,需要人為現(xiàn)場(chǎng)近距離操作,可考慮通過遙控設(shè)定,改進(jìn)方案后,可遠(yuǎn)距離操作,更好的節(jié)省人力。
6、附錄 
單片機(jī)源程序如下: - //包含頭文件
- #include<reg52.h>
- #include<intrins.h>
-
- //宏定義方便使用
- #define uint unsigned int
- #define uchar unsigned char
- #define AT24C02 255
- #define AT24C16 2047
- #define AT24CXX AT24C02 //此處修改器件類型24c02或者24c256
-
- sbit SCL = P1^6; //24Cxx接線
- sbit SDA = P1^7;
-
-
- //數(shù)碼管位選接口
- sbit seg_1=P3^0;
- sbit seg_2=P3^1;
- sbit seg_3=P3^2;
- sbit seg_4=P3^3;
-
- #define SEG_DATA P0 //數(shù)碼管的數(shù)據(jù)接口
-
-
- //獨(dú)立按鍵
- sbit K1=P3^7;
- sbit K2=P3^6;
- sbit K3=P3^5;
-
- //矩陣按鍵的接口
- #define K_PORT P2
-
- //蜂鳴器引腳
- sbit BUZZ=P1^0;
- //LED引腳
- sbit LED=P1^1;
-
- //電機(jī)的控機(jī)制口
- sbit moto=P1^2;
-
-
- uchar code SEG_Table[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e};//CA共陽(yáng)
- char dis_data_buf[4]={0,0,0,1};
- uchar counter_buf[4]={0,0,0,0};
- unsigned long int set_num=0;
- unsigned long int counter_num=0;
- uchar set_position=0;
- uchar set_mode=0;
-
-
- void Delay_1ms(uint i)//1ms延時(shí)
- {
- uchar x,j;
- for(j=0;j<i;j++)
- for(x=0;x<=148;x++);
- }
-
- void delay_us(uint i)
- {
- uint t;
- for(t=0;t<i;t++)
- _nop_();
-
- }
-
-
-
- /*開始I2C數(shù)據(jù)發(fā)送或接收*/
- void start_rom()//在時(shí)鐘線為高,數(shù)據(jù)線從高電平跳到低電平時(shí),開始傳送
- {
- SDA=1; //數(shù)據(jù)先
- delay_us(2);
- SCL=1; //時(shí)鐘線為高,等數(shù)據(jù)線下降才開始
- delay_us(5);
- SDA=0; //數(shù)據(jù)線下降拉,啟動(dòng)了
- delay_us(5);
- SCL=0;
- }
-
- /*結(jié)束數(shù)據(jù)傳送*/
- void stop_rom()
- {
- SDA=0; //時(shí)鐘線為高時(shí),數(shù)據(jù)線上升沿為結(jié)束信號(hào)
- delay_us(2);
- SCL=1;
- delay_us(4);
- SDA=1;
- delay_us(4);
- SCL=0;
- }
-
- //************************************************************************//
- //函數(shù)名稱:void ack_rom()
- //函數(shù)功能:ROM應(yīng)答信號(hào)
- //**********************************************************************//
- void ack_rom()
- {
- SDA=1;
- delay_us(2);
- SCL=0;
- delay_us(2);
- SCL=1;
- delay_us(2);
- SCL=0;
- delay_us(2);
- }
-
- //***********************************************************************//
- //函數(shù)名稱:void no_ack_rom()
- //函數(shù)功能:無需應(yīng)答
- //***********************************************************************//
- void no_ack_rom()
- {
- SDA=1;
- delay_us(2);
- SCL=1;
- delay_us(2);
- SCL=0;
- delay_us(2);
- }
-
- //**********************************************//
- //函數(shù)名稱:void write_byte_rom(uchar data)
- //函數(shù)功能:向ROM 寫入字節(jié)
- //傳入?yún)?shù):data 待寫入的字節(jié)
- //返回參數(shù):無
- //**********************************************//
- void write_byte_rom(uchar dataa)
- {
- uchar i=8;
- SDA = 0;
- SCL=0;
- _nop_();_nop_();_nop_();_nop_();_nop_();
- while(i--)//寫數(shù)據(jù)循環(huán),從高位開始
- {
- if((dataa & 0x80)) SDA=1; //將IO 口拉高,寫入1
- else SDA=0; //將IO 口拉低,寫入0
- delay_us(5);
- dataa<<=1;
- SCL=1;
- delay_us(5);
- SCL=0;
- delay_us(5);
- }
- }
-
- uchar read_byte_rom()
- {
- uchar i,k;
- for(i=0;i<8;i++)
- {
- SCL=1;
- delay_us(5);
- k=(k<<1)|SDA;
- SCL=0;
- delay_us(5);
- }
- return k;
- }
-
- uchar read_rom(uint add)
- {
- uchar da;
- start_rom();
- write_byte_rom(0xa0);
- ack_rom();
- if(AT24CXX>AT24C16)
- {
- //write_byte_rom(addr/256); //寫入地址高八位
- write_byte_rom(add>>8); //寫入地址高八位
- ack_rom();
- write_byte_rom(add%256); //寫入地址低八位
- //write_byte_rom(addr&0xff); //寫入地址低八位
- }
- else
- write_byte_rom(add);
-
- ack_rom();
- start_rom();
- write_byte_rom(0xa1);
- ack_rom();
- da=read_byte_rom();
- no_ack_rom();
- stop_rom();
- return da;
-
- }
-
- //**********************************************//
- //函數(shù)名稱:void write_rom(uchar addr,uchar data)
- //函數(shù)功能:寫數(shù)據(jù)到ROM
- //傳入?yún)?shù):addr 寫入的地址
- //返回參數(shù):read_data 待寫入的數(shù)據(jù)
- //**********************************************//
- void write_rom(uint addr,uchar dataa)
- {
- start_rom();
- write_byte_rom(0xa0); //選擇寫操作
- ack_rom();
- if(AT24CXX>AT24C16)
- {
- //write_byte_rom(addr/256); //寫入地址高八位
- write_byte_rom(addr>>8); //寫入地址高八位
- ack_rom();
- write_byte_rom(addr%256); //寫入地址低八位
- //write_byte_rom(addr&0xff); //寫入地址低八位
- }
- else
- write_byte_rom(addr);
- ack_rom();
- write_byte_rom(dataa); //寫入數(shù)據(jù)
-
- ack_rom();
- stop_rom();
-
- }
-
-
-
- //*********************************
- //按鍵掃描程序
- //*********************************
- uchar KEY_Scan()
- {
- uchar table[3]={0xB0,0xd0,0xE0};
- uchar temp=0,temp_data=0,temp_key_num=0XFF;
- uchar i=0,k=0;
- static uchar key_up=0;
-
- K_PORT = 0xF0;
- if(key_up==0)
- {
-
- for(k=0;k<4;k++)
- {
- temp_data=~(1<<k); //逐行拉低判斷有沒有按鍵按下
- _nop_();
- K_PORT=temp_data;
- if(K_PORT!=temp_data)//有按鍵按下
- {
- Delay_1ms(10);//去抖動(dòng)
- if(K_PORT!=temp_data)//有按鍵按下
- {
- key_up=1;
- temp=K_PORT&0xf0; //取高字節(jié),即列
- for(i=0;i<3;i++)
- {
- if(temp==table[i])
- {
- break;
- }
- }
- if(i!=3)//有效按鍵
- {
- temp_key_num=i+k*3; //獲取按鍵
- break;
- }
-
- }
- }
- }
-
- //判斷獨(dú)立按鍵
- if((K1==0||K2==0||K3==0))
- {
- key_up=1;
- Delay_1ms(10);//去抖動(dòng)
- if(K1==0)temp_key_num=12;
- else if(K2==0)temp_key_num=13;
- else if(K3==0)temp_key_num=14;
- }
-
- }
- else
- {
- if((K_PORT==0xf0)&&(K1==1)&&(K2==1)&&(K3==1))key_up=0; //松開按鍵
- temp_key_num=0XFF;
- }
- return temp_key_num;// 返回鍵值
- }
-
- //數(shù)碼管的顯示函數(shù)
- void diplay(uchar *dis_p)
- {
- static uchar temp_num=0;
- static uint flash_time=0;
- //全部關(guān)閉消引
- seg_1=0;
- seg_2=0;
- seg_3=0;
- seg_4=0;
- SEG_DATA=SEG_Table[*(dis_p+temp_num)]; //把數(shù)據(jù)發(fā)送給數(shù)碼管的數(shù)據(jù)接口
- switch(temp_num) //動(dòng)態(tài)一次掃描各個(gè)數(shù)碼管
- {
- case 0:
- if(set_position==4)
- {
- if(flash_time<50) //如果社說的時(shí)間小于50那么就打開心事
- {seg_1=1;seg_2=0;seg_3=0;seg_4=0;}
- else if(flash_time<100)//小于100就關(guān)閉顯示
- {seg_1=0;seg_2=0;seg_3=0;seg_4=0;}
- else //大于等于100就重新開始閃爍
- {flash_time=0;}
- }
- else
- {
- seg_1=1;
- seg_2=0;
- seg_3=0;
- seg_4=0;
- }
- break;
- case 1:
- if(set_position==3)
- {
- if( flash_time<50)
- {seg_1=0;seg_2=1;seg_3=0;seg_4=0;}
- else if(flash_time<100)
- {seg_1=0;seg_2=0;seg_3=0;seg_4=0;}
- else
- {flash_time=0;}
- }
- else
- {
- seg_1=0;
- seg_2=1;
- seg_3=0;
- seg_4=0;
- }
- break;
- case 2:
- if(set_position==2)
- {
- if( flash_time<50)
- {seg_1=0;seg_2=0;seg_3=1;seg_4=0;}
- else if(flash_time<100)
- {seg_1=0;seg_2=0;seg_3=0;seg_4=0;}
- else
- {flash_time=0;}
- }
- else
- {
- seg_1=0;
- seg_2=0;
- seg_3=1;
- seg_4=0;
- }
- break;
- case 3:
- if(set_position==1)
- {
- if( flash_time<50)
- {seg_1=0;seg_2=0;seg_3=0;seg_4=1;}
- else if(flash_time<100)
- {seg_1=0;seg_2=0;seg_3=0;seg_4=0;}
- else
- {flash_time=0;}
- }
- else
- {
- seg_1=0;
- seg_2=0;
- seg_3=0;
- seg_4=1;
- }
- break;
- }
- Delay_1ms(2);
-
- temp_num++;
- if(temp_num>3) temp_num=0;//循環(huán)四次
-
- flash_time++;
- if(set_position==0)flash_time=0; //閃爍
-
-
- }
- //計(jì)數(shù)器0的初始化
- void Time0_init(void)
- {
- TMOD=0x05;
- TH0=0xff;
- TL0=0xff;
- ET0=1;
- TR0=1;
- EA=1;
-
- }
-
- //讀取設(shè)定的目標(biāo)數(shù)值
- void Read_set_num(void)
- {
- uchar i=0;
- for(i=0;i<4;i++)
- {
- dis_data_buf[i]=read_rom(i);
- if(dis_data_buf[i]>9)break;
- }
- if(i==4)
- {
- set_num=(dis_data_buf[0]*1000)+(dis_data_buf[1]*100)+(dis_data_buf[2]*10)+dis_data_buf[3]; //計(jì)算出計(jì)數(shù)的數(shù)值
- }
- else
- {
- for(i=0;i<4;i++)
- {
- dis_data_buf[i]=0;
- write_rom(i,dis_data_buf[i]);
- }
- }
- }
- //向eeprom中寫入存儲(chǔ)數(shù)據(jù)
- void Write_set_num()
- {
- uchar i=0;
- for(i=0;i<4;i++)
- write_rom(i,dis_data_buf[i]);
-
-
- }
- /********************************************************************
- * 名稱 : Main()
- * 功能 : 主函數(shù)
- * 輸入 : 無
- * 輸出 : 無
- ***********************************************************************/
- void Main(void)
- {
- uchar press_sure_num=0;
- uchar Key_num=0;
- uchar temp=0;
-
- moto=0; //關(guān)閉電機(jī)
- BUZZ=1; //關(guān)閉報(bào)警
- Read_set_num(); //讀取設(shè)定的數(shù)值
- Time0_init(); // 定時(shí)器初始化
-
- while(1)
- {
- Key_num=KEY_Scan(); //掃描按鍵
-
- if(set_mode==0) //非設(shè)定模式
- {
- if(Key_num==12) //啟動(dòng)
- {
- counter_buf[0]=0;counter_buf[1]=0;counter_buf[2]=0;counter_buf[3]=0; //清除顯示
- counter_num=0; //計(jì)數(shù)清零
- moto=1; //打開電機(jī)
- LED=1;
- BUZZ=1; //關(guān)閉報(bào)警
- EA=1; //打開計(jì)數(shù)
- }
- else if(Key_num==13)//停止
- {
- moto=0; //關(guān)閉電機(jī)
- LED=1;
- BUZZ=1;//關(guān)閉報(bào)警
- EA=0; //關(guān)閉計(jì)數(shù)
- }
- if(Key_num==14) //設(shè)置
- {
- set_mode=1; //設(shè)置模式置一
- set_position=1;
- moto=0; //關(guān)閉電機(jī)
- EA=0; //關(guān)閉計(jì)數(shù)
-
- }
-
-
- }
- else//設(shè)定模式
- {
- if(Key_num==11)//按下了確定鍵
- {
- set_mode=0;//退出設(shè)定
- set_position=0;
- counter_buf[0]=0;counter_buf[1]=0;counter_buf[2]=0;counter_buf[3]=0;
- //set_num=(dis_data_buf[0]*1000)+(dis_data_buf[1]*100)+(dis_data_buf[2]*10)+dis_data_buf[3]; //計(jì)算出計(jì)數(shù)的數(shù)值
- Write_set_num();
- }
- else if(Key_num<10)//顯示的設(shè)定值
- {
-
- dis_data_buf[4-set_position]=Key_num;
- set_position++;
- if(set_position>4)set_position=4;
- }
- else if(Key_num==10)//清除設(shè)定
- {
- set_position=1;
- dis_data_buf[0]=0;
- dis_data_buf[1]=0;
- dis_data_buf[2]=0;
- dis_data_buf[3]=0;
- }
- }
-
- set_num=(dis_data_buf[0]*1000)+(dis_data_buf[1]*100)+(dis_data_buf[2]*10)+dis_data_buf[3]; //計(jì)算出計(jì)數(shù)的數(shù)值
-
- if(counter_num>=set_num) //如果計(jì)數(shù)數(shù)值大于等于設(shè)定的數(shù)值就停止
- {
- moto=0; //關(guān)閉電機(jī)
- BUZZ=0; //打開報(bào)警
- LED=0;//
-
- }
- if(set_mode==0) //正常模式下顯示計(jì)數(shù)值
- {
- diplay(counter_buf);
- }
- else //設(shè)定模式下顯示設(shè)定值
- {
- diplay(dis_data_buf);
- }
-
-
- }
- }
-
- //計(jì)數(shù)器0中斷
- void Time0_counter() interrupt 1
- {
- TH0=0xff;
- TL0=0xff;
-
- if(TF0==0)
- {
- if(counter_num>9999)counter_num=0; //最大計(jì)數(shù)到9999,然后從零開始
- else
- {
- counter_num++; //計(jì)數(shù)加一
- counter_buf[3]++;
- if(counter_buf[3]>9) //個(gè)位大于9十位就加一
- {
- counter_buf[3]=0;
- counter_buf[2]++;
- }
- if(counter_buf[2]>9) //十位大于9百位就加一
- {
- counter_buf[2]=0;
- counter_buf[1]++;
- }
- if(counter_buf[1]>9)
- {
- counter_buf[1]=0;
- counter_buf[0]++;
- }
- if(counter_buf[0]>9)
- {
- counter_buf[0]=0;
- }
- }
- }
- }
復(fù)制代碼
|