找回密码
 立即注册

QQ登录

只需一步,快速开始

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

单片机PID控制算法调节DS18B20水温控制系统设计源码

[复制链接]
跳转到指定楼层
楼主
ID:328014 发表于 2018-7-1 03:55 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
水温控制系统设计

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

  494. …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码

所有资料51hei提供下载:
http://www.51hei.com/bbs/dpj-124587-1.html


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

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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