找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 5350|回復: 2
收起左側

單片機熱水鍋爐自動溫度控制系統(tǒng)(C51)

[復制鏈接]
ID:104835 發(fā)表于 2016-2-3 22:52 | 顯示全部樓層 |閱讀模式


  為好朋友東東設計了個單片機熱水鍋爐自動溫度控制系統(tǒng)。因為他家的熱水鍋爐因溫度太低,沒及時加熱,爆過幾 次。也有因加熱過頭,燒干水,化了管子。東東很快做好了實物,程序得到驗證,兩人皆大歡喜。
1.下限5°C時加熱器加熱,上限40°C時停止。溫度下降,直到下限時重新加熱。
2.溫度70°C時冷卻水泵工作,溫度降到45°C時停止。下次仍為70°C時水泵工作。
3.加熱/水泵 按鈕可切換切換加熱器和冷卻泵的設定及顯示(HTR為加熱器,CTP為冷卻水泵)。

程序中對兩組上下限設定做成可調的,方便實際使用中對上下限的細調。


E:\DPJ_C\18B20LCD\DD2\18B20DD2.C
  1. //2012 05 04
  2. #include<reg51.h>
  3. #include<intrins.h>
  4. #define uchar unsigned char
  5. #define uint unsigned int
  6. sbit RS=P2^0;
  7. sbit RW=P2^1;
  8. sbit E=P2^2;
  9. sbit BF=P0^7;
  10. sbit DQ=P3^3;
  11. sbit KEY0=P1^0;
  12. sbit KEY1=P1^1;
  13. sbit KEY2=P1^2;
  14. sbit KEY3=P1^3;
  15. sbit HTR=P1^4; //加熱器
  16. sbit CTP=P1^5; //冷卻泵
  17. uchar h_TH=40,h_TL=5,p_TH=70,p_TL=45;

  18. uchar code digit[12]={"0123456789- "};
  19. uchar code digit1[15]={"011233445677889"};
  20. uchar code digit2[16]={"0112234456677889"};
  21. uchar code Now[]={"Now:"};
  22. uchar code TH[]={"TH"};
  23. uchar code TL[]={"TL"};
  24. uchar code Cent[]={0xdf,0x43}; //溫度單位℃
  25. bit flag1,flag2,flag3; //flag1溫度為負的標志 flag2電熱標志 flag3 水泵標志

  26. /*****************************************************
  27. us 延時子函數
  28. ***************************************************/
  29. void ds18b20_delay(uchar us)
  30. {
  31. while(us--);
  32. }

  33. /*****************************************************
  34. ms 延時子函數

  35. ***************************************************/
  36. void delay(uint ms)
  37. {
  38. uchar i;
  39. while(ms--)
  40. for(i=0;i<123;i++);
  41. }

  42. /*****************************************************
  43. 判斷液晶模塊的忙碌狀態(tài)

  44. ***************************************************/
  45. bit BusyTest()
  46. {
  47. bit result;
  48. RS=0;
  49. RW=1;
  50. E=1;
  51. _nop_();
  52. _nop_();
  53. _nop_();
  54. _nop_(); //空操作四個機器周期,給硬件反應時間
  55. result=BF;
  56. E=0; //將E恢復低電平
  57. return result;
  58. }
  59. /*****************************************************
  60. 將模式設置指令或顯示地址寫入液晶模塊

  61. ***************************************************/
  62. void WriteCmd (uchar dictate)
  63. {
  64. while(BusyTest()==1); //如果忙就等待
  65. RS=0;
  66. RW=0;
  67. E=0;
  68. _nop_();
  69. _nop_(); //空操作兩個機器周期,給硬件反應時間
  70. P0=dictate;
  71. _nop_();
  72. _nop_();
  73. _nop_();
  74. _nop_(); //空操作四個機器周期,給硬件反應時間
  75. E=1;
  76. _nop_();
  77. _nop_();
  78. _nop_();
  79. _nop_();
  80. E=0;
  81. }
  82. /*****************************************************
  83. 函數功能:指定字符顯示的實際地址
  84. 入口參數:x
  85. ***************************************************/
  86. void WriteAdd(uchar x)
  87. {
  88. WriteCmd(x|0x80); //顯示位置的確定方法規(guī)定為"80H+地址碼x"
  89. }
  90. /*****************************************************
  91. 將數據(字符的標準ASCII碼)寫入液晶模塊

  92. ***************************************************/
  93. void WriteData(uchar y)
  94. {
  95. while(BusyTest()==1);
  96. RS=1; //RS為高電平,RW為低電平時,可以寫入數據
  97. RW=0;
  98. E=0; //E置低電平(根據表8-6,寫指令時,E為高脈沖,
  99. // 就是讓E從0到1發(fā)生正跳變,所以應先置"0"
  100. P0=y; //將數據送入P0口,即將數據寫入液晶模塊
  101. _nop_();
  102. _nop_();
  103. _nop_();
  104. _nop_(); //空操作四個機器周期,給硬件反應時間
  105. E=1; //E置高電平
  106. _nop_();
  107. _nop_();
  108. _nop_();
  109. _nop_(); //空操作四個機器周期,給硬件反應時間
  110. E=0; //當E由高電平跳變成低電平時,液晶模塊開始執(zhí)行命令
  111. }
  112. /*****************************************************
  113. LCD1602 初始化
  114. ***************************************************/
  115. void LcdInitiate(void)
  116. {
  117. delay(15); //延時15ms,首次寫指令時應給LCD一段較長的反應時間
  118. WriteCmd(0x38); //顯示模式設置:16×2顯示,5×7點陣,8位數據接口
  119. delay(5); //延時5ms ,給硬件一點反應時間
  120. WriteCmd(0x38);
  121. delay(5); //延時5ms ,給硬件一點反應時間
  122. WriteCmd(0x38); //連續(xù)三次,確保初始化成功
  123. delay(5); //延時5ms ,給硬件一點反應時間
  124. WriteCmd(0x0c); //顯示模式設置:顯示開,無光標,光標不閃爍
  125. delay(5); //延時5ms ,給硬件一點反應時間
  126. // WriteCmd(0x06); //顯示模式設置:光標右移,字符不移
  127. delay(5); //延時5ms ,給硬件一點反應時間
  128. WriteCmd(0x01); //清屏幕指令,將以前的顯示內容清除
  129. delay(5); //延時5ms ,給硬件一點反應時間
  130. }
  131. /************************************************************************
  132. 以下是DS18B20的操作程序
  133. ************************************************************************/

  134. /*****************************************************
  135. DS18B20初始化

  136. ***************************************************/
  137. void Init_DS18B20()
  138. {
  139. uchar x=0;
  140. DQ=1;
  141. ds18b20_delay(8);
  142. DQ=0;
  143. ds18b20_delay(80);
  144. DQ=1;
  145. ds18b20_delay(14);
  146. x=DQ;
  147. ds18b20_delay(20);
  148. }
  149. /*****************************************************
  150. 函數功能:寫一個字節(jié)
  151. 入口參數:
  152. ***************************************************/
  153. void WriteOneChar(uchar dat)
  154. {
  155. uchar i;
  156. for(i=8;i>0;i--)
  157. {
  158. DQ=0;
  159. if(dat&0x01==0x01)
  160. DQ=1;
  161. else
  162. DQ=0;
  163. ds18b20_delay(5);
  164. DQ=1;
  165. ds18b20_delay(1);
  166. dat>>=1;
  167. }
  168. }
  169. /*****************************************************
  170. 讀一個字節(jié)

  171. ***************************************************/
  172. uchar ReadOneChar()
  173. {
  174. uchar dat=0,i;
  175. for(i=8;i>0;i--)
  176. {
  177. dat>>=1;
  178. DQ=0;
  179. ds18b20_delay(1);
  180. DQ=1;
  181. if(DQ==1)
  182. dat|=0x80;
  183. else
  184. dat&=0x7f;
  185. ds18b20_delay(4);
  186. }
  187. return(dat);
  188. }

  189. /*****************************************************
  190. 顯示Now:
  191. ***************************************************/
  192. void display_Now()
  193. {
  194. uchar i;
  195. WriteAdd(0x00); //寫顯示地址,將在第1行第1列開始顯示
  196. for(i=0;i<4;i++)
  197. WriteData(Now[i]);
  198. delay(50); //延時1ms給硬件一點反應時間
  199. }

  200. /*****************************************************
  201. 顯示溫度的小數點
  202. ***************************************************/
  203. void display_dot(void)
  204. {
  205. WriteAdd(0x07); //寫顯示地址,將在第1行第10列開始顯示
  206. WriteData('.'); //將小數點的字符常量寫入LCD
  207. delay(50); //延時1ms給硬件一點反應時間
  208. }
  209. /*****************************************************
  210. 顯示溫度的單位(°C)
  211. ***************************************************/
  212. void display_cent(void)
  213. {
  214. uchar i;
  215. WriteAdd(0x09); //寫顯示地址,將在第1行第13列開始顯示
  216. for(i=0;i<2;i++)
  217. WriteData(Cent[i]); //將字符常量寫入LCD
  218. WriteAdd(0x45);
  219. for(i=0;i<2;i++)
  220. WriteData(Cent[i]);
  221. WriteAdd(0x4e);
  222. for(i=0;i<2;i++)
  223. WriteData(Cent[i]);
  224. }
  225. /*****************************************************
  226. 顯示溫度的整數部分

  227. ***************************************************/
  228. void display_temp1(uchar x)
  229. {
  230. uchar j,k,l; //j,k,l分別儲存溫度的百位、十位和個位
  231. j=x/100; //取百位
  232. k=(x%100)/10; //取十位
  233. l=x%10; //取個位
  234. WriteAdd(0x04); //寫顯示地址,將在第1行第5列開始顯示
  235. if(flag1==1)
  236. {
  237. WriteData(digit[10]); //將"-" 號寫入LCD
  238. }
  239. else
  240. if(j==0)
  241. {j=11;}
  242. WriteData(digit[j]); //將百位數字的字符常量寫入LCD
  243. if(j==0&&k==0)
  244. {k=11;}
  245. WriteData(digit[k]); //將十位數字寫入LCD

  246. WriteData(digit[l]); //將個位數字寫入LCD
  247. delay(50);
  248. }
  249. /*****************************************************
  250. 顯示溫度的小數部分

  251. ***************************************************/
  252. void display_temp2(uchar x)
  253. {
  254. WriteAdd(0x08); //寫顯示地址,將在第2行第11列開始顯示
  255. if(flag1==1)
  256. {
  257. WriteData(digit1[x]); //溫度為負,將小數部分的第一位數字寫入LCD
  258. }
  259. else
  260. WriteData(digit2[x]); //溫度為正,將小數部分的第一位數字寫入LCD
  261. }

  262. /*****************************************************
  263. 顯示溫度設定部分

  264. ***************************************************/
  265. void display_THTL ()
  266. {
  267. uchar i,hhh,hhl,phh,phl,hlh,hll,plh,pll;
  268. hhh=h_TH/10;
  269. hhl=h_TH%10;
  270. phh=p_TH/10;
  271. phl=p_TH%10;
  272. hlh=h_TL/10;
  273. hll=h_TL%10;
  274. plh=p_TL/10;
  275. pll=p_TL%10;

  276. WriteAdd(0x40); //第2行第1個字節(jié)開始
  277. for(i=0;i<2;i++)
  278. WriteData(TH[i]);
  279. WriteAdd(0x43);
  280. if(flag2)
  281. {
  282. WriteData(digit[phh]);
  283. WriteData(digit[phl]);
  284. }

  285. else
  286. {
  287. WriteData(digit[hhh]);
  288. WriteData(digit[hhl]);
  289. }

  290. WriteAdd(0x49); //第2行第10個字節(jié)開始
  291. for(i=0;i<2;i++)
  292. WriteData(TL[i]);
  293. WriteAdd(0x4c);
  294. if(flag2)
  295. {
  296. WriteData(digit[plh]);
  297. WriteData(digit[pll]);

  298. WriteAdd(0x0d);
  299. WriteData('C');
  300. WriteAdd(0x0e);
  301. WriteData('T');
  302. WriteAdd(0x0f);
  303. WriteData('P');
  304. }
  305. else
  306. {
  307. WriteData(digit[hlh]);
  308. WriteData(digit[hll]);
  309. WriteAdd(0x0d);//也可以這樣的寫法
  310. WriteData('H');
  311. WriteAdd(0x0e);
  312. WriteData('T');
  313. WriteAdd(0x0f);
  314. WriteData('R');
  315. }
  316. }
  317. /*****************************************************
  318. 準備讀溫度
  319. ***************************************************/
  320. void ReadyReadTemp()
  321. {
  322. Init_DS18B20(); //將DS18B20初始化
  323. WriteOneChar(0xCC); // 跳過讀序號列號的操作
  324. WriteOneChar(0x44); // 啟動溫度轉換
  325. //for(time=0;time<100;time++); //溫度轉換需要一點時間
  326. Init_DS18B20(); //將DS18B20初始化
  327. WriteOneChar(0xCC); //跳過讀序號列號的操作
  328. WriteOneChar(0xBE); //讀取溫度寄存器,前兩個分別是溫度的低位和高位
  329. }

  330. /*****************************************************
  331. 函數功能:按鍵掃描子函數

  332. ***************************************************/
  333. void keyscan()
  334. {
  335. while(!KEY0) //加熱/水泵切換
  336. {
  337. delay(10);
  338. if(KEY0)
  339. flag2=!flag2;
  340. }

  341. while(!KEY1) //上限/下限切換
  342. {
  343. delay(10);
  344. if(KEY1)
  345. flag3=!flag3;
  346. }
  347. while(!KEY2) //設置溫度加
  348. {
  349. delay(10);
  350. if(KEY2)
  351. {
  352. if(flag2)
  353. {
  354. if(flag3)
  355. p_TL++;
  356. else
  357. p_TH++;
  358. }
  359. else
  360. {
  361. if(flag3)
  362. h_TL++;
  363. else
  364. h_TH++;
  365. }
  366. }
  367. }

  368. while(!KEY3) //設置溫度減
  369. {
  370. delay(10);
  371. if(KEY3)
  372. {
  373. if(flag2)
  374. {
  375. if(flag3)
  376. p_TL--;
  377. else
  378. p_TH--;
  379. }
  380. else
  381. {
  382. if(flag3)
  383. h_TL--;
  384. else
  385. h_TH--;
  386. }
  387. }
  388. }
  389. }

  390. /*****************************************************
  391. 主函數
  392. ***************************************************/

  393. void main()
  394. {
  395. uint temp;
  396. uchar TL; //儲存暫存器的溫度低位
  397. uchar TH; //儲存暫存器的溫度高位
  398. uchar TN; //儲存溫度的整數部分
  399. uchar TD; //儲存溫度的小數部分
  400. LcdInitiate(); //將液晶初始化
  401. delay(5); //延時5ms給硬件一點反應時間
  402. display_Now();
  403. display_dot(); //顯示溫度的小數點
  404. display_cent(); //顯示 ℃
  405. HTR=1;
  406. CTP=1;

  407. while(1)
  408. {
  409. keyscan();
  410. ReadyReadTemp(); //讀溫度準備
  411. TL=ReadOneChar(); //先讀溫度值低位
  412. TH=ReadOneChar(); //后讀溫度值高位
  413. ds18b20_delay(150);
  414. if(TN<h_TL)
  415. HTR=0;
  416. if(TN>h_TH)
  417. HTR=1;
  418. if(TN>p_TH)
  419. CTP=0;
  420. if(TN<p_TL)
  421. CTP=1;

  422. // if(TH&0xf8==0xf8) //TH高5 位為1,溫度值為負 。負數一直調試未成,原來是忽視了優(yōu)先等級。改成if((TH&0XF8)==0XF8),負溫度就正常了。
  423. // {
  424. // flag1=1;
  425. // TL=~(TL)+0x01;
  426. // TH=~TH;
  427. // }
  428. // else

  429. temp=TH;
  430. temp=temp<<8|TL;
  431. TN=temp*0.0625;

  432. // flag1=0;
  433. TD=TL&0x0f;
  434. display_THTL();
  435. display_temp1(TN); //顯示溫度的整數部分
  436. display_temp2(TD); //顯示溫度的小數部分
  437. delay(10);
  438. }

  439. }
復制代碼








回復

使用道具 舉報

ID:36525 發(fā)表于 2016-2-27 23:13 | 顯示全部樓層
我試了一下。顯示NOW:255一直在閃
回復

使用道具 舉報

ID:168553 發(fā)表于 2017-3-9 18:41 | 顯示全部樓層
//2012 05 04
回復

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規(guī)則

小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術交流QQ群281945664

Powered by 單片機教程網

快速回復 返回頂部 返回列表