找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 5405|回复: 2
打印 上一主题 下一主题
收起左侧

单片机热水锅炉自动温度控制系统(C51)

[复制链接]
跳转到指定楼层
楼主
ID:104835 发表于 2016-2-3 22:52 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式


  为好朋友东东设计了个单片机热水锅炉自动温度控制系统。因为他家的热水锅炉因温度太低,没及时加热,爆过几 次。也有因加热过头,烧干水,化了管子。东东很快做好了实物,程序得到验证,两人皆大欢喜。
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. 判断液晶模块的忙碌状态

  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); //显示位置的确定方法规定为"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发生正跳变,所以应先置"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由高电平跳变成低电平时,液晶模块开始执行命令
  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); //连续三次,确保初始化成功
  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. 函数功能:写一个字节
  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. 读一个字节

  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个字节开始
  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个字节开始
  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,温度值为负 。负数一直调试未成,原来是忽视了优先等级。改成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. }
复制代码








分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏3 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:36525 发表于 2016-2-27 23:13 | 只看该作者
我试了一下。显示NOW:255一直在闪
回复

使用道具 举报

板凳
ID:168553 发表于 2017-3-9 18:41 | 只看该作者
//2012 05 04
回复

使用道具 举报

无效楼层,该帖已经被删除
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表