標(biāo)題: 單片機(jī)轉(zhuǎn)送帶計(jì)數(shù)器設(shè)計(jì) 附源程序原理圖 [打印本頁(yè)]
作者: 佳桂 時(shí)間: 2023-7-29 08:13
標(biāo)題: 單片機(jī)轉(zhuǎn)送帶計(jì)數(shù)器設(shè)計(jì) 附源程序原理圖
目錄
1、項(xiàng)目需求分析 2
11、項(xiàng)目目標(biāo)意義 2
12、功能需求分析 2
13、系統(tǒng)開(kāi)發(fā)環(huán)境、工具需求分析與選擇 2
14、非功能性需求分析 2
2、項(xiàng)目硬件系統(tǒng)結(jié)構(gòu) 2
21、 系統(tǒng)方案原理圖 2
22、AT89C51原理介紹 2
23 、光電開(kāi)關(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ù)量,基于光電開(kāi)關(guān)和AT89C51單片機(jī)開(kāi)發(fā)的傳送帶計(jì)數(shù)器完美解決了傳送帶上面運(yùn)送的產(chǎn)品需要人工計(jì)數(shù)的煩惱,通過(guò)該計(jì)數(shù)器的應(yīng)用,企業(yè)無(wú)論是計(jì)數(shù)效率和準(zhǔn)確度方面都有了質(zhì)的提升而普及自動(dòng)計(jì)數(shù)器也具有非常實(shí)際的意義,受到廣大企業(yè)的青睞。
1.2、功能需求分析
通過(guò)光電開(kāi)關(guān)檢測(cè)傳送帶傳送過(guò)來(lái)的產(chǎn)品,每過(guò)一個(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ù)的顯示功能;通過(guò)EEPROM存儲(chǔ)器,實(shí)現(xiàn)計(jì)數(shù)的存儲(chǔ)功能;添加按鍵實(shí)現(xiàn)相關(guān)設(shè)置功能。
1.3、系統(tǒng)開(kāi)發(fā)環(huán)境、工具需求分析與選擇
本系統(tǒng)是基于Keil C51的單片機(jī)開(kāi)發(fā)環(huán)境進(jìn)行的開(kāi)發(fā),Keil C51是美國(guó)Keil Software公司出品的51系列兼容單片機(jī)C語(yǔ)言軟件開(kāi)發(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ā)展已越來(lái)越成熟,每個(gè)行業(yè)都在尋求自動(dòng)化來(lái)代替人工,基于光電開(kāi)關(guān)和AT89C51單片機(jī)開(kāi)發(fā)的傳送帶計(jì)數(shù)器使用簡(jiǎn)單,操作方便,有效節(jié)省了人工成本,單位時(shí)間內(nèi)提高了工作效率,給企業(yè)帶來(lái)更大的收益。
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)通過(guò)這幾個(gè)模塊協(xié)同工作實(shí)現(xiàn)傳送帶計(jì)數(shù)器的功能。
2.2、AT89C51原理介紹
AT89C51是一種帶4K字節(jié)閃爍可編程可擦除只讀存儲(chǔ)器(FPEROM—Falsh Programmable and Erasable Read Only Memory)的低電壓,高性能CMOS8位微處理器,俗稱(chēng)單片機(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三大類(lèi);P0可以作普通IO口,也可以在讀寫(xiě)外部存儲(chǔ)器作低8位的地址總線(xiàn)和8位的數(shù)據(jù)總線(xiàn);P1口只作為一般IO口;P2作為一般IO口還在在讀寫(xiě)外部存儲(chǔ)器作高8位的地址總線(xiàn);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ǔ)器寫(xiě)選通信號(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ù)滿(mǎn)后自動(dòng)裝入計(jì)數(shù)初值,精確定時(shí)并簡(jiǎn)化定時(shí)初值;方式3只適用于T0,T1不能工作在方式3。
2.3 、光電開(kāi)關(guān)模塊原理
光電開(kāi)關(guān)即光電傳感器,是光電接近開(kāi)關(guān)的簡(jiǎn)稱(chēng),它主要是利用被檢測(cè)物對(duì)光束的遮擋或反射,由同步回路選通電路,從而檢測(cè)物體有無(wú)的。光電開(kāi)關(guān)是傳感器的一種,它把發(fā)射端和接收端之間光的強(qiáng)弱變化轉(zhuǎn)化為電流的變化以達(dá)到探測(cè)的目的。例當(dāng)光電開(kāi)關(guān)被產(chǎn)品遮擋時(shí),輸出引腳變低電平,單片機(jī)檢測(cè)到低電平計(jì)數(shù)一次代表一個(gè)產(chǎn)品,當(dāng)光電開(kāi)關(guān)無(wú)遮擋是,輸出引腳變高電平,單片機(jī)檢測(cè)到高電平不予計(jì)數(shù),代表無(wú)產(chǎn)品通過(guò)。我們這里使用一個(gè)開(kāi)關(guān)模擬他的信號(hào),這個(gè)開(kāi)關(guān)接入單片機(jī)的P3.4口,當(dāng)按鍵按下一次表示檢測(cè)到一個(gè)商品。
2.4、報(bào)警模塊原理
本系統(tǒng)采用蜂鳴器和LED指示燈做報(bào)警元件,蜂鳴器一端接電源,另一端通過(guò)三級(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口線(xiàn)構(gòu)成的單個(gè)按鍵電路,其特點(diǎn)式每個(gè)按鍵單獨(dú)占用一根I/O口線(xiàn),每個(gè)按鍵的工作不會(huì)影響其他I/O口線(xiàn)的狀態(tài)。獨(dú)立式按鍵電路配置靈活,軟件結(jié)構(gòu)簡(jiǎn)單,但每個(gè)按鍵必須占用一個(gè)I/O口線(xiàn),因此,在按鍵較多時(shí),I/O口線(xiàn)浪費(fèi)較大,不宜采用。獨(dú)立按鍵的軟件常采用查詢(xún)式結(jié)構(gòu)。先逐位查詢(xún)沒(méi)跟I/O口線(xiàn)的輸入狀態(tài),如某一根I/O口線(xiàn)輸入為低電平,則可確認(rèn)該I/O口線(xiàn)所對(duì)應(yīng)的按鍵已按下,然后,再轉(zhuǎn)向該鍵的功能處理程序。矩陣按鍵是逐行掃描,然后判斷有沒(méi)有按鍵按下,有按下的時(shí)候再判斷列,最終確定按鍵的數(shù)值。
2.6、數(shù)碼管顯示模塊原理
數(shù)碼管也稱(chēng)LED數(shù)碼管,晶美、光電、不同行業(yè)人士對(duì)數(shù)碼管的稱(chēng)呼不一樣,其實(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接到地線(xiàn)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í)又可以在高于普通電壓的作用下擦除和重寫(xiě),這就方便了單片機(jī)對(duì)其的開(kāi)發(fā),現(xiàn)在電腦上的ROM很多都是用的EEPROM。
2.8、傳送帶電機(jī)驅(qū)動(dòng)模塊原理
本系統(tǒng)采用單片機(jī)通過(guò)三極管控制繼電器驅(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í),三極管截止,繼電器斷開(kāi),電機(jī)電源端斷開(kāi),電機(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ù)值。
/********************************************************************
* 名稱(chēng) : Main()
* 功能 : 主函數(shù)
* 輸入 : 無(wú)
* 輸出 : 無(wú)
***********************************************************************/
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; //打開(kāi)電機(jī)
LED=1;
BUZZ=1; //關(guān)閉報(bào)警
EA=1; //打開(kāi)計(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; //打開(kāi)報(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ù)碼管的顯示,這一步稱(chēng)為消引。然后把顯示的數(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) //如果社說(shuō)的時(shí)間小于50那么就打開(kāi)心事
{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就重新開(kāi)始閃爍
{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ù)在程序的一開(kāi)始調(diào)用一次,主要是讀取上一次存儲(chǔ)的數(shù)據(jù),防止其掉電丟失。首選讀24C02得到不同地址內(nèi)的數(shù)據(jù),然后根據(jù)存入的順序把數(shù)據(jù)拼接成設(shè)定值給后面使用。
4、項(xiàng)目運(yùn)行效果展示
這是初始狀態(tài)沒(méi)有進(jìn)行操作的時(shí)候,如圖
然后我們點(diǎn)擊啟動(dòng)按鈕,可以看到電機(jī)開(kāi)始轉(zhuǎn)動(dòng)了,如圖
我們按下模擬光電的開(kāi)關(guān),實(shí)際數(shù)值增加到設(shè)定值,此時(shí)電機(jī)停止并報(bào)警,如圖
5、總結(jié)與心得體會(huì)
這個(gè)設(shè)計(jì)過(guò)程中,我們通過(guò)在原有的計(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è)過(guò)程中,我們花費(fèi)了大量的時(shí)間和精力,更重要的是,我們?cè)趯W(xué)會(huì)創(chuàng)新的基礎(chǔ)上,同時(shí)還懂得合作精神的重要性,學(xué)會(huì)了與他人合作。我們掌握的僅僅是理論知識(shí),如何去鍛煉我們的實(shí)踐能力?如何把我們所學(xué)的專(zhuān)業(yè)基礎(chǔ)課理論知識(shí)運(yùn)用到實(shí)踐中去呢?我想做類(lèi)似設(shè)計(jì)就為我們提供了良好的實(shí)踐平臺(tái)。
在這次設(shè)計(jì)中,我們運(yùn)用到了以前所學(xué)的專(zhuān)業(yè)知識(shí),如:C語(yǔ)言、模擬和數(shù)字電路知識(shí)等。雖然過(guò)去從未獨(dú)立應(yīng)用過(guò)它們,但在學(xué)習(xí)的過(guò)程中帶著問(wèn)題去學(xué)效率很高,這是我做這次設(shè)計(jì)的又一收獲。
基于Keil C51的單片機(jī)開(kāi)發(fā)環(huán)境應(yīng)用范圍廣泛,功能強(qiáng)大,但由于自己應(yīng)用不夠熟悉,出現(xiàn)了很多不規(guī)范的情況,使得在調(diào)試過(guò)程中遇到很多困難,這是自己軟件開(kāi)發(fā)能力不足的表現(xiàn),有待提高。本系統(tǒng)通過(guò)按鍵進(jìn)行設(shè)定計(jì)數(shù)功能,需要人為現(xiàn)場(chǎng)近距離操作,可考慮通過(guò)遙控設(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 //此處修改器件類(lèi)型24c02或者24c256
-
- sbit SCL = P1^6; //24Cxx接線(xiàn)
- 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_();
-
- }
-
-
-
- /*開(kāi)始I2C數(shù)據(jù)發(fā)送或接收*/
- void start_rom()//在時(shí)鐘線(xiàn)為高,數(shù)據(jù)線(xiàn)從高電平跳到低電平時(shí),開(kāi)始傳送
- {
- SDA=1; //數(shù)據(jù)先
- delay_us(2);
- SCL=1; //時(shí)鐘線(xiàn)為高,等數(shù)據(jù)線(xiàn)下降才開(kāi)始
- delay_us(5);
- SDA=0; //數(shù)據(jù)線(xiàn)下降拉,啟動(dòng)了
- delay_us(5);
- SCL=0;
- }
-
- /*結(jié)束數(shù)據(jù)傳送*/
- void stop_rom()
- {
- SDA=0; //時(shí)鐘線(xiàn)為高時(shí),數(shù)據(jù)線(xiàn)上升沿為結(jié)束信號(hào)
- delay_us(2);
- SCL=1;
- delay_us(4);
- SDA=1;
- delay_us(4);
- SCL=0;
- }
-
- //************************************************************************//
- //函數(shù)名稱(chēng):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ù)名稱(chēng):void no_ack_rom()
- //函數(shù)功能:無(wú)需應(yīng)答
- //***********************************************************************//
- void no_ack_rom()
- {
- SDA=1;
- delay_us(2);
- SCL=1;
- delay_us(2);
- SCL=0;
- delay_us(2);
- }
-
- //**********************************************//
- //函數(shù)名稱(chēng):void write_byte_rom(uchar data)
- //函數(shù)功能:向ROM 寫(xiě)入字節(jié)
- //傳入?yún)?shù):data 待寫(xiě)入的字節(jié)
- //返回參數(shù):無(wú)
- //**********************************************//
- void write_byte_rom(uchar dataa)
- {
- uchar i=8;
- SDA = 0;
- SCL=0;
- _nop_();_nop_();_nop_();_nop_();_nop_();
- while(i--)//寫(xiě)數(shù)據(jù)循環(huán),從高位開(kāi)始
- {
- if((dataa & 0x80)) SDA=1; //將IO 口拉高,寫(xiě)入1
- else SDA=0; //將IO 口拉低,寫(xiě)入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); //寫(xiě)入地址高八位
- write_byte_rom(add>>8); //寫(xiě)入地址高八位
- ack_rom();
- write_byte_rom(add%256); //寫(xiě)入地址低八位
- //write_byte_rom(addr&0xff); //寫(xiě)入地址低八位
- }
- 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ù)名稱(chēng):void write_rom(uchar addr,uchar data)
- //函數(shù)功能:寫(xiě)數(shù)據(jù)到ROM
- //傳入?yún)?shù):addr 寫(xiě)入的地址
- //返回參數(shù):read_data 待寫(xiě)入的數(shù)據(jù)
- //**********************************************//
- void write_rom(uint addr,uchar dataa)
- {
- start_rom();
- write_byte_rom(0xa0); //選擇寫(xiě)操作
- ack_rom();
- if(AT24CXX>AT24C16)
- {
- //write_byte_rom(addr/256); //寫(xiě)入地址高八位
- write_byte_rom(addr>>8); //寫(xiě)入地址高八位
- ack_rom();
- write_byte_rom(addr%256); //寫(xiě)入地址低八位
- //write_byte_rom(addr&0xff); //寫(xiě)入地址低八位
- }
- else
- write_byte_rom(addr);
- ack_rom();
- write_byte_rom(dataa); //寫(xiě)入數(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); //逐行拉低判斷有沒(méi)有按鍵按下
- _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; //松開(kāi)按鍵
- 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) //如果社說(shuō)的時(shí)間小于50那么就打開(kāi)心事
- {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就重新開(kāi)始閃爍
- {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中寫(xiě)入存儲(chǔ)數(shù)據(jù)
- void Write_set_num()
- {
- uchar i=0;
- for(i=0;i<4;i++)
- write_rom(i,dis_data_buf[i]);
-
-
- }
- /********************************************************************
- * 名稱(chēng) : Main()
- * 功能 : 主函數(shù)
- * 輸入 : 無(wú)
- * 輸出 : 無(wú)
- ***********************************************************************/
- 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; //打開(kāi)電機(jī)
- LED=1;
- BUZZ=1; //關(guān)閉報(bào)警
- EA=1; //打開(kāi)計(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; //打開(kāi)報(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,然后從零開(kāi)始
- 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ù)制代碼
| 歡迎光臨 (http://m.raoushi.com/bbs/) |
Powered by Discuz! X3.1 |