找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 3164|回复: 1
收起左侧

基于51单片机的水温PID控制恒温系统Proteus仿真源程序

  [复制链接]
ID:332674 发表于 2021-5-15 17:06 | 显示全部楼层 |阅读模式
基于51单片机的PID控制恒温系统protues仿真,楼主之前找了很久,没找到好用的,这个是楼主花了一点小代价找到的,现在免费分享给那些需要的伙伴吧,希望能帮助到你们一点

仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)
51hei.png 51hei.png

单片机源程序如下:
  1. #include"reg51.h"
  2. #define uchar unsigned char
  3. #define uint unsigned int
  4. #define ulong unsigned long
  5. /*****************引脚定义*********************************/
  6. //l298n
  7. sbit output=P2^5;
  8. sbit in1=P2^3;
  9. sbit in2=P2^4;
  10. /********************************/
  11. //AD芯片
  12. sbit CLOCK=P3^1;
  13. sbit D_IN=P2^7;
  14. sbit D_OUT=P2^6;
  15. sbit _CS=P3^0;
  16. /********************************/
  17. //lcd液晶
  18. sbit lcdrs=P2^0;
  19. sbit lcdrw=P2^1;
  20. sbit lcden=P2^2;
  21. /********************************/
  22. //灯
  23. sbit led=P3^2;
  24. //蜂鸣器
  25. sbit speaker=P3^3;
  26. /*****************引脚定义*********************************/
  27. /*****************变量定义(申明)*********************************/
  28. int freq=500,pwm=0;
  29. uchar setflag=0,pageflag=0,ok=0;
  30. float pwm_temp=0;
  31. float  KP=100,KI=10,KD=0;  
  32. uint  pul_count=0;
  33. float ek=0,ek1=0,ek2=0;
  34. float keytemp=0;

  35. uchar code str[16]="    welcome!    ";
  36. uchar code str1[16]=" temperature PID";
  37. uchar code str2[16]="set-T     now-T " ;
  38. uchar code str3[16]="P:     I:     D:" ;
  39. uchar code str4[16]="set-P:       " ;
  40. uchar code str5[16]="set-I:       " ;
  41. uchar code str6[16]="set-D:       " ;
  42. void Init(void);
  43. uint adcread(uchar port);
  44. void delay(uint n);
  45. void writecom(uchar com);
  46. void writedata(uchar date);
  47. void initlcd();
  48. float keyscan(void);
  49. uchar keyscans(void);
  50. void lcdnumdisplay(uchar pos,double  f);
  51. void lcdnumdisplays(uchar pos,double  f);
  52. uint read_pul();
  53. void mypid(float Kp,float Ki,float Kd,uint count,uint point);
  54. /*****************变量定义(申明)*********************************/

  55. void main()
  56. {
  57.     uchar i;float scantemp;
  58.         float adnum0=0;
  59.         float adnum1=0;
  60.         bit init0,init1,init2,init3,init4;
  61.         Init();
  62.         initlcd();
  63.     writecom(0x80);
  64.         for(i=0;i<16;i++)writedata(str[i]);                 //huanyin
  65.         writecom(0x80+0x40);
  66.         for(i=0;i<16;i++)writedata(str1[i]);          //shuming
  67.         delay(2000);
  68. //        output=0;
  69. //        in1=1;in2=0;
  70. //        while(1);
  71.         while(1)
  72.         {
  73.                  pwm_temp=500*(float)(adnum0)/4095;
  74.                  //pwm=pwm_temp;
  75.                  mypid(KP,KI,KD,adnum1,pwm_temp);
  76.                  scantemp=keyscan();
  77.                  if(adnum1>=pwm_temp-1.5&&adnum1<=pwm_temp+1.5)
  78.                    {
  79.                         led=0;
  80.                         speaker=1;
  81.                    }
  82.                 else{
  83.                     led=1;
  84.                         speaker=0;
  85.                         }
  86.             if(setflag==0)
  87.                 {
  88.                  adnum0=adcread(0);
  89.                  adnum1=adcread(1)/45;
  90.                  if(init0==0)
  91.                  {
  92.                  initlcd();
  93.                  writecom(0x80);
  94.              for(i=0;i<16;i++)
  95.                                         writedata(str2[i]);          //shuming
  96.                         init0=1;init1=0;init2=0;init3=0;init4=0;
  97.                  }
  98.                  lcdnumdisplays(0x80+0x40,(float)pwm_temp);         //pwm_temp
  99.                  lcdnumdisplays(0x80+0x4a,(float)adnum1);         
  100.                  }

  101.                  if(setflag!=0&&pageflag==0)
  102.                  {
  103.                     if(init1==0)
  104.                         {
  105.                         initlcd();
  106.                         writecom(0x80);
  107.                         for(i=0;i<16;i++)writedata(str3[i]);          
  108.                         init0=0;init1=1;init2=0;init3=0;init4=0;
  109.                         }
  110.                         lcdnumdisplays(0x80+0x40,KP);
  111.                         lcdnumdisplays(0x80+0x46,KI);
  112.                         lcdnumdisplays(0x80+0x4D,KD);       
  113.                  }
  114.                  if(setflag!=0&&pageflag==1)
  115.                  {
  116.                     if(init2==0)
  117.                         {
  118.                         initlcd();
  119.                         writecom(0x80);
  120.                         for(i=0;i<16;i++)writedata(str4[i]);          
  121.                         init0=0;init1=0;init2=1;init3=0;init4=0;
  122.                         }
  123.                         lcdnumdisplays(0x80+0x40,scantemp);
  124.                         if(ok==1){KP=scantemp;ok=0;}       
  125.                  }
  126.                  if(setflag!=0&&pageflag==2)
  127.                  {
  128.                     if(init3==0)
  129.                         {
  130.                         initlcd();
  131.                         writecom(0x80);
  132.                         for(i=0;i<16;i++)writedata(str5[i]);          
  133.                         init0=0;init1=0;init2=0;init3=1;init4=0;
  134.                         }
  135.                         lcdnumdisplays(0x80+0x40,scantemp);
  136.                         if(ok==1){KI=scantemp;ok=0;}       
  137.                  }
  138.                  if(setflag!=0&&pageflag==3)
  139.                  {
  140.                     if(init4==0)
  141.                         {
  142.                         initlcd();
  143.                         writecom(0x80);
  144.                         for(i=0;i<16;i++)writedata(str6[i]);        
  145.                         init0=0;init1=0;init2=0;init3=0;init4=1;
  146.                         }
  147.                         lcdnumdisplays(0x80+0x40,scantemp);
  148.                         if(ok==1){KD=scantemp;ok=0;}               
  149.                  }             
  150.     }
  151. }

  152. void mypid(float Kp,float Ki,float Kd,uint count,uint point)
  153. {
  154.    static float Uk;
  155.    ek=point-count;
  156. //   if(ek>=5&&ek<=-5)   //积分分离                                       
  157.    {Uk=Kp*(ek-ek1)+Ki*ek+Kd*(ek-2*ek1+ek2);}      
  158. //   else
  159. //   Uk=Kp*ek;
  160.    pwm=Uk;
  161.          //lcdnumdisplays(0x80+0x4a,(float)pwm);       
  162.    if(pwm>freq)pwm=freq;
  163.    if(pwm<=0){pwm=0;in1=0;in2=1;}
  164.    if(pwm>0) {in1=1;in2=0;}
  165.    ek2=ek1;
  166.    ek1=ek;
  167. }
  168. uint read_pul()
  169. {
  170.   uint t1,th1,th2;                                 
  171.   uint val;
  172.   while(1)
  173.   {
  174.      th1=TH1;
  175.          t1=TL1;
  176.          th2=TH1;
  177.          if(th1==th2)
  178.            break;
  179.   }      
  180.      val=th1*256+t1;
  181.          return val;
  182. }


  183. void delay(uint n)
  184. {
  185. uint i,j;
  186. for(i=n;i>0;i--)
  187. for(j=1;j>0;j--);
  188. }

  189. void Init(void)//初始化函数
  190. {
  191.     TMOD=0x51;
  192.         TH0=(65536-10)/256;
  193.         TL0=(65536-10)%256;
  194.         EA=1;
  195.         ET0=1;               
  196.         TR0=1;
  197.         TH1=0;
  198.         TL1=0;
  199.         TR1=1;
  200. }

  201. void  Timer_0(void) interrupt 1
  202. {
  203.        static ulong t_count=0;
  204.            static uint num_count=0;
  205.        TR0=0;
  206.            TH0=(65536-10)/256;
  207.            TL0=(65536-10)%256;
  208.            TR0=1;
  209.            num_count++;
  210. //           t_count++;
  211. //           if(t_count==2320)
  212. //                 {
  213. //                             t_count=0;
  214. //                                 TR1=0;
  215. //                                 pul_count=read_pul();               
  216. //                         TH1=0;
  217. //                         TL1=0;
  218. //                                 TR1=1;
  219. //                 }
  220.            if(num_count>freq)num_count=0;    //1khz;
  221.            if(num_count<pwm)output=1;
  222.            else output=0;
  223.           
  224. }
  225. //lcd写命令
  226. void writecom(uchar com)
  227. {
  228.    lcdrs=0;
  229.    P0=com;
  230.    delay(1);
  231.    lcden=1;
  232.    delay(1);
  233.    lcden=0;         
  234. }
  235. //lcd写数据
  236. void writedata(uchar date)
  237. //初始化lcd
  238. {  
  239.    lcdrs=1;          
  240.    P0=date;
  241.    delay(1);
  242.    lcden=1;
  243.    delay(1);
  244.    lcden=0;          
  245. }
  246. void initlcd()
  247. {
  248.    lcdrw=0;
  249.    writecom(0x38);delay(1);       
  250.    writecom(0x0c);delay(1);          
  251.    writecom(0x06);delay(1);
  252.    writecom(0x01);delay(5);
  253. }

  254. //adc读
  255. uint adcread(uchar port)
  256. {                 
  257.    uint ad=0,i;
  258.        
  259.    CLOCK=0;
  260.    _CS=0;
  261.    port<<=4;
  262.    for(i=0;i<12;i++)
  263.   {
  264.                 if(D_OUT)
  265.                         ad|=0x01;
  266.                 D_IN=(bit)(port&0x80);
  267.                 CLOCK=1;
  268.                 delay(1);
  269.                 CLOCK=0;
  270.                 delay(1);
  271.                 port<<=1;
  272.                 ad<<=1;
  273.   }
  274.   _CS=1;
  275.        
  276.   ad>>=1;
  277.   return(ad);
  278. }
  279. //lcd显示数据1
  280. void lcdnumdisplays(uchar pos,float f)                //(0.001-99999) 精度低 但方便数据更新
  281. {  
  282.    uchar i;
  283.    writecom(pos);
  284.    if(f>65535&&f<0.001) for(i=0;i<5;i++)writedata(0x23);//超出范围 显示#
  285.    else if(f==0){writedata(0x30);for(i=0;i<4;i++)writedata(0x20);}
  286.    else
  287.      {
  288.            if((uint)f/10000!=0)
  289.            {
  290.             writedata((uint)f/10000+0x30);
  291.             writedata((uint)f%10000/1000+0x30);
  292.                 writedata((uint)f%1000/100+0x30);
  293.                 writedata((uint)f%100/10+0x30);
  294.                 writedata((uint)f%10+0x30);
  295.            }
  296.            else
  297.            {
  298.             if((uint)f/1000!=0)
  299.                 {
  300.                 writedata(0+0x30);
  301.             writedata((uint)f/1000+0x30);
  302.                 writedata((uint)f%1000/100+0x30);
  303.                 writedata((uint)f%100/10+0x30);
  304.                 writedata((uint)f%10+0x30);
  305.                 }
  306.                 else
  307.                 {
  308.                   if((uint)f/100!=0)
  309.                   {
  310.                     writedata((uint)f/100+0x30);
  311.                            writedata((uint)f%100/10+0x30);
  312.                     writedata((uint)f%10+0x30);
  313.                         writedata(0x2e);
  314.                         writedata((uint)(f*10)%10+0x30);
  315.                   }
  316.                   else
  317.                   {
  318.                     if((uint)f/10!=0)
  319.                         {
  320.                         writedata((uint)f/10+0x30);
  321.                         writedata((uint)f%10+0x30);
  322.                         writedata(0x2e);
  323.                         writedata((uint)(f*10)%10+0x30);
  324.                         writedata((uint)(f*100)%10+0x30);
  325.                         }
  326.                         else
  327.                         {
  328.                         writedata((uint)f%10+0x30);
  329.                         writedata(0x2e);
  330.                         writedata((uint)(f*10)%10+0x30);
  331.                         writedata((uint)(f*100)%10+0x30);
  332.                         writedata((uint)(f*1000)%10+0x30);
  333.                         }
  334.                   }
  335.                  }
  336.            }
  337.          }
  338. }


  339. //lcd显示数据2
  340. void lcdnumdisplay(uchar pos,float f0)                //(0.00001-99999.99999) 精度高 但数据需刷屏更新
  341. {
  342.    uchar temp;
  343.    ulong    f;
  344.    writecom(pos);
  345.    f=(ulong)f0;
  346.    temp=f/10000;         //整数部分
  347.    if(temp!=0)
  348.      {
  349.             writedata(temp+0x30);
  350.                 writedata(f%10000/1000+0x30);
  351.                 writedata(f%1000/100+0x30);
  352.                 writedata(f%100/10+0x30);
  353.                 writedata(f%10+0x30);
  354.          }
  355.    else
  356.      {
  357.             temp=f%10000/1000;
  358.                 if(temp!=0)
  359.                 {
  360.                    writedata(temp+0x30);
  361.                    writedata(f%1000/100+0x30);
  362.                    writedata(f%100/10+0x30);
  363.                    writedata(f%10+0x30);
  364.                 }
  365.                 else
  366.                 {
  367.                    temp=f%1000/100;
  368.                    if(temp!=0)
  369.                    {
  370.                       writedata(temp+0x30);
  371.                           writedata(f%100/10+0x30);
  372.                       writedata(f%10+0x30);
  373.                    }
  374.                    else
  375.                    {
  376.                       temp=f%100/10;
  377.                           if(temp!=0)
  378.                                 {
  379.                                    writedata(temp+0x30);
  380.                                    writedata(f%10+0x30);     
  381.                                 }
  382.                                 else
  383.                                 {
  384.                                    temp=f%10;
  385.                                    if(temp!=0)
  386.                                    {
  387.                                      writedata(temp+0x30);
  388.                                    }
  389.                                    else writedata(0+0x30);
  390.                                  }
  391.                           }  
  392.                    }
  393.                 }


  394.     if((ulong)(f0*10)%10!=0||(ulong)(f0*100)%10!=0||(ulong)(f0*1000)%10!=0||(ulong)(f0*10000)%10!=0)                  
  395.         {
  396.                       writedata(0x2e);
  397.                    temp=(ulong)(f0*10000)%10;
  398.                    if(temp!=0)
  399.                    {
  400.                      writedata((ulong)(f0*10)%10+0x30);
  401.                          writedata((ulong)(f0*100)%10+0x30);
  402.                          writedata((ulong)(f0*1000)%10+0x30);
  403.                          writedata(temp+0x30);
  404.                    }
  405.                    else
  406.                    {
  407.                        temp=(ulong)(f0*1000)%10;
  408.                        if(temp!=0)
  409.                            {
  410.                              writedata((ulong)(f0*10)%10+0x30);
  411.                              writedata((ulong)(f0*100)%10+0x30);
  412.                                  writedata(temp+0x30);
  413.                            }
  414.                            else
  415.                            {
  416.                               temp=(ulong)(f0*100)%10;
  417.                                   if(temp!=0)
  418.                                   {
  419.                                     writedata((ulong)(f0*10)%10+0x30);
  420.                                         writedata(temp+0x30);
  421.                                   }
  422.                                   else
  423.                                   {
  424.                                     temp=(ulong)(f0*10)%10;
  425.                                         if(temp!=0)
  426.                                           writedata(temp+0x30);
  427.                                   }
  428.                             }            
  429.                       }
  430.                     }
  431. }



  432. uchar keyscans(void)//矩阵键盘扫描
  433. {
  434.     uchar i, j, temp, Buffer[4] = {0xef, 0xdf, 0xbf, 0x7f};
  435.     for(j = 0; j < 4; j++)    //循环四次
  436.    {
  437.       P1 = Buffer[j];         //在P1高四位分别输出一个低电平
  438.       temp = 0x01;            //计划先判断P1.0位
  439.       for(i = 0; i < 4; i++)
  440.    {
  441.         if(!(P1 & temp))      //从P1低四位,截取1位
  442.           return (i + j * 4); //返回取得的按键值
  443.         temp <<= 1;           //判断的位,左移一位
  444.    }
  445. ……………………

  446. …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码
51hei.png
所有资料51hei提供下载:
水温控制系统PID可调51单片机仿真.zip (100.06 KB, 下载次数: 171)

评分

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

查看全部评分

回复

使用道具 举报

ID:897014 发表于 2021-5-25 12:07 | 显示全部楼层
这里面没有温度传感器呀,滑动电阻控制的是设定温度
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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