第49節(jié):利用DS18B20做一個溫控器
DS18B20是一款常用的溫度傳感器芯片,它只占用單片機(jī)一根IO口,使用起來也特別方便。需要特別注意的是,正因?yàn)樗挥靡桓鵌O口跟單片機(jī)通訊,因此讀取一次溫度值的通訊時間比較長,而且時序要求嚴(yán)格,在通訊期間不允許被單片機(jī)其它的中斷干擾,因此在實(shí)際項目中,系統(tǒng)一旦選用了這款傳感器芯片,就千萬不要選用動態(tài)掃描數(shù)碼管的顯示方式。否則在關(guān)閉中斷讀取溫度的時候,數(shù)碼管的顯示會有略微的“閃爍”現(xiàn)象。
DS18B20的測溫范圍是-55度至125度。在-10度至85度的溫度范圍內(nèi)誤差是+-0.5度,能滿足大部分常用的測溫要求。
這一節(jié)要教會大家三個知識點(diǎn):
第一個:大概了解一下DS18B20的驅(qū)動程序。
第二個:做溫控設(shè)備的時候,為了避免繼電器在臨界溫度附近頻繁跳動切換,應(yīng)該設(shè)置一個緩沖溫差。本程序的緩沖溫差是2度。
第三個:繼續(xù)加深了解按鍵,顯示,傳感器它們?nèi)呤侨绾尉o密關(guān)聯(lián)起來的程序框架。
具體內(nèi)容,請看源代碼講解。
(1) 硬件平臺.
基于朱兆祺51單片機(jī)學(xué)習(xí)板。
(2)實(shí)現(xiàn)功能:
本程序只有1個窗口。這個窗口有2個局部顯示。
第1個局部是第7,6,5位數(shù)碼管,顯示設(shè)定的溫度。
第2個局部是第4,3,2,1位數(shù)碼管,顯示實(shí)際環(huán)境溫度。其中第4位數(shù)碼管顯示正負(fù)符號位。
S1按鍵是加鍵,S5按鍵是減鍵。通過它們可以直接設(shè)置“設(shè)定溫度”。
一個LED燈用來模擬工控的繼電器。
當(dāng)實(shí)際溫度低于或者等于設(shè)定溫度2度以下時,模擬繼電器的LED燈亮。
當(dāng)實(shí)際溫度等于或者大于設(shè)定溫度時,模擬繼電器的LED燈滅。
當(dāng)實(shí)際溫度處于設(shè)定溫度和設(shè)定溫度減去2度的范圍內(nèi),模擬繼電器的LED維持現(xiàn)狀,這個2度范圍用來做緩沖溫差,避免繼電器在臨界溫度附近頻繁跳動切換。
(3)源代碼講解如下:
- #include "REG52.H"
- #define const_voice_short40 //蜂鳴器短叫的持續(xù)時間
- #define const_key_time120 //按鍵去抖動延時的時間
- #define const_key_time220 //按鍵去抖動延時的時間
- #define const_ds18b20_sampling_time 180 //累計主循環(huán)次數(shù)的時間,每次刷新采樣時鐘芯片的時間
- void initial_myself(void);
- void initial_peripheral(void);
- void delay_short(unsigned int uiDelayShort);
- void delay_long(unsigned int uiDelaylong);
- //驅(qū)動數(shù)碼管的74HC595
- void dig_hc595_drive(unsigned char ucDigStatusTemp16_09,unsigned char ucDigStatusTemp08_01);
- void display_drive(void); //顯示數(shù)碼管字模的驅(qū)動函數(shù)
- void display_service(void); //顯示的窗口菜單服務(wù)程序
- //驅(qū)動LED的74HC595
- void hc595_drive(unsigned char ucLedStatusTemp16_09,unsigned char ucLedStatusTemp08_01);
- void T0_time(void);//定時中斷函數(shù)
- void key_service(void); //按鍵服務(wù)的應(yīng)用程序
- void key_scan(void);//按鍵掃描函數(shù) 放在定時中斷里
- void temper_control_service(void); //溫控程序
- void ds18b20_sampling(void); //ds18b20采樣程序
- void ds18b20_reset(); //復(fù)位ds18b20的時序
- unsigned char ds_read_byte(void ); //讀一字節(jié)
- void ds_write_byte(unsigned char dat); //寫一個字節(jié)
- unsigned int get_temper();//讀取一次沒有經(jīng)過換算的溫度數(shù)值
- sbit dq_dr_sr=P2^6; //ds18b20的數(shù)據(jù)驅(qū)動線
- sbit key_sr1=P0^0; //對應(yīng)朱兆祺學(xué)習(xí)板的S1鍵
- sbit key_sr2=P0^1; //對應(yīng)朱兆祺學(xué)習(xí)板的S5鍵
- sbit led_dr=P3^5;//LED燈,模擬工控中的繼電器
- sbit key_gnd_dr=P0^4; //模擬獨(dú)立按鍵的地GND,因此必須一直輸出低電平
- sbit beep_dr=P2^7; //蜂鳴器的驅(qū)動IO口
- sbit dig_hc595_sh_dr=P2^0; //數(shù)碼管的74HC595程序
- sbit dig_hc595_st_dr=P2^1;
- sbit dig_hc595_ds_dr=P2^2;
- sbit hc595_sh_dr=P2^3; //LED燈的74HC595程序
- sbit hc595_st_dr=P2^4;
- sbit hc595_ds_dr=P2^5;
- unsigned int uiSampingCnt=0; //采集Ds1302的計時器,每秒鐘更新采集一次
- unsigned char ucSignFlag=0; //正負(fù)符號。0代表正數(shù),1代表負(fù)數(shù),表示零下多少度。
- unsigned long ulCurrentTemper=33; //實(shí)際溫度
- unsigned long ulSetTemper=26; //設(shè)定溫度
- unsigned int uiTemperTemp=0; //中間變量
- unsigned char ucKeySec=0; //被觸發(fā)的按鍵編號
- unsigned intuiKeyTimeCnt1=0; //按鍵去抖動延時計數(shù)器
- unsigned char ucKeyLock1=0; //按鍵觸發(fā)后自鎖的變量標(biāo)志
- unsigned intuiKeyTimeCnt2=0; //按鍵去抖動延時計數(shù)器
- unsigned char ucKeyLock2=0; //按鍵觸發(fā)后自鎖的變量標(biāo)志
- unsigned intuiVoiceCnt=0;//蜂鳴器鳴叫的持續(xù)時間計數(shù)器
- unsigned charucVoiceLock=0;//蜂鳴器鳴叫的原子鎖
- unsigned char ucDigShow8;//第8位數(shù)碼管要顯示的內(nèi)容
- unsigned char ucDigShow7;//第7位數(shù)碼管要顯示的內(nèi)容
- unsigned char ucDigShow6;//第6位數(shù)碼管要顯示的內(nèi)容
- unsigned char ucDigShow5;//第5位數(shù)碼管要顯示的內(nèi)容
- unsigned char ucDigShow4;//第4位數(shù)碼管要顯示的內(nèi)容
- unsigned char ucDigShow3;//第3位數(shù)碼管要顯示的內(nèi)容
- unsigned char ucDigShow2;//第2位數(shù)碼管要顯示的內(nèi)容
- unsigned char ucDigShow1;//第1位數(shù)碼管要顯示的內(nèi)容
- unsigned char ucDigDot8;//數(shù)碼管8的小數(shù)點(diǎn)是否顯示的標(biāo)志
- unsigned char ucDigDot7;//數(shù)碼管7的小數(shù)點(diǎn)是否顯示的標(biāo)志
- unsigned char ucDigDot6;//數(shù)碼管6的小數(shù)點(diǎn)是否顯示的標(biāo)志
- unsigned char ucDigDot5;//數(shù)碼管5的小數(shù)點(diǎn)是否顯示的標(biāo)志
- unsigned char ucDigDot4;//數(shù)碼管4的小數(shù)點(diǎn)是否顯示的標(biāo)志
- unsigned char ucDigDot3;//數(shù)碼管3的小數(shù)點(diǎn)是否顯示的標(biāo)志
- unsigned char ucDigDot2;//數(shù)碼管2的小數(shù)點(diǎn)是否顯示的標(biāo)志
- unsigned char ucDigDot1;//數(shù)碼管1的小數(shù)點(diǎn)是否顯示的標(biāo)志
- unsigned char ucDigShowTemp=0; //臨時中間變量
- unsigned char ucDisplayDriveStep=1;//動態(tài)掃描數(shù)碼管的步驟變量
- unsigned char ucWd=1;//因?yàn)楸境绦蛑挥?個窗口,在實(shí)際項目中,此處的ucWd也可以省略不要
- unsigned char ucWd1Part1Update=1;//在窗口1中,局部1的更新顯示標(biāo)志
- unsigned char ucWd1Part2Update=1; //在窗口1中,局部2的更新顯示標(biāo)志
- unsigned char ucTemp1=0;//中間過渡變量
- unsigned char ucTemp2=0;//中間過渡變量
- unsigned char ucTemp3=0;//中間過渡變量
- unsigned char ucTemp4=0;//中間過渡變量
- unsigned char ucTemp5=0;//中間過渡變量
- unsigned char ucTemp6=0;//中間過渡變量
- unsigned char ucTemp7=0;//中間過渡變量
- unsigned char ucTemp8=0;//中間過渡變量
- //根據(jù)原理圖得出的共陰數(shù)碼管字模表
- code unsigned char dig_table[]=
- {
- 0x3f,//0 序號0
- 0x06,//1 序號1
- 0x5b,//2 序號2
- 0x4f,//3 序號3
- 0x66,//4 序號4
- 0x6d,//5 序號5
- 0x7d,//6 序號6
- 0x07,//7 序號7
- 0x7f,//8 序號8
- 0x6f,//9 序號9
- 0x00,//無 序號10
- 0x40,//- 序號11
- 0x73,//P 序號12
- };
- void main()
- {
- initial_myself();
- delay_long(100);
- initial_peripheral();
- while(1)
- {
- key_service(); //按鍵服務(wù)的應(yīng)用程序
- ds18b20_sampling(); //ds18b20采樣程序
- temper_control_service(); //溫控程序
- display_service(); //顯示的窗口菜單服務(wù)程序
- }
- }
- /* 注釋一:
- * 做溫控設(shè)備的時候,為了避免繼電器在臨界溫度附近頻繁跳動切換,應(yīng)該設(shè)置一個
- * 緩沖溫差。本程序的緩沖溫差是2度。
- */
- void temper_control_service(void) //溫控程序
- {
- if(ucSignFlag==0) //是正數(shù)的前提下
- {
- if(ulCurrentTemper>=ulSetTemper)//當(dāng)實(shí)際溫度大于等于設(shè)定溫度時
- {
- led_dr=0; //模擬繼電器的LED燈熄滅
- }
- else if(ulCurrentTemper<=(ulSetTemper-2))//當(dāng)實(shí)際溫度小于等于設(shè)定溫度2讀以下時,這里的2是緩沖溫差2度
- {
- led_dr=1; //模擬繼電器的LED燈點(diǎn)亮
- }
- }
- else//是負(fù)數(shù),說明是零下多少度的情況下
- {
- led_dr=1; //模擬繼電器的LED燈點(diǎn)亮
- }
- }
- void ds18b20_sampling(void) //ds18b20采樣程序
- {
- ++uiSampingCnt;//累計主循環(huán)次數(shù)的時間
- if(uiSampingCnt>const_ds18b20_sampling_time)//每隔一段時間就更新采集一次Ds18b20數(shù)據(jù)
- {
- uiSampingCnt=0;
- ET0=0;//禁止定時中斷
- uiTemperTemp=get_temper();//讀取一次沒有經(jīng)過換算的溫度數(shù)值
- ET0=1; //開啟定時中斷
- if((uiTemperTemp&0xf800)==0xf800) //是負(fù)號
- {
- ucSignFlag=1;
- uiTemperTemp=~uiTemperTemp;//求補(bǔ)碼
- uiTemperTemp=uiTemperTemp+1;
- }
- else //是正號
- {
- ucSignFlag=0;
- }
- ulCurrentTemper=0; //把int數(shù)據(jù)類型賦給long類型之前要先清零
- ulCurrentTemper=uiTemperTemp;
- ulCurrentTemper=ulCurrentTemper*10; //為了先保留一位小數(shù)點(diǎn),所以放大10倍,
- ulCurrentTemper=ulCurrentTemper>>4;//往右邊移動4位,相當(dāng)于乘以0.0625. 此時保留了1位小數(shù)點(diǎn),
- ulCurrentTemper=ulCurrentTemper+5;//四舍五入
- ulCurrentTemper=ulCurrentTemper/10; //四舍五入后,去掉小數(shù)點(diǎn)
- ucWd1Part2Update=1; //局部2更新顯示實(shí)時溫度
- }
- }
- //ds18b20驅(qū)動程序
- unsigned int get_temper()//讀取一次沒有經(jīng)過換算的溫度數(shù)值
- {
- unsigned char temper_H;
- unsigned char temper_L;
- unsigned int ds18b20_data=0;
- ds18b20_reset(); //復(fù)位ds18b20的時序
- ds_write_byte(0xCC);
- ds_write_byte(0x44);
- ds18b20_reset(); //復(fù)位ds18b20的時序
- ds_write_byte(0xCC);
- ds_write_byte(0xBE);
- temper_L=ds_read_byte();
- temper_H=ds_read_byte();
- ds18b20_data=temper_H; //把兩個字節(jié)合并成一個int數(shù)據(jù)類型
- ds18b20_data=ds18b20_data<<8;
- ds18b20_data=ds18b20_data|temper_L;
- return ds18b20_data;
- }
- void ds18b20_reset() //復(fù)位ds18b20的時序
- {
- unsigned char x;
- dq_dr_sr=1;
- delay_short(8);
- dq_dr_sr=0;
- delay_short(80);
- dq_dr_sr=1;
- delay_short(14);
- x=dq_dr_sr;
- delay_short(20);
- }
- void ds_write_byte(unsigned char date) //寫一個字節(jié)
- {
- unsigned chari;
- for(i=0;i<8;i++)
- {
- dq_dr_sr=0;
- dq_dr_sr=date&0x01;
- delay_short(5);
- dq_dr_sr=1;
- date=date>>1;
- }
- }
- unsigned char ds_read_byte(void ) //讀一字節(jié)
- {
- unsigned char i;
- unsigned char date=0;
- for(i=0;i<8;i++)
- {
- dq_dr_sr=0;
- date=date>>1;
- dq_dr_sr=1;
- if(dq_dr_sr)
- {
- date=date|0x80;
- }
- delay_short(5);
- }
- return (date);
- }
- void display_service(void) //顯示的窗口菜單服務(wù)程序
- {
- switch(ucWd)//因?yàn)楸境绦蛑挥?個窗口,在實(shí)際項目中,此處的ucWd也可以省略不要
- {
- case 1:
- if(ucWd1Part1Update==1)//局部設(shè)定溫度更新顯示
- {
- ucWd1Part1Update=0;
- ucTemp8=10; //顯示空
- if(ulSetTemper>=100)
- {
- ucTemp7=ulSetTemper%1000/100; //顯示設(shè)定溫度的百位
- }
- else
- {
- ucTemp7=10; //顯示空
- }
- if(ulSetTemper>=10)
- {
- ucTemp6=ulSetTemper%100/10; //顯示設(shè)定溫度的十位
- }
- else
- {
- ucTemp6=10; //顯示空
- }
- ucTemp5=ulSetTemper%10; //顯示設(shè)定溫度的個位
- ucDigShow8=ucTemp8; //數(shù)碼管顯示實(shí)際內(nèi)容
- ucDigShow7=ucTemp7;
- ucDigShow6=ucTemp6;
- ucDigShow5=ucTemp5;
- }
- if(ucWd1Part2Update==1)//局部實(shí)際溫度更新顯示
- {
- if(ucSignFlag==0)//正數(shù)
- {
- ucTemp4=10; //顯示空
- }
- else//負(fù)數(shù),說明是零下多少度的情況下
- {
- ucTemp4=11; //顯示負(fù)號-
- }
- if(ulCurrentTemper>=100)
- {
- ucTemp3=ulCurrentTemper%100/100; //顯示實(shí)際溫度的百位
- }
- else
- {
- ucTemp3=10; //顯示空
- }
- if(ulCurrentTemper>=10)
- {
- ucTemp2=ulCurrentTemper%100/10;//顯示實(shí)際溫度的十位
- }
- else
- {
- ucTemp2=10;//顯示空
- }
- ucTemp1=ulCurrentTemper%10; //顯示實(shí)際溫度的個數(shù)位
- ucDigShow4=ucTemp4; //數(shù)碼管顯示實(shí)際內(nèi)容
- ucDigShow3=ucTemp3;
- ucDigShow2=ucTemp2;
- ucDigShow1=ucTemp1;
- }
- break;
- }
- }
- void key_scan(void)//按鍵掃描函數(shù) 放在定時中斷里
- {
- if(key_sr1==1)//IO是高電平,說明按鍵沒有被按下,這時要及時清零一些標(biāo)志位
- {
- ucKeyLock1=0; //按鍵自鎖標(biāo)志清零
- uiKeyTimeCnt1=0;//按鍵去抖動延時計數(shù)器清零,此行非常巧妙,是我實(shí)戰(zhàn)中摸索出來的。
- }
- else if(ucKeyLock1==0)//有按鍵按下,且是第一次被按下
- {
- uiKeyTimeCnt1++; //累加定時中斷次數(shù)
- if(uiKeyTimeCnt1>const_key_time1)
- {
- uiKeyTimeCnt1=0;
- ucKeyLock1=1;//自鎖按鍵置位,避免一直觸發(fā)
- ucKeySec=1; //觸發(fā)1號鍵
- }
- }
- if(key_sr2==1)//IO是高電平,說明按鍵沒有被按下,這時要及時清零一些標(biāo)志位
- {
- ucKeyLock2=0; //按鍵自鎖標(biāo)志清零
- uiKeyTimeCnt2=0;//按鍵去抖動延時計數(shù)器清零,此行非常巧妙,是我實(shí)戰(zhàn)中摸索出來的。
- }
- else if(ucKeyLock2==0)//有按鍵按下,且是第一次被按下
- {
- uiKeyTimeCnt2++; //累加定時中斷次數(shù)
- if(uiKeyTimeCnt2>const_key_time2)
- {
- uiKeyTimeCnt2=0;
- ucKeyLock2=1;//自鎖按鍵置位,避免一直觸發(fā)
- ucKeySec=2; //觸發(fā)2號鍵
- }
- }
- }
- void key_service(void) //按鍵服務(wù)的應(yīng)用程序
- {
- switch(ucKeySec) //按鍵服務(wù)狀態(tài)切換
- {
- case 1:// 加按鍵 對應(yīng)朱兆祺學(xué)習(xí)板的S1鍵
- switch(ucWd) //因?yàn)楸境绦蛑挥?個窗口,在實(shí)際項目中,此處的ucWd也可以省略不要
- {
- case 1: //在窗口1下設(shè)置設(shè)定溫度
- ulSetTemper++;
- if(ulSetTemper>125)
- {
- ulSetTemper=125;
- }
- ucWd1Part1Update=1; //更新顯示設(shè)定溫度
- break;
- }
- ucVoiceLock=1;//原子鎖加鎖,保護(hù)主函數(shù)與中斷函數(shù)的共享變量uiVoiceCnt
- uiVoiceCnt=const_voice_short; //按鍵聲音觸發(fā),滴一聲就停。
- ucVoiceLock=0;//原子鎖解鎖,保護(hù)主函數(shù)與中斷函數(shù)的共享變量uiVoiceCnt
- ucKeySec=0;//響應(yīng)按鍵服務(wù)處理程序后,按鍵編號清零,避免一致觸發(fā)
- break;
- case 2:// 減按鍵 對應(yīng)朱兆祺學(xué)習(xí)板的S5鍵
- switch(ucWd) //因?yàn)楸境绦蛑挥?個窗口,在實(shí)際項目中,此處的ucWd也可以省略不要
- {
- case 1: //在窗口1下設(shè)置設(shè)定溫度
- if(ulSetTemper>2)//由于緩沖溫差是2度,所以我人為規(guī)定最小允許設(shè)定的溫度不能低于2度
- {
- ulSetTemper--;
- }
- ucWd1Part1Update=1; //更新顯示設(shè)定溫度
- break;
- }
- ucVoiceLock=1;//原子鎖加鎖,保護(hù)主函數(shù)與中斷函數(shù)的共享變量uiVoiceCnt
- uiVoiceCnt=const_voice_short; //按鍵聲音觸發(fā),滴一聲就停。
- ucVoiceLock=0;//原子鎖解鎖,保護(hù)主函數(shù)與中斷函數(shù)的共享變量uiVoiceCnt
- ucKeySec=0;//響應(yīng)按鍵服務(wù)處理程序后,按鍵編號清零,避免一致觸發(fā)
- break;
- }
- }
- void display_drive(void)
- {
- //以下程序,如果加一些數(shù)組和移位的元素,還可以壓縮容量。但是鴻哥追求的不是容量,而是清晰的講解思路
- switch(ucDisplayDriveStep)
- {
- case 1://顯示第1位
- ucDigShowTemp=dig_table[ucDigShow1];
- if(ucDigDot1==1)
- {
- ucDigShowTemp=ucDigShowTemp|0x80;//顯示小數(shù)點(diǎn)
- }
- dig_hc595_drive(ucDigShowTemp,0xfe);
- break;
- case 2://顯示第2位
- ucDigShowTemp=dig_table[ucDigShow2];
- if(ucDigDot2==1)
- {
- ucDigShowTemp=ucDigShowTemp|0x80;//顯示小數(shù)點(diǎn)
- }
- dig_hc595_drive(ucDigShowTemp,0xfd);
- break;
- case 3://顯示第3位
- ucDigShowTemp=dig_table[ucDigShow3];
- if(ucDigDot3==1)
- {
- ucDigShowTemp=ucDigShowTemp|0x80;//顯示小數(shù)點(diǎn)
- }
- dig_hc595_drive(ucDigShowTemp,0xfb);
- break;
- case 4://顯示第4位
- ucDigShowTemp=dig_table[ucDigShow4];
- if(ucDigDot4==1)
- {
- ucDigShowTemp=ucDigShowTemp|0x80;//顯示小數(shù)點(diǎn)
- }
- dig_hc595_drive(ucDigShowTemp,0xf7);
- break;
- case 5://顯示第5位
- ucDigShowTemp=dig_table[ucDigShow5];
- if(ucDigDot5==1)
- {
- ucDigShowTemp=ucDigShowTemp|0x80;//顯示小數(shù)點(diǎn)
- }
- dig_hc595_drive(ucDigShowTemp,0xef);
- break;
- case 6://顯示第6位
- ucDigShowTemp=dig_table[ucDigShow6];
- if(ucDigDot6==1)
- {
- ucDigShowTemp=ucDigShowTemp|0x80;//顯示小數(shù)點(diǎn)
- }
- dig_hc595_drive(ucDigShowTemp,0xdf);
- break;
- case 7://顯示第7位
- ucDigShowTemp=dig_table[ucDigShow7];
- if(ucDigDot7==1)
- {
- ucDigShowTemp=ucDigShowTemp|0x80;//顯示小數(shù)點(diǎn)
- }
- dig_hc595_drive(ucDigShowTemp,0xbf);
- break;
- case 8://顯示第8位
- ucDigShowTemp=dig_table[ucDigShow8];
- if(ucDigDot8==1)
- {
- ucDigShowTemp=ucDigShowTemp|0x80;//顯示小數(shù)點(diǎn)
- }
- dig_hc595_drive(ucDigShowTemp,0x7f);
- break;
- }
- ucDisplayDriveStep++;
- if(ucDisplayDriveStep>8)//掃描完8個數(shù)碼管后,重新從第一個開始掃描
- {
- ucDisplayDriveStep=1;
- }
- }
- //數(shù)碼管的74HC595驅(qū)動函數(shù)
- void dig_hc595_drive(unsigned char ucDigStatusTemp16_09,unsigned char ucDigStatusTemp08_01)
- {
- unsigned char i;
- unsigned char ucTempData;
- dig_hc595_sh_dr=0;
- dig_hc595_st_dr=0;
- ucTempData=ucDigStatusTemp16_09;//先送高8位
- for(i=0;i<8;i++)
- {
- if(ucTempData>=0x80)dig_hc595_ds_dr=1;
- else dig_hc595_ds_dr=0;
- dig_hc595_sh_dr=0; //SH引腳的上升沿把數(shù)據(jù)送入寄存器
- delay_short(1);
- dig_hc595_sh_dr=1;
- delay_short(1);
- ucTempData=ucTempData<<1;
- }
- ucTempData=ucDigStatusTemp08_01;//再先送低8位
- for(i=0;i<8;i++)
- {
- if(ucTempData>=0x80)dig_hc595_ds_dr=1;
- else dig_hc595_ds_dr=0;
- dig_hc595_sh_dr=0; //SH引腳的上升沿把數(shù)據(jù)送入寄存器
- delay_short(1);
- dig_hc595_sh_dr=1;
- delay_short(1);
- ucTempData=ucTempData<<1;
- }
- dig_hc595_st_dr=0;//ST引腳把兩個寄存器的數(shù)據(jù)更新輸出到74HC595的輸出引腳上并且鎖存起來
- delay_short(1);
- dig_hc595_st_dr=1;
- delay_short(1);
- dig_hc595_sh_dr=0; //拉低,抗干擾就增強(qiáng)
- dig_hc595_st_dr=0;
- dig_hc595_ds_dr=0;
- }
- //LED燈的74HC595驅(qū)動函數(shù)
- void hc595_drive(unsigned char ucLedStatusTemp16_09,unsigned char ucLedStatusTemp08_01)
- {
- unsigned char i;
- unsigned char ucTempData;
- hc595_sh_dr=0;
- hc595_st_dr=0;
- ucTempData=ucLedStatusTemp16_09;//先送高8位
- for(i=0;i<8;i++)
- {
- if(ucTempData>=0x80)hc595_ds_dr=1;
- else hc595_ds_dr=0;
- hc595_sh_dr=0; //SH引腳的上升沿把數(shù)據(jù)送入寄存器
- delay_short(1);
- hc595_sh_dr=1;
- delay_short(1);
- ucTempData=ucTempData<<1;
- }
- ucTempData=ucLedStatusTemp08_01;//再先送低8位
- for(i=0;i<8;i++)
- {
- if(ucTempData>=0x80)hc595_ds_dr=1;
- else hc595_ds_dr=0;
- hc595_sh_dr=0; //SH引腳的上升沿把數(shù)據(jù)送入寄存器
- delay_short(1);
- hc595_sh_dr=1;
- delay_short(1);
- ucTempData=ucTempData<<1;
- }
- hc595_st_dr=0;//ST引腳把兩個寄存器的數(shù)據(jù)更新輸出到74HC595的輸出引腳上并且鎖存起來
- delay_short(1);
- hc595_st_dr=1;
- delay_short(1);
- hc595_sh_dr=0; //拉低,抗干擾就增強(qiáng)
- hc595_st_dr=0;
- hc595_ds_dr=0;
- }
- void T0_time(void) interrupt 1 //定時中斷
- {
- TF0=0;//清除中斷標(biāo)志
- TR0=0; //關(guān)中斷
- if(ucVoiceLock==0) //原子鎖判斷
- {
- if(uiVoiceCnt!=0)
- {
- uiVoiceCnt--; //每次進(jìn)入定時中斷都自減1,直到等于零為止。才停止鳴叫
- beep_dr=0;//蜂鳴器是PNP三極管控制,低電平就開始鳴叫。
- }
- else
- {
- ; //此處多加一個空指令,想維持跟if括號語句的數(shù)量對稱,都是兩條指令。不加也可以。
- beep_dr=1;//蜂鳴器是PNP三極管控制,高電平就停止鳴叫。
- }
- }
- key_scan(); //按鍵掃描函數(shù)
- display_drive();//數(shù)碼管字模的驅(qū)動函數(shù)
- TH0=0xfe; //重裝初始值(65535-500)=65035=0xfe0b
- TL0=0x0b;
- TR0=1;//開中斷
- }
- void delay_short(unsigned int uiDelayShort)
- {
- unsigned int i;
- for(i=0;i
- {
- ; //一個分號相當(dāng)于執(zhí)行一條空語句
- }
- }
- void delay_long(unsigned int uiDelayLong)
- {
- unsigned int i;
- unsigned int j;
- for(i=0;i
- {
- for(j=0;j<500;j++)//內(nèi)嵌循環(huán)的空指令數(shù)量
- {
- ; //一個分號相當(dāng)于執(zhí)行一條空語句
- }
- }
- }
- void initial_myself(void)//第一區(qū) 初始化單片機(jī)
- {
- led_dr=0;//此處的LED燈模擬工控中的繼電器
- key_gnd_dr=0; //模擬獨(dú)立按鍵的地GND,因此必須一直輸出低電平
- beep_dr=1; //用PNP三極管控制蜂鳴器,輸出高電平時不叫。
- hc595_drive(0x00,0x00);//關(guān)閉所有經(jīng)過另外兩個74HC595驅(qū)動的LED燈
- TMOD=0x01;//設(shè)置定時器0為工作方式1
- TH0=0xfe; //重裝初始值(65535-500)=65035=0xfe0b
- TL0=0x0b;
- }
- void initial_peripheral(void) //第二區(qū) 初始化外圍
- {
- ucDigDot8=0; //小數(shù)點(diǎn)全部不顯示
- ucDigDot7=0;
- ucDigDot6=0;
- ucDigDot5=0;
- ucDigDot4=0;
- ucDigDot3=0;
- ucDigDot2=0;
- ucDigDot1=0;
- EA=1; //開總中斷
- ET0=1; //允許定時中斷
- TR0=1; //啟動定時中斷
- }
總結(jié)陳詞:
下一節(jié)開始講單片機(jī)采集模擬信號的內(nèi)容,欲知詳情,請聽下回分解-----利用ADC0832采集電壓的模擬信號。
評論