新聞中心

        EEPW首頁 > 嵌入式系統 > 設計應用 > 第49節:利用DS18B20做一個溫控器

        第49節:利用DS18B20做一個溫控器

        作者: 時間:2016-11-22 來源:網絡 收藏
        開場白:
        DS18B20是一款常用的溫度傳感器芯片,它只占用單片機一根IO口,使用起來也特別方便。需要特別注意的是,正因為它只用一根IO口跟單片機通訊,因此讀取一次溫度值的通訊時間比較長,而且時序要求嚴格,在通訊期間不允許被單片機其它的中斷干擾,因此在實際項目中,系統一旦選用了這款傳感器芯片,就千萬不要選用動態掃描數碼管的顯示方式。否則在關閉中斷讀取溫度的時候,數碼管的顯示會有略微的“閃爍”現象。
        DS18B20的測溫范圍是-55度至125度。在-10度至85度的溫度范圍內誤差是+-0.5度,能滿足大部分常用的測溫要求。
        這一節要教會大家三個知識點:
        第一個:大概了解一下DS18B20的驅動程序。
        第二個:做溫控設備的時候,為了避免繼電器在臨界溫度附近頻繁跳動切換,應該設置一個緩沖溫差。本程序的緩沖溫差是2度。
        第三個:繼續加深了解按鍵,顯示,傳感器它們三者是如何緊密關聯起來的程序框架。

        具體內容,請看源代碼講解。

        (1) 硬件平臺.
        基于朱兆祺51單片機學習板

        (2)實現功能:
        本程序只有1個窗口。這個窗口有2個局部顯示。
        第1個局部是第7,6,5位數碼管,顯示設定的溫度。
        第2個局部是第4,3,2,1位數碼管,顯示實際環境溫度。其中第4位數碼管顯示正負符號位。
        S1按鍵是加鍵,S5按鍵是減鍵。通過它們可以直接設置“設定溫度”。
        一個LED燈用來模擬工控的繼電器。
        當實際溫度低于或者等于設定溫度2度以下時,模擬繼電器的LED燈亮。
        當實際溫度等于或者大于設定溫度時,模擬繼電器的LED燈滅。
        當實際溫度處于設定溫度和設定溫度減去2度的范圍內,模擬繼電器的LED維持現狀,這個2度范圍用來做緩沖溫差,避免繼電器在臨界溫度附近頻繁跳動切換。

        (3)源代碼講解如下:
        1. #include "REG52.H"
        2. #define const_voice_short40 //蜂鳴器短叫的持續時間
        3. #define const_key_time120 //按鍵去抖動延時的時間
        4. #define const_key_time220 //按鍵去抖動延時的時間
        5. #define const_ds18b20_sampling_time 180 //累計主循環次數的時間,每次刷新采樣時鐘芯片的時間
        6. void initial_myself(void);
        7. void initial_peripheral(void);
        8. void delay_short(unsigned int uiDelayShort);
        9. void delay_long(unsigned int uiDelaylong);
        10. //驅動數碼管的74HC595
        11. void dig_hc595_drive(unsigned char ucDigStatusTemp16_09,unsigned char ucDigStatusTemp08_01);
        12. void display_drive(void); //顯示數碼管字模的驅動函數
        13. void display_service(void); //顯示的窗口菜單服務程序
        14. //驅動LED的74HC595
        15. void hc595_drive(unsigned char ucLedStatusTemp16_09,unsigned char ucLedStatusTemp08_01);
        16. void T0_time(void);//定時中斷函數
        17. void key_service(void); //按鍵服務的應用程序
        18. void key_scan(void);//按鍵掃描函數 放在定時中斷里
        19. void temper_control_service(void); //溫控程序
        20. void ds18b20_sampling(void); //ds18b20采樣程序
        21. void ds18b20_reset(); //復位ds18b20的時序
        22. unsigned char ds_read_byte(void ); //讀一字節
        23. void ds_write_byte(unsigned char dat); //寫一個字節
        24. unsigned int get_temper();//讀取一次沒有經過換算的溫度數值
        25. sbit dq_dr_sr=P2^6; //ds18b20的數據驅動線
        26. sbit key_sr1=P0^0; //對應朱兆祺學習板的S1鍵
        27. sbit key_sr2=P0^1; //對應朱兆祺學習板的S5鍵
        28. sbit led_dr=P3^5;//LED燈,模擬工控中的繼電器
        29. sbit key_gnd_dr=P0^4; //模擬獨立按鍵的地GND,因此必須一直輸出低電平
        30. sbit beep_dr=P2^7; //蜂鳴器的驅動IO口
        31. sbit dig_hc595_sh_dr=P2^0; //數碼管的74HC595程序
        32. sbit dig_hc595_st_dr=P2^1;
        33. sbit dig_hc595_ds_dr=P2^2;
        34. sbit hc595_sh_dr=P2^3; //LED燈的74HC595程序
        35. sbit hc595_st_dr=P2^4;
        36. sbit hc595_ds_dr=P2^5;
        37. unsigned int uiSampingCnt=0; //采集Ds1302的計時器,每秒鐘更新采集一次
        38. unsigned char ucSignFlag=0; //正負符號。0代表正數,1代表負數,表示零下多少度。
        39. unsigned long ulCurrentTemper=33; //實際溫度
        40. unsigned long ulSetTemper=26; //設定溫度
        41. unsigned int uiTemperTemp=0; //中間變量
        42. unsigned char ucKeySec=0; //被觸發的按鍵編號
        43. unsigned intuiKeyTimeCnt1=0; //按鍵去抖動延時計數器
        44. unsigned char ucKeyLock1=0; //按鍵觸發后自鎖的變量標志
        45. unsigned intuiKeyTimeCnt2=0; //按鍵去抖動延時計數器
        46. unsigned char ucKeyLock2=0; //按鍵觸發后自鎖的變量標志
        47. unsigned intuiVoiceCnt=0;//蜂鳴器鳴叫的持續時間計數器
        48. unsigned charucVoiceLock=0;//蜂鳴器鳴叫的原子鎖
        49. unsigned char ucDigShow8;//第8位數碼管要顯示的內容
        50. unsigned char ucDigShow7;//第7位數碼管要顯示的內容
        51. unsigned char ucDigShow6;//第6位數碼管要顯示的內容
        52. unsigned char ucDigShow5;//第5位數碼管要顯示的內容
        53. unsigned char ucDigShow4;//第4位數碼管要顯示的內容
        54. unsigned char ucDigShow3;//第3位數碼管要顯示的內容
        55. unsigned char ucDigShow2;//第2位數碼管要顯示的內容
        56. unsigned char ucDigShow1;//第1位數碼管要顯示的內容
        57. unsigned char ucDigDot8;//數碼管8的小數點是否顯示的標志
        58. unsigned char ucDigDot7;//數碼管7的小數點是否顯示的標志
        59. unsigned char ucDigDot6;//數碼管6的小數點是否顯示的標志
        60. unsigned char ucDigDot5;//數碼管5的小數點是否顯示的標志
        61. unsigned char ucDigDot4;//數碼管4的小數點是否顯示的標志
        62. unsigned char ucDigDot3;//數碼管3的小數點是否顯示的標志
        63. unsigned char ucDigDot2;//數碼管2的小數點是否顯示的標志
        64. unsigned char ucDigDot1;//數碼管1的小數點是否顯示的標志
        65. unsigned char ucDigShowTemp=0; //臨時中間變量
        66. unsigned char ucDisplayDriveStep=1;//動態掃描數碼管的步驟變量
        67. unsigned char ucWd=1;//因為本程序只有1個窗口,在實際項目中,此處的ucWd也可以省略不要
        68. unsigned char ucWd1Part1Update=1;//在窗口1中,局部1的更新顯示標志
        69. unsigned char ucWd1Part2Update=1; //在窗口1中,局部2的更新顯示標志
        70. unsigned char ucTemp1=0;//中間過渡變量
        71. unsigned char ucTemp2=0;//中間過渡變量
        72. unsigned char ucTemp3=0;//中間過渡變量
        73. unsigned char ucTemp4=0;//中間過渡變量
        74. unsigned char ucTemp5=0;//中間過渡變量
        75. unsigned char ucTemp6=0;//中間過渡變量
        76. unsigned char ucTemp7=0;//中間過渡變量
        77. unsigned char ucTemp8=0;//中間過渡變量
        78. //根據原理圖得出的共陰數碼管字模表
        79. code unsigned char dig_table[]=
        80. {
        81. 0x3f,//0 序號0
        82. 0x06,//1 序號1
        83. 0x5b,//2 序號2
        84. 0x4f,//3 序號3
        85. 0x66,//4 序號4
        86. 0x6d,//5 序號5
        87. 0x7d,//6 序號6
        88. 0x07,//7 序號7
        89. 0x7f,//8 序號8
        90. 0x6f,//9 序號9
        91. 0x00,//無 序號10
        92. 0x40,//- 序號11
        93. 0x73,//P 序號12
        94. };
        95. void main()
        96. {
        97. initial_myself();
        98. delay_long(100);
        99. initial_peripheral();
        100. while(1)
        101. {
        102. key_service(); //按鍵服務的應用程序
        103. ds18b20_sampling(); //ds18b20采樣程序
        104. temper_control_service(); //溫控程序
        105. display_service(); //顯示的窗口菜單服務程序
        106. }
        107. }
        108. /* 注釋一:
        109. * 做溫控設備的時候,為了避免繼電器在臨界溫度附近頻繁跳動切換,應該設置一個
        110. * 緩沖溫差。本程序的緩沖溫差是2度。
        111. */
        112. void temper_control_service(void) //溫控程序
        113. {
        114. if(ucSignFlag==0) //是正數的前提下
        115. {
        116. if(ulCurrentTemper>=ulSetTemper)//當實際溫度大于等于設定溫度時
        117. {
        118. led_dr=0; //模擬繼電器的LED燈熄滅
        119. }
        120. else if(ulCurrentTemper<=(ulSetTemper-2))//當實際溫度小于等于設定溫度2讀以下時,這里的2是緩沖溫差2度
        121. {
        122. led_dr=1; //模擬繼電器的LED燈點亮
        123. }
        124. }
        125. else//是負數,說明是零下多少度的情況下
        126. {
        127. led_dr=1; //模擬繼電器的LED燈點亮
        128. }
        129. }
        130. void ds18b20_sampling(void) //ds18b20采樣程序
        131. {
        132. ++uiSampingCnt;//累計主循環次數的時間
        133. if(uiSampingCnt>const_ds18b20_sampling_time)//每隔一段時間就更新采集一次Ds18b20數據
        134. {
        135. uiSampingCnt=0;
        136. ET0=0;//禁止定時中斷
        137. uiTemperTemp=get_temper();//讀取一次沒有經過換算的溫度數值
        138. ET0=1; //開啟定時中斷
        139. if((uiTemperTemp&0xf800)==0xf800) //是負號
        140. {
        141. ucSignFlag=1;
        142. uiTemperTemp=~uiTemperTemp;//求補碼
        143. uiTemperTemp=uiTemperTemp+1;
        144. }
        145. else //是正號
        146. {
        147. ucSignFlag=0;
        148. }
        149. ulCurrentTemper=0; //把int數據類型賦給long類型之前要先清零
        150. ulCurrentTemper=uiTemperTemp;
        151. ulCurrentTemper=ulCurrentTemper*10; //為了先保留一位小數點,所以放大10倍,
        152. ulCurrentTemper=ulCurrentTemper>>4;//往右邊移動4位,相當于乘以0.0625. 此時保留了1位小數點,
        153. ulCurrentTemper=ulCurrentTemper+5;//四舍五入
        154. ulCurrentTemper=ulCurrentTemper/10; //四舍五入后,去掉小數點
        155. ucWd1Part2Update=1; //局部2更新顯示實時溫度
        156. }
        157. }
        158. //ds18b20驅動程序
        159. unsigned int get_temper()//讀取一次沒有經過換算的溫度數值
        160. {
        161. unsigned char temper_H;
        162. unsigned char temper_L;
        163. unsigned int ds18b20_data=0;
        164. ds18b20_reset(); //復位ds18b20的時序
        165. ds_write_byte(0xCC);
        166. ds_write_byte(0x44);
        167. ds18b20_reset(); //復位ds18b20的時序
        168. ds_write_byte(0xCC);
        169. ds_write_byte(0xBE);
        170. temper_L=ds_read_byte();
        171. temper_H=ds_read_byte();
        172. ds18b20_data=temper_H; //把兩個字節合并成一個int數據類型
        173. ds18b20_data=ds18b20_data<<8;
        174. ds18b20_data=ds18b20_data|temper_L;
        175. return ds18b20_data;
        176. }
        177. void ds18b20_reset() //復位ds18b20的時序
        178. {
        179. unsigned char x;
        180. dq_dr_sr=1;
        181. delay_short(8);
        182. dq_dr_sr=0;
        183. delay_short(80);
        184. dq_dr_sr=1;
        185. delay_short(14);
        186. x=dq_dr_sr;
        187. delay_short(20);
        188. }
        189. void ds_write_byte(unsigned char date) //寫一個字節
        190. {
        191. unsigned chari;
        192. for(i=0;i<8;i++)
        193. {
        194. dq_dr_sr=0;
        195. dq_dr_sr=date&0x01;
        196. delay_short(5);
        197. dq_dr_sr=1;
        198. date=date>>1;
        199. }
        200. }
        201. unsigned char ds_read_byte(void ) //讀一字節
        202. {
        203. unsigned char i;
        204. unsigned char date=0;
        205. for(i=0;i<8;i++)
        206. {
        207. dq_dr_sr=0;
        208. date=date>>1;
        209. dq_dr_sr=1;
        210. if(dq_dr_sr)
        211. {
        212. date=date|0x80;
        213. }
        214. delay_short(5);
        215. }
        216. return (date);
        217. }
        218. void display_service(void) //顯示的窗口菜單服務程序
        219. {
        220. switch(ucWd)//因為本程序只有1個窗口,在實際項目中,此處的ucWd也可以省略不要
        221. {
        222. case 1:
        223. if(ucWd1Part1Update==1)//局部設定溫度更新顯示
        224. {
        225. ucWd1Part1Update=0;
        226. ucTemp8=10; //顯示空
        227. if(ulSetTemper>=100)
        228. {
        229. ucTemp7=ulSetTemper%1000/100; //顯示設定溫度的百位
        230. }
        231. else
        232. {
        233. ucTemp7=10; //顯示空
        234. }
        235. if(ulSetTemper>=10)
        236. {
        237. ucTemp6=ulSetTemper%100/10; //顯示設定溫度的十位
        238. }
        239. else
        240. {
        241. ucTemp6=10; //顯示空
        242. }
        243. ucTemp5=ulSetTemper%10; //顯示設定溫度的個位
        244. ucDigShow8=ucTemp8; //數碼管顯示實際內容
        245. ucDigShow7=ucTemp7;
        246. ucDigShow6=ucTemp6;
        247. ucDigShow5=ucTemp5;
        248. }
        249. if(ucWd1Part2Update==1)//局部實際溫度更新顯示
        250. {
        251. if(ucSignFlag==0)//正數
        252. {
        253. ucTemp4=10; //顯示空
        254. }
        255. else//負數,說明是零下多少度的情況下
        256. {
        257. ucTemp4=11; //顯示負號-
        258. }
        259. if(ulCurrentTemper>=100)
        260. {
        261. ucTemp3=ulCurrentTemper%100/100; //顯示實際溫度的百位
        262. }
        263. else
        264. {
        265. ucTemp3=10; //顯示空
        266. }
        267. if(ulCurrentTemper>=10)
        268. {
        269. ucTemp2=ulCurrentTemper%100/10;//顯示實際溫度的十位
        270. }
        271. else
        272. {
        273. ucTemp2=10;//顯示空
        274. }
        275. ucTemp1=ulCurrentTemper%10; //顯示實際溫度的個數位
        276. ucDigShow4=ucTemp4; //數碼管顯示實際內容
        277. ucDigShow3=ucTemp3;
        278. ucDigShow2=ucTemp2;
        279. ucDigShow1=ucTemp1;
        280. }
        281. break;
        282. }
        283. }
        284. void key_scan(void)//按鍵掃描函數 放在定時中斷里
        285. {
        286. if(key_sr1==1)//IO是高電平,說明按鍵沒有被按下,這時要及時清零一些標志位
        287. {
        288. ucKeyLock1=0; //按鍵自鎖標志清零
        289. uiKeyTimeCnt1=0;//按鍵去抖動延時計數器清零,此行非常巧妙,是我實戰中摸索出來的。
        290. }
        291. else if(ucKeyLock1==0)//有按鍵按下,且是第一次被按下
        292. {
        293. uiKeyTimeCnt1++; //累加定時中斷次數
        294. if(uiKeyTimeCnt1>const_key_time1)
        295. {
        296. uiKeyTimeCnt1=0;
        297. ucKeyLock1=1;//自鎖按鍵置位,避免一直觸發
        298. ucKeySec=1; //觸發1號鍵
        299. }
        300. }
        301. if(key_sr2==1)//IO是高電平,說明按鍵沒有被按下,這時要及時清零一些標志位
        302. {
        303. ucKeyLock2=0; //按鍵自鎖標志清零
        304. uiKeyTimeCnt2=0;//按鍵去抖動延時計數器清零,此行非常巧妙,是我實戰中摸索出來的。
        305. }
        306. else if(ucKeyLock2==0)//有按鍵按下,且是第一次被按下
        307. {
        308. uiKeyTimeCnt2++; //累加定時中斷次數
        309. if(uiKeyTimeCnt2>const_key_time2)
        310. {
        311. uiKeyTimeCnt2=0;
        312. ucKeyLock2=1;//自鎖按鍵置位,避免一直觸發
        313. ucKeySec=2; //觸發2號鍵
        314. }
        315. }
        316. }
        317. void key_service(void) //按鍵服務的應用程序
        318. {
        319. switch(ucKeySec) //按鍵服務狀態切換
        320. {
        321. case 1:// 加按鍵 對應朱兆祺學習板的S1鍵
        322. switch(ucWd) //因為本程序只有1個窗口,在實際項目中,此處的ucWd也可以省略不要
        323. {
        324. case 1: //在窗口1下設置設定溫度
        325. ulSetTemper++;
        326. if(ulSetTemper>125)
        327. {
        328. ulSetTemper=125;
        329. }
        330. ucWd1Part1Update=1; //更新顯示設定溫度
        331. break;
        332. }
        333. ucVoiceLock=1;//原子鎖加鎖,保護主函數與中斷函數的共享變量uiVoiceCnt
        334. uiVoiceCnt=const_voice_short; //按鍵聲音觸發,滴一聲就停。
        335. ucVoiceLock=0;//原子鎖解鎖,保護主函數與中斷函數的共享變量uiVoiceCnt
        336. ucKeySec=0;//響應按鍵服務處理程序后,按鍵編號清零,避免一致觸發
        337. break;
        338. case 2:// 減按鍵 對應朱兆祺學習板的S5鍵
        339. switch(ucWd) //因為本程序只有1個窗口,在實際項目中,此處的ucWd也可以省略不要
        340. {
        341. case 1: //在窗口1下設置設定溫度
        342. if(ulSetTemper>2)//由于緩沖溫差是2度,所以我人為規定最小允許設定的溫度不能低于2度
        343. {
        344. ulSetTemper--;
        345. }
        346. ucWd1Part1Update=1; //更新顯示設定溫度
        347. break;
        348. }
        349. ucVoiceLock=1;//原子鎖加鎖,保護主函數與中斷函數的共享變量uiVoiceCnt
        350. uiVoiceCnt=const_voice_short; //按鍵聲音觸發,滴一聲就停。
        351. ucVoiceLock=0;//原子鎖解鎖,保護主函數與中斷函數的共享變量uiVoiceCnt
        352. ucKeySec=0;//響應按鍵服務處理程序后,按鍵編號清零,避免一致觸發
        353. break;
        354. }
        355. }
        356. void display_drive(void)
        357. {
        358. //以下程序,如果加一些數組和移位的元素,還可以壓縮容量。但是鴻哥追求的不是容量,而是清晰的講解思路
        359. switch(ucDisplayDriveStep)
        360. {
        361. case 1://顯示第1位
        362. ucDigShowTemp=dig_table[ucDigShow1];
        363. if(ucDigDot1==1)
        364. {
        365. ucDigShowTemp=ucDigShowTemp|0x80;//顯示小數點
        366. }
        367. dig_hc595_drive(ucDigShowTemp,0xfe);
        368. break;
        369. case 2://顯示第2位
        370. ucDigShowTemp=dig_table[ucDigShow2];
        371. if(ucDigDot2==1)
        372. {
        373. ucDigShowTemp=ucDigShowTemp|0x80;//顯示小數點
        374. }
        375. dig_hc595_drive(ucDigShowTemp,0xfd);
        376. break;
        377. case 3://顯示第3位
        378. ucDigShowTemp=dig_table[ucDigShow3];
        379. if(ucDigDot3==1)
        380. {
        381. ucDigShowTemp=ucDigShowTemp|0x80;//顯示小數點
        382. }
        383. dig_hc595_drive(ucDigShowTemp,0xfb);
        384. break;
        385. case 4://顯示第4位
        386. ucDigShowTemp=dig_table[ucDigShow4];
        387. if(ucDigDot4==1)
        388. {
        389. ucDigShowTemp=ucDigShowTemp|0x80;//顯示小數點
        390. }
        391. dig_hc595_drive(ucDigShowTemp,0xf7);
        392. break;
        393. case 5://顯示第5位
        394. ucDigShowTemp=dig_table[ucDigShow5];
        395. if(ucDigDot5==1)
        396. {
        397. ucDigShowTemp=ucDigShowTemp|0x80;//顯示小數點
        398. }
        399. dig_hc595_drive(ucDigShowTemp,0xef);
        400. break;
        401. case 6://顯示第6位
        402. ucDigShowTemp=dig_table[ucDigShow6];
        403. if(ucDigDot6==1)
        404. {
        405. ucDigShowTemp=ucDigShowTemp|0x80;//顯示小數點
        406. }
        407. dig_hc595_drive(ucDigShowTemp,0xdf);
        408. break;
        409. case 7://顯示第7位
        410. ucDigShowTemp=dig_table[ucDigShow7];
        411. if(ucDigDot7==1)
        412. {
        413. ucDigShowTemp=ucDigShowTemp|0x80;//顯示小數點
        414. }
        415. dig_hc595_drive(ucDigShowTemp,0xbf);
        416. break;
        417. case 8://顯示第8位
        418. ucDigShowTemp=dig_table[ucDigShow8];
        419. if(ucDigDot8==1)
        420. {
        421. ucDigShowTemp=ucDigShowTemp|0x80;//顯示小數點
        422. }
        423. dig_hc595_drive(ucDigShowTemp,0x7f);
        424. break;
        425. }
        426. ucDisplayDriveStep++;
        427. if(ucDisplayDriveStep>8)//掃描完8個數碼管后,重新從第一個開始掃描
        428. {
        429. ucDisplayDriveStep=1;
        430. }
        431. }
        432. //數碼管的74HC595驅動函數
        433. void dig_hc595_drive(unsigned char ucDigStatusTemp16_09,unsigned char ucDigStatusTemp08_01)
        434. {
        435. unsigned char i;
        436. unsigned char ucTempData;
        437. dig_hc595_sh_dr=0;
        438. dig_hc595_st_dr=0;
        439. ucTempData=ucDigStatusTemp16_09;//先送高8位
        440. for(i=0;i<8;i++)
        441. {
        442. if(ucTempData>=0x80)dig_hc595_ds_dr=1;
        443. else dig_hc595_ds_dr=0;
        444. dig_hc595_sh_dr=0; //SH引腳的上升沿把數據送入寄存器
        445. delay_short(1);
        446. dig_hc595_sh_dr=1;
        447. delay_short(1);
        448. ucTempData=ucTempData<<1;
        449. }
        450. ucTempData=ucDigStatusTemp08_01;//再先送低8位
        451. for(i=0;i<8;i++)
        452. {
        453. if(ucTempData>=0x80)dig_hc595_ds_dr=1;
        454. else dig_hc595_ds_dr=0;
        455. dig_hc595_sh_dr=0; //SH引腳的上升沿把數據送入寄存器
        456. delay_short(1);
        457. dig_hc595_sh_dr=1;
        458. delay_short(1);
        459. ucTempData=ucTempData<<1;
        460. }
        461. dig_hc595_st_dr=0;//ST引腳把兩個寄存器的數據更新輸出到74HC595的輸出引腳上并且鎖存起來
        462. delay_short(1);
        463. dig_hc595_st_dr=1;
        464. delay_short(1);
        465. dig_hc595_sh_dr=0; //拉低,抗干擾就增強
        466. dig_hc595_st_dr=0;
        467. dig_hc595_ds_dr=0;
        468. }
        469. //LED燈的74HC595驅動函數
        470. void hc595_drive(unsigned char ucLedStatusTemp16_09,unsigned char ucLedStatusTemp08_01)
        471. {
        472. unsigned char i;
        473. unsigned char ucTempData;
        474. hc595_sh_dr=0;
        475. hc595_st_dr=0;
        476. ucTempData=ucLedStatusTemp16_09;//先送高8位
        477. for(i=0;i<8;i++)
        478. {
        479. if(ucTempData>=0x80)hc595_ds_dr=1;
        480. else hc595_ds_dr=0;
        481. hc595_sh_dr=0; //SH引腳的上升沿把數據送入寄存器
        482. delay_short(1);
        483. hc595_sh_dr=1;
        484. delay_short(1);
        485. ucTempData=ucTempData<<1;
        486. }
        487. ucTempData=ucLedStatusTemp08_01;//再先送低8位
        488. for(i=0;i<8;i++)
        489. {
        490. if(ucTempData>=0x80)hc595_ds_dr=1;
        491. else hc595_ds_dr=0;
        492. hc595_sh_dr=0; //SH引腳的上升沿把數據送入寄存器
        493. delay_short(1);
        494. hc595_sh_dr=1;
        495. delay_short(1);
        496. ucTempData=ucTempData<<1;
        497. }
        498. hc595_st_dr=0;//ST引腳把兩個寄存器的數據更新輸出到74HC595的輸出引腳上并且鎖存起來
        499. delay_short(1);
        500. hc595_st_dr=1;
        501. delay_short(1);
        502. hc595_sh_dr=0; //拉低,抗干擾就增強
        503. hc595_st_dr=0;
        504. hc595_ds_dr=0;
        505. }
        506. void T0_time(void) interrupt 1 //定時中斷
        507. {
        508. TF0=0;//清除中斷標志
        509. TR0=0; //關中斷
        510. if(ucVoiceLock==0) //原子鎖判斷
        511. {
        512. if(uiVoiceCnt!=0)
        513. {
        514. uiVoiceCnt--; //每次進入定時中斷都自減1,直到等于零為止。才停止鳴叫
        515. beep_dr=0;//蜂鳴器是PNP三極管控制,低電平就開始鳴叫。
        516. }
        517. else
        518. {
        519. ; //此處多加一個空指令,想維持跟if括號語句的數量對稱,都是兩條指令。不加也可以。
        520. beep_dr=1;//蜂鳴器是PNP三極管控制,高電平就停止鳴叫。
        521. }
        522. }
        523. key_scan(); //按鍵掃描函數
        524. display_drive();//數碼管字模的驅動函數
        525. TH0=0xfe; //重裝初始值(65535-500)=65035=0xfe0b
        526. TL0=0x0b;
        527. TR0=1;//開中斷
        528. }
        529. void delay_short(unsigned int uiDelayShort)
        530. {
        531. unsigned int i;
        532. for(i=0;i
        533. {
        534. ; //一個分號相當于執行一條空語句
        535. }
        536. }
        537. void delay_long(unsigned int uiDelayLong)
        538. {
        539. unsigned int i;
        540. unsigned int j;
        541. for(i=0;i
        542. {
        543. for(j=0;j<500;j++)//內嵌循環的空指令數量
        544. {
        545. ; //一個分號相當于執行一條空語句
        546. }
        547. }
        548. }
        549. void initial_myself(void)//第一區 初始化單片機
        550. {
        551. led_dr=0;//此處的LED燈模擬工控中的繼電器
        552. key_gnd_dr=0; //模擬獨立按鍵的地GND,因此必須一直輸出低電平
        553. beep_dr=1; //用PNP三極管控制蜂鳴器,輸出高電平時不叫。
        554. hc595_drive(0x00,0x00);//關閉所有經過另外兩個74HC595驅動的LED燈
        555. TMOD=0x01;//設置定時器0為工作方式1
        556. TH0=0xfe; //重裝初始值(65535-500)=65035=0xfe0b
        557. TL0=0x0b;
        558. }
        559. void initial_peripheral(void) //第二區 初始化外圍
        560. {
        561. ucDigDot8=0; //小數點全部不顯示
        562. ucDigDot7=0;
        563. ucDigDot6=0;
        564. ucDigDot5=0;
        565. ucDigDot4=0;
        566. ucDigDot3=0;
        567. ucDigDot2=0;
        568. ucDigDot1=0;
        569. EA=1; //開總中斷
        570. ET0=1; //允許定時中斷
        571. TR0=1; //啟動定時中斷
        572. }

        總結陳詞:
        下一節開始講單片機采集模擬信號的內容,欲知詳情,請聽下回分解-----利用ADC0832采集電壓的模擬信號。


        關鍵詞: DS18B20溫控

        評論


        技術專區

        關閉
        主站蜘蛛池模板: 灵宝市| 乌恰县| 肥城市| 二连浩特市| 收藏| 乐昌市| 曲周县| 阆中市| 长兴县| 北川| 日照市| 年辖:市辖区| 南澳县| 曲靖市| 刚察县| 大厂| 水富县| 南涧| 托克逊县| 梅河口市| 邢台市| 镇安县| 紫金县| 南部县| 南丰县| 方山县| 岚皋县| 洛宁县| 丽水市| 墨江| 万山特区| 宜宾县| 承德市| 横峰县| 麦盖提县| 文昌市| 三江| 河西区| 镇远县| 鸡东县| 卢氏县|