新聞中心

EEPW首頁 > 嵌入式系統(tǒng) > 設(shè)計應(yīng)用 > 第49節(jié):利用DS18B20做一個溫控器

第49節(jié):利用DS18B20做一個溫控器

作者: 時間:2016-11-22 來源:網(wǎng)絡(luò) 收藏
開場白:
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)源代碼講解如下:
  1. #include "REG52.H"
  2. #define const_voice_short40 //蜂鳴器短叫的持續(xù)時間
  3. #define const_key_time120 //按鍵去抖動延時的時間
  4. #define const_key_time220 //按鍵去抖動延時的時間
  5. #define const_ds18b20_sampling_time 180 //累計主循環(huán)次數(shù)的時間,每次刷新采樣時鐘芯片的時間
  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. //驅(qū)動數(shù)碼管的74HC595
  11. void dig_hc595_drive(unsigned char ucDigStatusTemp16_09,unsigned char ucDigStatusTemp08_01);
  12. void display_drive(void); //顯示數(shù)碼管字模的驅(qū)動函數(shù)
  13. void display_service(void); //顯示的窗口菜單服務(wù)程序
  14. //驅(qū)動LED的74HC595
  15. void hc595_drive(unsigned char ucLedStatusTemp16_09,unsigned char ucLedStatusTemp08_01);
  16. void T0_time(void);//定時中斷函數(shù)
  17. void key_service(void); //按鍵服務(wù)的應(yīng)用程序
  18. void key_scan(void);//按鍵掃描函數(shù) 放在定時中斷里
  19. void temper_control_service(void); //溫控程序
  20. void ds18b20_sampling(void); //ds18b20采樣程序
  21. void ds18b20_reset(); //復(fù)位ds18b20的時序
  22. unsigned char ds_read_byte(void ); //讀一字節(jié)
  23. void ds_write_byte(unsigned char dat); //寫一個字節(jié)
  24. unsigned int get_temper();//讀取一次沒有經(jīng)過換算的溫度數(shù)值
  25. sbit dq_dr_sr=P2^6; //ds18b20的數(shù)據(jù)驅(qū)動線
  26. sbit key_sr1=P0^0; //對應(yīng)朱兆祺學(xué)習(xí)板的S1鍵
  27. sbit key_sr2=P0^1; //對應(yīng)朱兆祺學(xué)習(xí)板的S5鍵
  28. sbit led_dr=P3^5;//LED燈,模擬工控中的繼電器
  29. sbit key_gnd_dr=P0^4; //模擬獨(dú)立按鍵的地GND,因此必須一直輸出低電平
  30. sbit beep_dr=P2^7; //蜂鳴器的驅(qū)動IO口
  31. sbit dig_hc595_sh_dr=P2^0; //數(shù)碼管的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; //正負(fù)符號。0代表正數(shù),1代表負(fù)數(shù),表示零下多少度。
  39. unsigned long ulCurrentTemper=33; //實(shí)際溫度
  40. unsigned long ulSetTemper=26; //設(shè)定溫度
  41. unsigned int uiTemperTemp=0; //中間變量
  42. unsigned char ucKeySec=0; //被觸發(fā)的按鍵編號
  43. unsigned intuiKeyTimeCnt1=0; //按鍵去抖動延時計數(shù)器
  44. unsigned char ucKeyLock1=0; //按鍵觸發(fā)后自鎖的變量標(biāo)志
  45. unsigned intuiKeyTimeCnt2=0; //按鍵去抖動延時計數(shù)器
  46. unsigned char ucKeyLock2=0; //按鍵觸發(fā)后自鎖的變量標(biāo)志
  47. unsigned intuiVoiceCnt=0;//蜂鳴器鳴叫的持續(xù)時間計數(shù)器
  48. unsigned charucVoiceLock=0;//蜂鳴器鳴叫的原子鎖
  49. unsigned char ucDigShow8;//第8位數(shù)碼管要顯示的內(nèi)容
  50. unsigned char ucDigShow7;//第7位數(shù)碼管要顯示的內(nèi)容
  51. unsigned char ucDigShow6;//第6位數(shù)碼管要顯示的內(nèi)容
  52. unsigned char ucDigShow5;//第5位數(shù)碼管要顯示的內(nèi)容
  53. unsigned char ucDigShow4;//第4位數(shù)碼管要顯示的內(nèi)容
  54. unsigned char ucDigShow3;//第3位數(shù)碼管要顯示的內(nèi)容
  55. unsigned char ucDigShow2;//第2位數(shù)碼管要顯示的內(nèi)容
  56. unsigned char ucDigShow1;//第1位數(shù)碼管要顯示的內(nèi)容
  57. unsigned char ucDigDot8;//數(shù)碼管8的小數(shù)點(diǎn)是否顯示的標(biāo)志
  58. unsigned char ucDigDot7;//數(shù)碼管7的小數(shù)點(diǎn)是否顯示的標(biāo)志
  59. unsigned char ucDigDot6;//數(shù)碼管6的小數(shù)點(diǎn)是否顯示的標(biāo)志
  60. unsigned char ucDigDot5;//數(shù)碼管5的小數(shù)點(diǎn)是否顯示的標(biāo)志
  61. unsigned char ucDigDot4;//數(shù)碼管4的小數(shù)點(diǎn)是否顯示的標(biāo)志
  62. unsigned char ucDigDot3;//數(shù)碼管3的小數(shù)點(diǎn)是否顯示的標(biāo)志
  63. unsigned char ucDigDot2;//數(shù)碼管2的小數(shù)點(diǎn)是否顯示的標(biāo)志
  64. unsigned char ucDigDot1;//數(shù)碼管1的小數(shù)點(diǎn)是否顯示的標(biāo)志
  65. unsigned char ucDigShowTemp=0; //臨時中間變量
  66. unsigned char ucDisplayDriveStep=1;//動態(tài)掃描數(shù)碼管的步驟變量
  67. unsigned char ucWd=1;//因?yàn)楸境绦蛑挥?個窗口,在實(shí)際項目中,此處的ucWd也可以省略不要
  68. unsigned char ucWd1Part1Update=1;//在窗口1中,局部1的更新顯示標(biāo)志
  69. unsigned char ucWd1Part2Update=1; //在窗口1中,局部2的更新顯示標(biāo)志
  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. //根據(jù)原理圖得出的共陰數(shù)碼管字模表
  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(); //按鍵服務(wù)的應(yīng)用程序
  103. ds18b20_sampling(); //ds18b20采樣程序
  104. temper_control_service(); //溫控程序
  105. display_service(); //顯示的窗口菜單服務(wù)程序
  106. }
  107. }
  108. /* 注釋一:
  109. * 做溫控設(shè)備的時候,為了避免繼電器在臨界溫度附近頻繁跳動切換,應(yīng)該設(shè)置一個
  110. * 緩沖溫差。本程序的緩沖溫差是2度。
  111. */
  112. void temper_control_service(void) //溫控程序
  113. {
  114. if(ucSignFlag==0) //是正數(shù)的前提下
  115. {
  116. if(ulCurrentTemper>=ulSetTemper)//當(dāng)實(shí)際溫度大于等于設(shè)定溫度時
  117. {
  118. led_dr=0; //模擬繼電器的LED燈熄滅
  119. }
  120. else if(ulCurrentTemper<=(ulSetTemper-2))//當(dāng)實(shí)際溫度小于等于設(shè)定溫度2讀以下時,這里的2是緩沖溫差2度
  121. {
  122. led_dr=1; //模擬繼電器的LED燈點(diǎn)亮
  123. }
  124. }
  125. else//是負(fù)數(shù),說明是零下多少度的情況下
  126. {
  127. led_dr=1; //模擬繼電器的LED燈點(diǎn)亮
  128. }
  129. }
  130. void ds18b20_sampling(void) //ds18b20采樣程序
  131. {
  132. ++uiSampingCnt;//累計主循環(huán)次數(shù)的時間
  133. if(uiSampingCnt>const_ds18b20_sampling_time)//每隔一段時間就更新采集一次Ds18b20數(shù)據(jù)
  134. {
  135. uiSampingCnt=0;
  136. ET0=0;//禁止定時中斷
  137. uiTemperTemp=get_temper();//讀取一次沒有經(jīng)過換算的溫度數(shù)值
  138. ET0=1; //開啟定時中斷
  139. if((uiTemperTemp&0xf800)==0xf800) //是負(fù)號
  140. {
  141. ucSignFlag=1;
  142. uiTemperTemp=~uiTemperTemp;//求補(bǔ)碼
  143. uiTemperTemp=uiTemperTemp+1;
  144. }
  145. else //是正號
  146. {
  147. ucSignFlag=0;
  148. }
  149. ulCurrentTemper=0; //把int數(shù)據(jù)類型賦給long類型之前要先清零
  150. ulCurrentTemper=uiTemperTemp;
  151. ulCurrentTemper=ulCurrentTemper*10; //為了先保留一位小數(shù)點(diǎn),所以放大10倍,
  152. ulCurrentTemper=ulCurrentTemper>>4;//往右邊移動4位,相當(dāng)于乘以0.0625. 此時保留了1位小數(shù)點(diǎn),
  153. ulCurrentTemper=ulCurrentTemper+5;//四舍五入
  154. ulCurrentTemper=ulCurrentTemper/10; //四舍五入后,去掉小數(shù)點(diǎn)
  155. ucWd1Part2Update=1; //局部2更新顯示實(shí)時溫度
  156. }
  157. }
  158. //ds18b20驅(qū)動程序
  159. unsigned int get_temper()//讀取一次沒有經(jīng)過換算的溫度數(shù)值
  160. {
  161. unsigned char temper_H;
  162. unsigned char temper_L;
  163. unsigned int ds18b20_data=0;
  164. ds18b20_reset(); //復(fù)位ds18b20的時序
  165. ds_write_byte(0xCC);
  166. ds_write_byte(0x44);
  167. ds18b20_reset(); //復(fù)位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; //把兩個字節(jié)合并成一個int數(shù)據(jù)類型
  173. ds18b20_data=ds18b20_data<<8;
  174. ds18b20_data=ds18b20_data|temper_L;
  175. return ds18b20_data;
  176. }
  177. void ds18b20_reset() //復(fù)位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) //寫一個字節(jié)
  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 ) //讀一字節(jié)
  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) //顯示的窗口菜單服務(wù)程序
  219. {
  220. switch(ucWd)//因?yàn)楸境绦蛑挥?個窗口,在實(shí)際項目中,此處的ucWd也可以省略不要
  221. {
  222. case 1:
  223. if(ucWd1Part1Update==1)//局部設(shè)定溫度更新顯示
  224. {
  225. ucWd1Part1Update=0;
  226. ucTemp8=10; //顯示空
  227. if(ulSetTemper>=100)
  228. {
  229. ucTemp7=ulSetTemper%1000/100; //顯示設(shè)定溫度的百位
  230. }
  231. else
  232. {
  233. ucTemp7=10; //顯示空
  234. }
  235. if(ulSetTemper>=10)
  236. {
  237. ucTemp6=ulSetTemper%100/10; //顯示設(shè)定溫度的十位
  238. }
  239. else
  240. {
  241. ucTemp6=10; //顯示空
  242. }
  243. ucTemp5=ulSetTemper%10; //顯示設(shè)定溫度的個位
  244. ucDigShow8=ucTemp8; //數(shù)碼管顯示實(shí)際內(nèi)容
  245. ucDigShow7=ucTemp7;
  246. ucDigShow6=ucTemp6;
  247. ucDigShow5=ucTemp5;
  248. }
  249. if(ucWd1Part2Update==1)//局部實(shí)際溫度更新顯示
  250. {
  251. if(ucSignFlag==0)//正數(shù)
  252. {
  253. ucTemp4=10; //顯示空
  254. }
  255. else//負(fù)數(shù),說明是零下多少度的情況下
  256. {
  257. ucTemp4=11; //顯示負(fù)號-
  258. }
  259. if(ulCurrentTemper>=100)
  260. {
  261. ucTemp3=ulCurrentTemper%100/100; //顯示實(shí)際溫度的百位
  262. }
  263. else
  264. {
  265. ucTemp3=10; //顯示空
  266. }
  267. if(ulCurrentTemper>=10)
  268. {
  269. ucTemp2=ulCurrentTemper%100/10;//顯示實(shí)際溫度的十位
  270. }
  271. else
  272. {
  273. ucTemp2=10;//顯示空
  274. }
  275. ucTemp1=ulCurrentTemper%10; //顯示實(shí)際溫度的個數(shù)位
  276. ucDigShow4=ucTemp4; //數(shù)碼管顯示實(shí)際內(nèi)容
  277. ucDigShow3=ucTemp3;
  278. ucDigShow2=ucTemp2;
  279. ucDigShow1=ucTemp1;
  280. }
  281. break;
  282. }
  283. }
  284. void key_scan(void)//按鍵掃描函數(shù) 放在定時中斷里
  285. {
  286. if(key_sr1==1)//IO是高電平,說明按鍵沒有被按下,這時要及時清零一些標(biāo)志位
  287. {
  288. ucKeyLock1=0; //按鍵自鎖標(biāo)志清零
  289. uiKeyTimeCnt1=0;//按鍵去抖動延時計數(shù)器清零,此行非常巧妙,是我實(shí)戰(zhàn)中摸索出來的。
  290. }
  291. else if(ucKeyLock1==0)//有按鍵按下,且是第一次被按下
  292. {
  293. uiKeyTimeCnt1++; //累加定時中斷次數(shù)
  294. if(uiKeyTimeCnt1>const_key_time1)
  295. {
  296. uiKeyTimeCnt1=0;
  297. ucKeyLock1=1;//自鎖按鍵置位,避免一直觸發(fā)
  298. ucKeySec=1; //觸發(fā)1號鍵
  299. }
  300. }
  301. if(key_sr2==1)//IO是高電平,說明按鍵沒有被按下,這時要及時清零一些標(biāo)志位
  302. {
  303. ucKeyLock2=0; //按鍵自鎖標(biāo)志清零
  304. uiKeyTimeCnt2=0;//按鍵去抖動延時計數(shù)器清零,此行非常巧妙,是我實(shí)戰(zhàn)中摸索出來的。
  305. }
  306. else if(ucKeyLock2==0)//有按鍵按下,且是第一次被按下
  307. {
  308. uiKeyTimeCnt2++; //累加定時中斷次數(shù)
  309. if(uiKeyTimeCnt2>const_key_time2)
  310. {
  311. uiKeyTimeCnt2=0;
  312. ucKeyLock2=1;//自鎖按鍵置位,避免一直觸發(fā)
  313. ucKeySec=2; //觸發(fā)2號鍵
  314. }
  315. }
  316. }
  317. void key_service(void) //按鍵服務(wù)的應(yīng)用程序
  318. {
  319. switch(ucKeySec) //按鍵服務(wù)狀態(tài)切換
  320. {
  321. case 1:// 加按鍵 對應(yīng)朱兆祺學(xué)習(xí)板的S1鍵
  322. switch(ucWd) //因?yàn)楸境绦蛑挥?個窗口,在實(shí)際項目中,此處的ucWd也可以省略不要
  323. {
  324. case 1: //在窗口1下設(shè)置設(shè)定溫度
  325. ulSetTemper++;
  326. if(ulSetTemper>125)
  327. {
  328. ulSetTemper=125;
  329. }
  330. ucWd1Part1Update=1; //更新顯示設(shè)定溫度
  331. break;
  332. }
  333. ucVoiceLock=1;//原子鎖加鎖,保護(hù)主函數(shù)與中斷函數(shù)的共享變量uiVoiceCnt
  334. uiVoiceCnt=const_voice_short; //按鍵聲音觸發(fā),滴一聲就停。
  335. ucVoiceLock=0;//原子鎖解鎖,保護(hù)主函數(shù)與中斷函數(shù)的共享變量uiVoiceCnt
  336. ucKeySec=0;//響應(yīng)按鍵服務(wù)處理程序后,按鍵編號清零,避免一致觸發(fā)
  337. break;
  338. case 2:// 減按鍵 對應(yīng)朱兆祺學(xué)習(xí)板的S5鍵
  339. switch(ucWd) //因?yàn)楸境绦蛑挥?個窗口,在實(shí)際項目中,此處的ucWd也可以省略不要
  340. {
  341. case 1: //在窗口1下設(shè)置設(shè)定溫度
  342. if(ulSetTemper>2)//由于緩沖溫差是2度,所以我人為規(guī)定最小允許設(shè)定的溫度不能低于2度
  343. {
  344. ulSetTemper--;
  345. }
  346. ucWd1Part1Update=1; //更新顯示設(shè)定溫度
  347. break;
  348. }
  349. ucVoiceLock=1;//原子鎖加鎖,保護(hù)主函數(shù)與中斷函數(shù)的共享變量uiVoiceCnt
  350. uiVoiceCnt=const_voice_short; //按鍵聲音觸發(fā),滴一聲就停。
  351. ucVoiceLock=0;//原子鎖解鎖,保護(hù)主函數(shù)與中斷函數(shù)的共享變量uiVoiceCnt
  352. ucKeySec=0;//響應(yīng)按鍵服務(wù)處理程序后,按鍵編號清零,避免一致觸發(fā)
  353. break;
  354. }
  355. }
  356. void display_drive(void)
  357. {
  358. //以下程序,如果加一些數(shù)組和移位的元素,還可以壓縮容量。但是鴻哥追求的不是容量,而是清晰的講解思路
  359. switch(ucDisplayDriveStep)
  360. {
  361. case 1://顯示第1位
  362. ucDigShowTemp=dig_table[ucDigShow1];
  363. if(ucDigDot1==1)
  364. {
  365. ucDigShowTemp=ucDigShowTemp|0x80;//顯示小數(shù)點(diǎn)
  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;//顯示小數(shù)點(diǎn)
  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;//顯示小數(shù)點(diǎn)
  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;//顯示小數(shù)點(diǎn)
  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;//顯示小數(shù)點(diǎn)
  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;//顯示小數(shù)點(diǎn)
  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;//顯示小數(shù)點(diǎn)
  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;//顯示小數(shù)點(diǎn)
  422. }
  423. dig_hc595_drive(ucDigShowTemp,0x7f);
  424. break;
  425. }
  426. ucDisplayDriveStep++;
  427. if(ucDisplayDriveStep>8)//掃描完8個數(shù)碼管后,重新從第一個開始掃描
  428. {
  429. ucDisplayDriveStep=1;
  430. }
  431. }
  432. //數(shù)碼管的74HC595驅(qū)動函數(shù)
  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引腳的上升沿把數(shù)據(jù)送入寄存器
  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引腳的上升沿把數(shù)據(jù)送入寄存器
  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引腳把兩個寄存器的數(shù)據(jù)更新輸出到74HC595的輸出引腳上并且鎖存起來
  462. delay_short(1);
  463. dig_hc595_st_dr=1;
  464. delay_short(1);
  465. dig_hc595_sh_dr=0; //拉低,抗干擾就增強(qiáng)
  466. dig_hc595_st_dr=0;
  467. dig_hc595_ds_dr=0;
  468. }
  469. //LED燈的74HC595驅(qū)動函數(shù)
  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引腳的上升沿把數(shù)據(jù)送入寄存器
  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引腳的上升沿把數(shù)據(jù)送入寄存器
  493. delay_short(1);
  494. hc595_sh_dr=1;
  495. delay_short(1);
  496. ucTempData=ucTempData<<1;
  497. }
  498. hc595_st_dr=0;//ST引腳把兩個寄存器的數(shù)據(jù)更新輸出到74HC595的輸出引腳上并且鎖存起來
  499. delay_short(1);
  500. hc595_st_dr=1;
  501. delay_short(1);
  502. hc595_sh_dr=0; //拉低,抗干擾就增強(qiáng)
  503. hc595_st_dr=0;
  504. hc595_ds_dr=0;
  505. }
  506. void T0_time(void) interrupt 1 //定時中斷
  507. {
  508. TF0=0;//清除中斷標(biāo)志
  509. TR0=0; //關(guān)中斷
  510. if(ucVoiceLock==0) //原子鎖判斷
  511. {
  512. if(uiVoiceCnt!=0)
  513. {
  514. uiVoiceCnt--; //每次進(jìn)入定時中斷都自減1,直到等于零為止。才停止鳴叫
  515. beep_dr=0;//蜂鳴器是PNP三極管控制,低電平就開始鳴叫。
  516. }
  517. else
  518. {
  519. ; //此處多加一個空指令,想維持跟if括號語句的數(shù)量對稱,都是兩條指令。不加也可以。
  520. beep_dr=1;//蜂鳴器是PNP三極管控制,高電平就停止鳴叫。
  521. }
  522. }
  523. key_scan(); //按鍵掃描函數(shù)
  524. display_drive();//數(shù)碼管字模的驅(qū)動函數(shù)
  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. ; //一個分號相當(dāng)于執(zhí)行一條空語句
  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++)//內(nèi)嵌循環(huán)的空指令數(shù)量
  544. {
  545. ; //一個分號相當(dāng)于執(zhí)行一條空語句
  546. }
  547. }
  548. }
  549. void initial_myself(void)//第一區(qū) 初始化單片機(jī)
  550. {
  551. led_dr=0;//此處的LED燈模擬工控中的繼電器
  552. key_gnd_dr=0; //模擬獨(dú)立按鍵的地GND,因此必須一直輸出低電平
  553. beep_dr=1; //用PNP三極管控制蜂鳴器,輸出高電平時不叫。
  554. hc595_drive(0x00,0x00);//關(guān)閉所有經(jīng)過另外兩個74HC595驅(qū)動的LED燈
  555. TMOD=0x01;//設(shè)置定時器0為工作方式1
  556. TH0=0xfe; //重裝初始值(65535-500)=65035=0xfe0b
  557. TL0=0x0b;
  558. }
  559. void initial_peripheral(void) //第二區(qū) 初始化外圍
  560. {
  561. ucDigDot8=0; //小數(shù)點(diǎn)全部不顯示
  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. }

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


關(guān)鍵詞: DS18B20溫控

評論


技術(shù)專區(qū)

關(guān)閉