找回密码
 立即注册

QQ登录

只需一步,快速开始

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

51单片机的PID控制DS18B20水温源代码+电路原理图

[复制链接]
跳转到指定楼层
楼主
基于51单片机的DS18B20水温PID控制调节系统设计C语言程序,通过51单片机控制可控硅驱动加过零检测电路作为功率控制电路来控制加热过程,通过键盘扫描来设定水温,DS18B20实时测量水的温度,将实际水温与设定水温比较,通过PID控制算法调节,是实际水温与设定水温接近。从而达到控制水温的目的。

电路原理图如下:


单片机源程序如下:

  1. #include ‘reg52.h’
  2. #include ‘stdio.h’
  3. #define uchar unsigned char
  4. #define uint unsigned int
  5. sbit s1=P2^0;
  6. sbit s2=P2^1;
  7. sbit s3=P2^2;
  8. sbit s4=P2^3;
  9. sbit s5=P2^4;
  10. sbit ds=P2^5;
  11. sbit beep=P2^6;
  12. sbit rd=P1^0;
  13. sbit rs=P1^1;
  14. sbit wr=P1^2;
  15. sbit lcden=P1^3;
  16. sbit PWM=P1^6;
  17. sbit led1=P1^4;
  18. sbit led2=P1^5;
  19. uchar set_temp,keytemp;
  20. uint temp;
  21. uchar c;
  22. bit flag,flag1,flag2;
  23. float f_temp,t;
  24. int timecount,z;
  25. float KP,KI,KD;
  26. float e1,e2,e3;
  27. float uk,duk;
  28. uchar HighL,HighH,PWMH;
  29. float k;
  30. uchar code table[]={"设定温度:"};
  31. uchar code table1[]={"实测温度:"};
  32. uchar code table2[]={"加热"};
  33. uchar code table3[]={"保温"};
  34. uchar code table4[]={"作者:0903锋仔@"};
  35. uchar code table5[]={"系统初始化"};
  36. uchar code table6[]={"measured Temperature"};
  37. uchar code table7[]={"水温控制系统设计"};
  38. uchar code table8[]={"    "};
  39. void delay(uint z)//延时函数,延时5ms
  40. {
  41. uint x,y;
  42. for(x=z;x>0;x--)
  43. for(y=110;y>0;y--);
  44. }
  45. void keyscan()
  46. {
  47. if(set_temp>=100)//将设定温度限定在0-100度之间
  48. set_temp=100;
  49. if(set_temp<=0)
  50. set_temp=0;
  51. if(s5==0)//此键按下设定温度加5
  52. {
  53. delay(10);
  54. if(s5==0)
  55. {
  56. flag1=0;
  57. set_temp+=5;
  58. if(set_temp>=100)
  59. {
  60. set_temp=100;
  61. beep=0;
  62. delay(1000);
  63. beep=1;
  64. }
  65. }while(s5==0);
  66. }
  67. if(s4==0)//此键按下设定温度减5
  68. {
  69. delay(10);
  70. if(s4==0)
  71. {
  72. flag1=0;
  73. set_temp-=5;
  74. if(set_temp<=0)
  75. {
  76. set_temp=0;
  77. beep=0;
  78. delay(1000);
  79. beep=1;
  80. }
  81. }while(s4==0);
  82. }
  83. if(s3==0)//此键按下设定温度加1
  84. {
  85. delay(10);
  86. if(s3==0)
  87. {
  88. flag1=0;
  89. set_temp++;
  90. if(set_temp==100)
  91. {
  92. set_temp=100;
  93. beep=0;
  94. delay(1000);
  95. beep=1;
  96. }
  97. }while(s3==0);
  98. }
  99. if(s2==0)//此键按下设定温度减1
  100. {
  101. delay(10);
  102. if(s2==0)
  103. {
  104. flag1=0;
  105. set_temp--;
  106. if(set_temp==0)
  107. {
  108. set_temp=0;
  109. beep=0;
  110. delay(1000);
  111. beep=1;
  112. }
  113. }while(s2==0);
  114. }
  115. if(s1==0)//确定加热状态(加热与不加热)
  116. {
  117. delay(10);
  118. if(s1==0)
  119. {
  120. flag1=1;
  121. }
  122. while(s1==0);
  123. }
  124. }
  125. void dsreset()//DS18B20复位函数
  126. {
  127. uint i;
  128. ds=0;
  129. i=103;
  130. while(i>0)i--;
  131. ds=1;
  132. i=4;
  133. while(i>0)i--;
  134. }
  135. bit tempreadbit()//从DS18B20 RAM读一位数据
  136. {
  137. uint i;
  138. bit dat;
  139. ds=0;i++;
  140. ds=1;i++;i++;
  141. dat=ds;
  142. i=8;while(i>0)i--;
  143. return(dat);
  144. }
  145. uchar tempread()//从DS18B20 RAM读一字节数据
  146. {
  147. uchar i,j,dat;
  148. dat=0;
  149. for(i=1;i<=8;i++)
  150. {
  151. j=tempreadbit();
  152. dat=(j<<7)|(dat>>1);
  153. }
  154. return(dat);
  155. }
  156. void tempwritebyte(uchar dat)//向DS18B20写以字节的数据
  157. {
  158. uint i,j;
  159. bit testb;
  160. for(j=1;j<=8;j++)
  161. {
  162. testb=dat&0x01;
  163. dat=dat>>1;
  164. if(testb)//写1
  165. {
  166. ds=0;
  167. i++;i++;
  168. ds=1;
  169. i=8;while(i>0)i--;
  170. }
  171. else//写0
  172. {
  173. ds=0;
  174. i=8;while(i>0)i--;
  175. ds=1;
  176. i++;i++;
  177. }
  178. }
  179. }
  180. void tempchange()//启动温度转换
  181. {
  182. dsreset();
  183. delay(1);
  184. tempwritebyte(0xcc);
  185. tempwritebyte(0x44);
  186. }
  187. float get_temp()//温度值读取与处理函数
  188. {
  189. uchar a,b;
  190. dsreset();
  191. delay(1);
  192. tempwritebyte(0xcc);
  193. tempwritebyte(0xbe);
  194. a=tempread();
  195. b=tempread();
  196. temp=b;
  197. temp<<=8;
  198. temp=temp|a;
  199. f_temp=(float)(temp*0.0625);
  200. f_temp=f_temp*10;
  201. return(f_temp);
  202. }
  203. void write_com(uchar com)//向12864写指令
  204. {
  205. rs=0;
  206. wr=0;
  207. delay(1);
  208. P0=com;
  209. lcden=1;
  210. delay(1);
  211. lcden=0;
  212. delay(1);
  213. }
  214. void write_date(uchar date)//向12864写数据
  215. {
  216. rs=1;
  217. wr=0;
  218. delay(1);
  219. P0=date;
  220. lcden=1;
  221. delay(1);
  222. lcden=0;
  223. delay(1);
  224. }
  225. void display(float m,uchar n)//显示设定温度、实测温度、加热状态
  226. {
  227. uint i,j;
  228. float b;
  229. float p;
  230. uchar a1,a2,a3;
  231. uchar b1,b2,b3,b4;
  232. if(n<100)
  233. {
  234. a1=0;
  235. a2=n/10;
  236. a3=n;
  237. }
  238. else
  239. {
  240. a1=1;
  241. a2=0;
  242. a3=0;
  243. }
  244. p=m;
  245. j=(uint)(p*10);
  246. b1=(uchar)(j/1000);
  247. b2=(uchar)(j00/100);
  248. b3=(uchar)(j0/10);
  249. b4=(uchar)(j);
  250. write_com(0x90+5);//显示设定温度
  251. write_date(0x30+a1);
  252. write_date(0x30+a2);
  253. write_date(0x30+a3);
  254. write_com(0x88+5);//显示实测温度
  255. write_date(0x30+b1);
  256. write_date(0x30+b2);
  257. write_date(0x2e);
  258. write_date(0x30+b3);
  259. write_date(0x30+b4);
  260. b=((float)(b1*100+b2*10+b3))/10.0;
  261. i=0;
  262. if((b+0.2)
  263. {
  264. led1=0;
  265. write_com(0x98+1);
  266. while(table2[i]!='\0')
  267. {
  268. write_date(table2[i]);
  269. i++;
  270. }
  271. flag2=1;
  272. }
  273. else
  274. {
  275. led1=1;
  276. i=0;
  277. write_com(0x98+1);
  278. while(table8[i]!='\0')
  279. {
  280. write_date(table8[i]);
  281. i++;
  282. }
  283. i=0;
  284. if((b=n)||((b>n)&&((b-0.2)<=n))||((b=n)))
  285. {
  286. led2=0;
  287. write_com(0x98+4);
  288. while(table3[i]!='\0')
  289. {
  290. write_date(table3[i]);
  291. i++;
  292. }
  293. }
  294. }
  295. if(flag2==1)
  296. {
  297. flag2=0;
  298. led2=1;
  299. i=0;
  300. write_com(0x98+4);
  301. while(table8[i]!='\0')
  302. {
  303. write_date(table8[i]);
  304. i++;
  305. }
  306. }
  307. }
  308. void conversion()//定时器2初值处理函数
  309. {
  310. uint temp2;
  311. temp2=65536-PWMH*10;
  312. HighH=temp2/256;
  313. HighL=temp2%6;
  314. }
  315. void senddate(float y)
  316. {
  317. // uint i;
  318. if(flag==1)
  319. {
  320. ES=0;
  321. flag=0;
  322. c=0;
  323. TI=1;
  324. printf("The measured temp:%f",y);
  325. // SBUF=1;
  326. while(!TI);
  327. TI=0;
  328. ES=1;
  329. }
  330. }
  331. void init()//初始化函数
  332. {
  333. uint i,j;
  334. TMOD=0x21;
  335. TH1=0xfd;
  336. TL1=0xfd;
  337. TH0=(65536-50000)/256;
  338. TL0=(65536-50000)%6;
  339. PWMH=0;
  340. conversion();
  341. TH2=(65536-50000)/256;
  342. TL2=(65536-50000)%6;
  343. rd=1;
  344. lcden=0;
  345. write_com(0x30);
  346. write_com(0x0c);
  347. write_com(0x01);
  348. write_com(0x90);
  349. while(table5[i]!='\0')//系统初始化
  350. {
  351. write_date(table5[i]);
  352. i++;
  353. delay(20);
  354. }
  355. for(j=0;j<=1;j++)//6个点的三次循环
  356. {
  357. write_com(0x88+4);
  358. for(i=0;i<=5;i++)
  359. {
  360. write_date(0x2e);
  361. delay(200);
  362. }
  363. delay(100);
  364. write_com(0x88+4);
  365. for(i=0;i<=5;i++)
  366. {
  367. write_date(0x20);
  368. }
  369. delay(100);
  370. }
  371. i=0;
  372. write_com(0x80);//显示 水温控制系统设计标题
  373. while(table7[i]!='\0')
  374. {
  375. write_date(table7[i]);
  376. i++;
  377. }
  378. i=0;
  379. write_com(0x90);//显示 设定温度
  380. while(table[i]!='\0')
  381. {
  382. write_date(table[i]);
  383. i++;
  384. }
  385. i=0;
  386. write_com(0x88);//显示 实测温度
  387. while(table1[i]!='\0')
  388. {
  389. write_date(table1[i]);
  390. i++;
  391. }
  392. // tempwritebyte(0x4e);//设定DS18B20的分辨率为11位
  393. // tempwritebyte(0x5f);
  394. PWM=0;
  395. e1=0;
  396. e2=0;
  397. e3=0;
  398. duk=0;
  399. uk=0;
  400. KP=20;//PID控制算法参数
  401. KI=0.061;
  402. KD=30;
  403. REN=1;//串口通信设置
  404. SM0=0;
  405. SM1=1;
  406. ET0=1;
  407. ET2=1;
  408. TR0=1;
  409. TR1=1;
  410. TR2=1;//启动定时器2
  411. EA=1;
  412. ES=1;
  413. }
  414. void main()
  415. {
  416. init();
  417. while(1)
  418. {
  419. keyscan();//调用键盘扫描函数
  420. tempchange();//启动温度转换
  421. t=get_temp();//提取实测温度
  422. display(t,set_temp);//显示设定温度和实测温度
  423. senddate(t);//向上位机发送数据函数
  424. if((flag1==1))
  425. {
  426.    if(timecount>=375)
  427. {
  428. timecount=0;
  429. e1=set_temp-t;
  430. duk=(KP*(e1-e2)+KI*e1+KD*(e1-2*e2+e3));//PID控制算法式
  431.    uk=uk+duk;
  432. if(e1>=75)
  433. {
  434. z=4;
  435. }
  436. else if(e1>=50)
  437. {
  438. z=3;
  439. }
  440. else if(e1>=10)
  441. {
  442. z=2;
  443. }
  444. else
  445. z=1;
  446. }
  447. if(uk>=2500)uk=2500;
  448.    if(uk<=0)uk=0;
  449. if(uk<=0)
  450. {
  451. ET0=0;
  452. ET2=0;
  453. PWM=0;
  454. }
  455. else
  456. {
  457. ET0=1;
  458. ET2=1;
  459. PWMH=(uchar)uk;
  460. k=(float)uk;
  461. }
  462. e3=e2;
  463.    e2=e1;
  464. conversion();//调用定时器2初值处理函数
  465. }
  466. else
  467. {
  468. ET0=0;
  469. ET2=0;
  470. PWM=0;
  471. }
  472. }
  473. }
  474. void timer0() interrupt 1//定时器1中断
  475. {
  476. TH1=(65536-50000)/256;
  477. TL1=(65536-50000)%6;
  478. timecount++;
  479. TH2=HighH;
  480. TL2=HighL;
  481. PWM=1;
  482. }
  483. void ser() interrupt 4//串口中断
  484. {
  485. RI=0;
  486. c=SBUF;
  487. flag=1;
  488. }
  489. void Timer2() interrupt 5//用定时器2控制PWM占空比
  490. {
  491. TF2=0;
  492. PWM=0;
  493. }
复制代码

评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

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

使用道具 举报

沙发
ID:504053 发表于 2019-4-13 00:24 来自手机 | 只看该作者
程序和原理图不符
回复

使用道具 举报

板凳
ID:666029 发表于 2019-12-17 13:44 | 只看该作者
1374823693 发表于 2019-4-13 00:24
程序和原理图不符

可能是元器件不对
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

Powered by 单片机教程网

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