找回密码
 立即注册

QQ登录

只需一步,快速开始

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

单片机PID温度控制程序

[复制链接]
跳转到指定楼层
楼主
ID:918728 发表于 2024-3-20 09:19 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
  1. #include <REGX51.H>
  2. #define Kp 5        //比例系数
  3. #define Ki 2    //积分系数
  4. #define Kd 1        //微分系数

  5. unsigned char m,n,p;                          //温度的十位 个位 小数
  6. unsigned char test_temp;                //温度检定标志
  7. unsigned char key_set_flag;                //按键设定进入标志
  8. unsigned char flag=1;                        //按键保持标志
  9. unsigned char Change_step=1,e;        //温度设置步进
  10. unsigned char T0_H = 0,T0_L = 0,T1_H=0,T1_L=0;
  11. int Real_temp;                //实际温度值
  12. int Set_temp;                //设置温度
  13. int Disp_temp;                //显示温度
  14. int last_error;                //上次误差
  15. float I_term;                //前面温差和
  16. bit        key_hold;
  17. unsigned char dj_flag1;
  18. bit        key_flag;
  19. int PID_MAX;
  20. unsigned int out,PWMT,counter,kk,outp,dz;
  21. int time;        //脉冲触发时刻

  22. sbit DQ=P2^4;        //定义DS18b20的管脚
  23. sbit RS = P2^0;   //定义液晶屏定义端口
  24. sbit RW = P2^1;          //定义液晶屏定义端口
  25. sbit EN = P2^2;          //定义液晶屏定义端口
  26. sbit k1=P1^0;
  27. sbit k2=P1^1;
  28. sbit k3=P1^2;
  29. sbit k4=P1^3;
  30. sbit k5=P1^4;
  31. sbit k6=P1^5;
  32. sbit k7=P1^6;
  33. sbit k8=P1^7;
  34. sbit PWM=P2^7;        //PWM控制脚
  35. sbit DJ1=P2^3;
  36. sbit DJ2=P2^5;
  37. sbit led1=P3^5;
  38. sbit led2=P3^6;
  39. sbit led3=P3^7;
  40. sbit led4=P3^4;

  41. #define RS_CLR RS=0
  42. #define RS_SET RS=1

  43. #define RW_CLR RW=0
  44. #define RW_SET RW=1

  45. #define EN_CLR EN=0
  46. #define EN_SET EN=1

  47. unsigned char aa[]={' ',' ','S','e','t','u','p',':',' ',' ','.',' ',' ',' ',' ',' '};           //Distance
  48. unsigned char bb[]={' ',' ',' ',' ',' ',' ',' ','.',' ',' ',' ',' ',' ',' ',' ',' '};        


  49. void LCD_Write_String(unsigned char x,unsigned char y,unsigned char *s);
  50. void LCD_Write_Char(unsigned char x,unsigned char y,unsigned char Data);
  51. void init();                        //初始化
  52. /*------------------------------------------------
  53. uS延时函数,含有输入参数 unsigned char t,无返回值
  54. unsigned char 是定义无符号字符变量,其值的范围是
  55. 0~255 这里使用晶振12M,精确延时请使用汇编,大致延时
  56. 长度如下 T=tx2+5 uS
  57. ------------------------------------------------*/
  58. void DelayUs2x(unsigned char t)
  59. {   
  60.          while(--t);
  61. }
  62. /*------------------------------------------------
  63. mS延时函数,含有输入参数 unsigned char t,无返回值
  64. unsigned char 是定义无符号字符变量,其值的范围是
  65. 0~255 这里使用晶振12M,精确延时请使用汇编
  66. ------------------------------------------------*/
  67. void DelayMs(unsigned char t)
  68. {
  69.           while(t--)                 //大致延时1mS
  70.          {
  71.              DelayUs2x(245);
  72.                  DelayUs2x(245);
  73.          }
  74. }

  75. /*****延时子程序*****/
  76. void delay(unsigned int t)
  77. {
  78.         for(;t>0;t--);
  79. }
  80. void delay_50us(unsigned int t)
  81. {
  82.         unsigned char j;
  83.         for(;t>0;t--)
  84.                 for(j=19;j>0;j--);
  85. }
  86. /*****初始化DS18B20*****/
  87. unsigned char Init_DS18B20(void)
  88. {
  89.   unsigned char x=0;
  90.   DQ = 1;      //DQ复位
  91.   delay(8);    //稍做延时
  92.   DQ = 0;      //单片机将DQ拉低
  93.   delay(80);   //精确延时,大于480us
  94.   DQ = 1;      //拉高总线
  95.   delay(8);
  96.   x = DQ;      //稍做延时后,如果x=0则初始化成功,x=1则初始化失败
  97.   delay(4);
  98.   return x;
  99. }
  100. /*****读一个字节*****/
  101. unsigned char ReadOneChar(void)
  102. {
  103.   unsigned char i=0;
  104.   unsigned char dat = 0;
  105.   for (i=8;i>0;i--)
  106.   {
  107.     DQ = 0;     // 给脉冲信号
  108.     dat>>=1;
  109.     DQ = 1;     // 给脉冲信号
  110.     if(DQ)
  111.             dat|=0x80;
  112.         delay(4);
  113.   }
  114.   return(dat);
  115. }
  116. /*****写一个字节*****/
  117. void WriteOneChar(unsigned char dat)
  118. {
  119.   unsigned char i=0;
  120.   for (i=8; i>0; i--)
  121.   {
  122.     DQ = 0;
  123.     DQ = dat&0x01;
  124.         delay(4);
  125.     DQ = 1;
  126.     dat>>=1;
  127.   }
  128.   delay(4);
  129. }
  130. /*****读取温度*****/
  131. int ReadTemperature(void)
  132. {
  133.           unsigned char a=0;
  134.           unsigned char b=0;
  135.           unsigned int t=0;
  136.           t=Init_DS18B20();
  137.           if(t) return Real_temp;
  138.           WriteOneChar(0xCC);  //跳过读序号列号的操作
  139.           WriteOneChar(0x44);  //启动温度转换
  140.           t=Init_DS18B20();
  141.           if(t) return Real_temp;
  142.           WriteOneChar(0xCC);  //跳过读序号列号的操作
  143.           WriteOneChar(0xBE);  //读取温度寄存器
  144.           a=ReadOneChar();     //读低8位
  145.           b=ReadOneChar();     //读高8位
  146.           t=b;
  147.           t<<=8;
  148.           t=t|a;
  149.           if(t<=0||t>0x900)
  150.         return Real_temp;
  151.         t=t*0.625+0.5;
  152.           return(t);
  153. }  void keywendu_set(void)
  154. {
  155.         if(k1==0)
  156.         {
  157.                 delay(10);
  158.                 while(!k1);
  159.                 key_hold=~key_hold;
  160.         }
  161.         if(key_hold==0)
  162.         {
  163.             if(k2==0)
  164.                 {
  165.                         delay(10);
  166.                     while(!k2);
  167.                         Set_temp=Set_temp+1;
  168.                         if(Set_temp>99)
  169.                         Set_temp=99;
  170.                 }
  171.             if(k3==0)
  172.                 {
  173.                         delay(10);
  174.                         while(!k3);
  175.                         Set_temp=Set_temp-1;
  176.                         if(Set_temp<1)
  177.                         Set_temp=1;
  178.                 }
  179.                 aa[8]=10*Set_temp/100+'0';
  180.                 aa[9]=10*Set_temp/10%10+'0';
  181.                 aa[11]=10*Set_temp%10+'0';
  182.                 LCD_Write_String(0,0,aa);
  183.         }
  184. }  
  185. void keyzhuansu_set(void)
  186. {
  187.         if(k4==0)
  188.         {
  189.                 delay(10);
  190.                 while(!k4);
  191.                 key_flag=~key_flag;
  192.         }
  193.         if(key_flag==0)    //手动模式
  194.         {
  195.                 led4=1;
  196.     if(k5==0)
  197.                 {
  198.                         DJ1=1;
  199.                         DJ2=0;
  200.                 }
  201.                 else if(k6==0)
  202.                 {
  203.                         DJ1=0;
  204.                         DJ2=1;        
  205.                 }
  206.                 else
  207.                 {
  208.                         DJ1=0;
  209.                         DJ2=0;            
  210.                 }
  211.         }

  212. else
  213.         {
  214.                 led4=0;               
  215.           if(k5==0)
  216.                 {
  217.                         delay(10);
  218.                         while(!k5);        
  219.                         dj_flag1=1;
  220.                 }
  221.                 if(k6==0)
  222.                 {
  223.                         delay(10);
  224.                         while(!k6);
  225.                   dj_flag1=2;
  226.                 }        
  227.                 if(k7==0)
  228.                 {
  229.                         delay(10);
  230.                         while(!k7);
  231.                   dj_flag1=3;
  232.                 }        

  233.                 if(dj_flag1==1)
  234.                 {
  235.                         DJ1=1;
  236.                         DJ2=0;
  237.                 }
  238.     else if(dj_flag1==2)
  239.                 {
  240.                         DJ1=0;
  241.                         DJ2=1;               
  242.                 }
  243.                 else
  244.                 {
  245.                         DJ1=0;
  246.                         DJ2=0;               
  247.                 }
  248.         }
  249. }
  250. int PID(int Set_value,int Real_value) //标准PID温度控制算法
  251. {
  252.         float uk ,uk1 ,duk;
  253.         int pid_out,e ,e1 ,e2;
  254.         e=Set_value-Real_value;//误差量
  255.         duk=Kp*(e-e1)+Ki*e+Kd*(e-2*e1+e2);  //+Kd*(e-2e1+e2)
  256.         uk=uk1+duk;
  257.         pid_out=(int)uk;
  258.         uk1=uk;
  259.         e2=e1;
  260.         e1=e;
  261.         if(pid_out>1000)
  262.         {
  263.                 pid_out=998;
  264.         }
  265.         else if(pid_out<2)
  266.         {
  267.                 pid_out=2;
  268.         }
  269.         outp=pid_out;
  270.         return(pid_out);               
  271. }

  272. void T0_int(void) interrupt 1
  273. {
  274.         T0_H = (65535-2000)/256;                                //PWM=1高位初值计算
  275.         T0_L = (65535-2000)%256;                                  //PWM=1低位初值计算
  276.         TH0 = T0_H;                                 //通的初值高位
  277.         TL0= T0_L;                                 //通的初值低位
  278.         kk++;
  279.         if(kk>1000)
  280.         kk=0;
  281.         if(kk>outp)
  282.         PWM=1;
  283.         else PWM=0;
  284. //        }
  285. }

  286. void main()
  287. {        
  288.         PWMT=128;                        //128级步进PWM控制               
  289.         PID_MAX=PWMT;
  290.         counter=0;
  291.         out=0;
  292.         PWM=1;
  293.         I_term=0;
  294.         last_error=0;
  295.         Set_temp=30;                //初始设定温度为30度
  296.         init();
  297.         Real_temp=Set_temp*10;
  298.         key_hold=1;
  299.           Init_DS18B20();
  300.           WriteOneChar(0xCC);        //跳过读序号列号的操作
  301.           WriteOneChar(0x44); //启动温度转换
  302.         delay_50us(150);        //等待温度测量                  delay_50us(15000);
  303.         TMOD=0x01;                        //定时器0模式1        

  304.         TR0=1;
  305.         ET0=1;
  306.         IT0=1;
  307.         EX0=1;
  308.         EA=1;

  309.         aa[12]=0xdf;
  310.         aa[13]=0x43;
  311.         bb[9]=0xdf;
  312.         bb[10]=0x43;
  313.         aa[8]=10*Set_temp/100+'0';
  314.         aa[9]=10*Set_temp/10%10+'0';
  315.         aa[11]=10*Set_temp%10+'0';
  316.         LCD_Write_String(0,0,aa);
  317.         while(1)
  318.         {
  319.                 counter++;

  320.         DelayMs(500);
  321.                 if(counter>4)
  322.                 {
  323.                         test_temp=1;        //进行一次温度检定
  324.                         counter=0;                                
  325.                 }
  326.                 if(test_temp)         //温度检定标志置位,进入温度PID调节
  327.                 {
  328.                         Real_temp=ReadTemperature(); //采集当前实际温度               
  329.                         test_temp=0;                                 //检定完成,清温度检定标志
  330.                         bb[5]=Real_temp/100+'0';
  331.                         bb[6]=Real_temp/10%10+'0';
  332.                         bb[8]=Real_temp%10+'0';
  333.                         LCD_Write_String(0,1,bb);
  334.                         if((Real_temp/10)<(Set_temp))
  335.                         {   
  336.                                 led1=~led1;
  337.                                 led2=1;
  338.                     }
  339.                 else if((Real_temp/10)>(Set_temp))
  340.                         {   
  341.                                 led3=~led3;
  342.                                 led2=1;
  343.                     }
  344.                         else
  345.                         {
  346.                                 led1=1;
  347.                                 led2=0;
  348.                                 led3=1;
  349.                         }
  350.                 }
  351.                 if((Real_temp/10)<(Set_temp-1))
  352.                 {   
  353.                         outp=998;
  354.             }
  355.         else if((Real_temp/10)>(Set_temp+1))
  356.                 {   
  357.                         outp=2;
  358.             }
  359.                 else
  360.                 {
  361.                         PID(Set_temp*10,Real_temp); //PID程序        
  362.                 }

  363.                 keywendu_set();        //按键温度设置
  364.                 keyzhuansu_set();
  365.          }
  366. }

  367. ///////////////////////////////////////////////////
  368. //          液晶屏显示处理
  369. ///////////////////////////////////////////////////

  370. void write_com(unsigned char com) //写命令
  371. {
  372.         RS_CLR;
  373.         RW_CLR;
  374.         P0=com;
  375.         DelayMs(1);
  376.         EN_SET;
  377.         DelayMs(1);
  378.         EN_CLR;
  379. }

  380. void write_data(unsigned char date)         //写一个字符
  381. {
  382.         RS_SET;
  383.         RW_CLR;
  384.         P0=date;
  385.         DelayMs(1);
  386.         EN_SET;
  387.         DelayMs(1);
  388.         EN_CLR;
  389. }

  390. void init()                        //初始化
  391. {
  392.         write_com(0x38);
  393.         write_com(0x0c);
  394.         write_com(0x06);
  395.         write_com(0x01);
  396. }

  397. /*------------------------------------------------
  398.               写入字符串函数
  399. ------------------------------------------------*/
  400. void LCD_Write_String(unsigned char x,unsigned char y,unsigned char *s)
  401. {     
  402.          if (y == 0)
  403.          {     
  404.                  write_com(0x80 + x);     
  405.          }
  406.          else
  407.          {     
  408.                  write_com(0xC0 + x);     
  409.          }        
  410.          while (*s)
  411.          {     
  412.                  write_data( *s);     
  413.                  s ++;   

  414.         }
  415. }
复制代码
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏4 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:433219 发表于 2024-3-20 14:48 | 只看该作者
没有点 其他重点说明,纯看程序,看不出什么优缺点啊
回复

使用道具 举报

板凳
ID:149799 发表于 2024-3-20 16:33 | 只看该作者
51黑有你最精彩,谢谢上传。
回复

使用道具 举报

地板
ID:253767 发表于 2024-3-22 06:18 | 只看该作者
你最精彩,谢谢上传。
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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