找回密码
 立即注册

QQ登录

只需一步,快速开始

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

单片机PID温控源码,变量值为什么总是不对?

[复制链接]
跳转到指定楼层
楼主
ID:489498 发表于 2019-3-27 16:35 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
求助论坛大神,为什么我学习改写别人的PID温控源码代码,其中PWM 和temp_PID.SetPoint 总是不对,用串口调试的结果总是不对。
输出结果:  PWM:100  PWM:12288  PWM_P:  设置温度:30  实?饰露?2619  temp_s:3000  temp_PID.SetPoint:

按理说我用了这样的        PWM应该在0到100之间temp_PID.SetPoint:应该是3000才对可是输出为什么不是,实在查不出原因,请大神指正。

引脚分配    lcd    lcddata:    P0
            lcd_e:        P2^7
            lcd_rs:        P2^6
            lcd_rw:        P2^5
        
        设置按键    limit_choise:        P    //温度上下限选择按键
                increase_temperature        P    //增加温度限值按键
                reduce_temperature        P    //减少温度限值按键
        
        蜂鸣器报警    warning        P   

        温度传感器    temperature_sensor    P

        制热    heatting    P

        制冷    refrigerating    P

        LED显示        normal        P    //正常温度指示灯
                high_temperature    P    //高温指示灯
                low_temperature        P    //低温指示灯   

单片机源程序如下:
  1. /*******************************************************************************
  2. * 包含头文件
  3. *******************************************************************************/
  4. #include <main.h>

  5. /*******************************************************************************
  6. * 变量声明
  7. *******************************************************************************/

  8. uint  PWM=0;
  9. uint  PWM_P;//PWM_P  功率占比显示

  10. uchar time_value=0;
  11. uchar time_heatting=0;
  12. uint temp_m=0;                        //实际温度
  13. uint up_limit_temp=30;
  14. uint temp_s; //设置温度*100
  15. PID temp_PID;

  16. uchar massage[]=0;


  17. /*******************************************************************************
  18. * 函数名                                                : void main()
  19. * 函数功能                                        : 主函数
  20. * 输入                                                : 无
  21. * 输出                                                : 无
  22. *******************************************************************************/

  23. void main()//主函数
  24. {
  25.     init();//初始化函数

  26.     temp_PID.Proportion =150;              //  设置 PID 系数
  27.     temp_PID.Integral   =5;
  28.     temp_PID.Derivative =2;


  29.                 while(1)
  30.                 {
  31.                         temp_s = up_limit_temp*100;
  32.                         temp_PID.SetPoint =        temp_s;
  33.                         if(time_value==10)                                                                                        //读取温度
  34.                         {
  35.                                 temp_m=get_temp(Ds18b20ReadTemp());

  36.                         }
  37.                         if(time_value==50)
  38.       {
  39.                                 if(temp_s-temp_m>=100)
  40.                                 {
  41.                                         PWM=100;
  42.                                 }
  43.                                 else
  44.                                 {
  45.                                         PWM = pid_calc(&temp_PID,temp_m);
  46.                                         if( PWM>=100 )                PWM=100;
  47.                                         else if(PWM<=1)                PWM=1;
  48.                                 }
  49.                         }
  50.                         if(time_value==60)                                                                                        //显示温度
  51.                         {

  52.                                 display_real_temp(temp_m);                                                
  53.                         }
  54.                   if(time_value==70)
  55.                         {               
  56.                                 send_string("  PWM:");
  57.                                 DtoA(PWM,massage);
  58.                                 send_string(massage);               
  59.                                 /*
  60.                                 PWM_P = PWM;
  61.                                 
  62.                                 LcdWriteCom(0x80+0X40+0x0C);
  63.                                 LcdWriteData('0'+PWM_P/100);
  64.                                 LcdWriteCom(0x80+0X40+0x0D);
  65.                                 LcdWriteData('0'+PWM_P%100/10);
  66.                                 LcdWriteCom(0x80+0X40+0x0E);
  67.                                 LcdWriteData('0'+PWM_P%10);        
  68.                                 
  69.                                 */
  70.                                 send_string("  PWM:");
  71.                                 DtoA(PWM,massage);
  72.                                 send_string(massage);
  73.                                        
  74.                                 send_string("  PWM_P:");
  75.                                 DtoA(PWM_P,massage);
  76.                                 send_string(massage);
  77.                                 
  78.                                 send_string("  设置温度:");
  79.                                 DtoA(up_limit_temp,massage);
  80.                                 send_string(massage);
  81.         
  82.                                 send_string("  实际温度:");
  83.                                 DtoA(temp_m,massage);
  84.                                 send_string(massage);

  85.                           send_string("  temp_s:");
  86.                                 DtoA(temp_s,massage);
  87.                                 send_string(massage);
  88.                                 
  89.                                 send_string("  temp_PID.SetPoint:");
  90.                                 DtoA(temp_PID.SetPoint,massage);
  91.                                 send_string(massage);
  92.                                 send_string("\n");

  93.                         }

  94.                         if(time_value>=100)                                                                                        //指令执行时间,一个单位时间是10ms
  95.       {      
  96.                                 time_value=0;  
  97.       }
  98.                         if(time_heatting >= 500)  time_heatting = 0;
  99.                         if(time_heatting <= PWM*5)      
  100.                         {
  101.                                 heatting=1;
  102.                         }
  103.                         else
  104.                         {        
  105.                                 heatting=0;
  106.                         }

  107.         }               
  108. }
  109. /*******************************************************************************
  110. * 函数名                                                : void init()
  111. * 函数功能                                        : 初始化函数
  112. * 输入                                                : 无
  113. * 输出                                                : 无
  114. *******************************************************************************/
  115. void init()//初始化函数
  116. {
  117.         uint i,j;        
  118.         Ds18b20Init();//Ds18b20初始化
  119.         //heatting=0;//不制热
  120.         
  121.         IT0Init();
  122.         IT1Init();
  123.         InitUart0();
  124.         InitTimer0();//定时器初始化
  125.         pid_init (&temp_PID);//PID初始化

  126.         
  127.         LcdInit();//LCD初始化函数
  128.         
  129.         LcdWriteCom(0x80);//第一行显示
  130.         j=strlen(num1);
  131.         for(i=0; i<j; i++)
  132.         {
  133.                 LcdWriteData(num1[i]);        
  134.                 delay_ms(1);
  135.         }
  136.         LcdWriteCom(0x80+0x40);//第二行显示
  137.         j=strlen(num2);
  138.         for(i=0; i<j; i++)
  139.         {
  140.                 LcdWriteData(num2[i]);        
  141.                 delay_ms(1);
  142.         }
  143.         LcdWriteCom(0x04);  //关闭写一个指针加1
  144. }

  145. /*******************************************************************************
  146. * 函数名                                                : uint get_temp(uint temp)
  147. * 函数功能                                        : 计算温度函数
  148. * 输入                                                : 温度
  149. * 输出                                                : 温度
  150. *******************************************************************************/
  151. uint get_temp(uint temp)//计算温度函数
  152. {
  153.         float tp;
  154.         
  155.         tp=temp;//因为数据处理有小数点所以将温度赋给一个浮点型变量
  156.         //如果温度是正的那么,那么正数的原码就是补码它本身
  157.         temp=tp*0.0625*100+0.5;        
  158.         //留两个小数点就*100,+0.5是四舍五入,因为C语言浮点数转换为整型的时候把小数点
  159.         //后面的数自动去掉,不管是否大于0.5,而+0.5之后大于0.5的就是进1了,小于0.5的就
  160.         //算加上0.5,还是在小数点后面。
  161.         return temp;
  162. }
  163. /*******************************************************************************
  164. * 函数名                                                : void display_real_temp(uint temp)
  165. * 函数功能                                        : 实时温度显示函数
  166. * 输入                                                : 温度
  167. * 输出                                                : 无
  168. *******************************************************************************/
  169. void display_real_temp(uint temp)//实时温度显示函数
  170. {
  171.         uchar datas[] = {0, 0, 0, 0}; //定义数组

  172.         datas[0] = temp % 10000 / 1000;
  173.         datas[1] = temp % 1000 / 100;
  174.         datas[2] = temp % 100 / 10;
  175.         datas[3] = temp % 10;

  176.         LcdWriteCom(0x80+0x0a);                 //写地址 80表示初始地址
  177.         LcdWriteData('0'+datas[0]); //十位

  178.         LcdWriteCom(0x80+0x0b);        //写地址 80表示初始地址
  179.         LcdWriteData('0'+datas[1]); //个位

  180.         LcdWriteCom(0x80+0x0d);         //写地址 80表示初始地址
  181.         LcdWriteData('0'+datas[2]); //显示小数点  

  182.         LcdWriteCom(0x80+0x0e);                 //写地址 80表示初始地址
  183.         LcdWriteData('0'+datas[3]); //显示小数点  

  184. }

  185. /*******************************************************************************
  186. * 函数名                                                : void InitTimer0(void)
  187. * 函数功能                                        : 定时器初始化函数
  188. * 输入                                                : 无
  189. * 输出                                                : 无
  190. *******************************************************************************/
  191. void InitTimer0(void)
  192. {
  193.     TMOD &= 0xF0;
  194.     TMOD |= 0x01;//设置定时模式1
  195.     TH0 = 0xD8;
  196.     TL0 = 0xF0;
  197.     EA = 1;
  198.     ET0 = 1;
  199.     TR0 = 1;
  200. }
  201. /*******************************************************************************
  202. * 函数名                                                : void Timer0Interrupt(void) interrupt 1
  203. * 函数功能                                        : 定时器中断函数
  204. * 输入                                                : 无
  205. * 输出                                                : 无
  206. *******************************************************************************/
  207. void Timer0Interrupt(void) interrupt 1
  208. {
  209.     TH0 = 0xD8;
  210.     TL0 = 0xF0;

  211.         
  212.                 time_value++;             //功能计数值+1  
  213.                 time_heatting++;         //加热计数值+1
  214. }
  215. /*******************************************************************************
  216. * 函数名                                                : void INIT0(void) interrupt 0
  217. * 函数功能                                        : 外部中断0执行函数
  218. * 输入                                                : 无
  219. * 输出                                                : 无
  220. *******************************************************************************/
  221. void INIT0(void) interrupt 0
  222. {
  223.         
  224.         delay_ms(5);
  225.         if (increase_temperature == 0)
  226.                 {
  227.                         while(increase_temperature == 0);
  228.                                         if(up_limit_temp<=110)
  229.                                         {
  230.                                         up_limit_temp=up_limit_temp+5;
  231.                                         LcdWriteCom(0x80+0X40+0x03);
  232.                                         LcdWriteData('0'+up_limit_temp%1000/100);
  233.                                         LcdWriteCom(0x80+0X40+0x04);
  234.                                         LcdWriteData('0'+up_limit_temp%100/10);
  235.                                         LcdWriteCom(0x80+0X40+0x05);
  236.                                         LcdWriteData('0'+up_limit_temp%10);
  237.                                         }

  238.                 }        
  239. }
  240. /*******************************************************************************
  241. * 函数名                                                : void INIT1(void) interrupt 2
  242. * 函数功能                                        : 外部中断1执行函数
  243. * 输入                                                : 无
  244. * 输出                                                : 无
  245. *******************************************************************************/
  246. void INIT1(void) interrupt 2
  247. {
  248.         

  249.         delay_ms(5);
  250.         if (reduce_temperature == 0)
  251.                 {
  252.                         while(reduce_temperature == 0);
  253.                                         if(up_limit_temp>=20)
  254.                                         {
  255.                                         up_limit_temp=up_limit_temp-5;
  256.                                         LcdWriteCom(0x80+0X40+0x03);
  257.                                         LcdWriteData('0'+up_limit_temp%1000/100);
  258.                                         LcdWriteCom(0x80+0X40+0x04);
  259.                                         LcdWriteData('0'+up_limit_temp%100/10);
  260.                                         LcdWriteCom(0x80+0X40+0x05);
  261.                                         LcdWriteData('0'+up_limit_temp%10);
  262.                                         }

  263.                 }        
  264.                
  265. }
  266. /*******************************************************************************
  267. * 函数名                                                : void IT0Init(void)
  268. * 函数功能                                        : 外部中断0初始化
  269. * 输入                                                : 无
  270. * 输出                                                : 无
  271. *******************************************************************************/
  272. void IT0Init(void)
  273. {
  274.     IT0 = 0;//0为电平,1为下降沿
  275.     EX0 = 1;//外部中断1
  276. }
  277. /*******************************************************************************
  278. * 函数名                                                : void IT1Init(void)
  279. * 函数功能                                        : 外部中断1初始化
  280. * 输入                                                : 无
  281. * 输出                                                : 无
  282. *******************************************************************************/
  283. void IT1Init(void)
  284. {
  285.     IT1 = 0;//0为电平,1为下降沿
  286.     EX1 = 1;//外部中断0
  287. }
  288. /*******************************************************************************
  289. * 函数名                                                : void InitUart0(void)
  290. * 函数功能                                        : 串口中断初始化
  291. * 输入                                                : 无
  292. * 输出                                                : 无
  293. *******************************************************************************/
  294. void InitUart0(void)
  295. {//设计波特率:4800bps;实际波特率:4464bps
  296.     TMOD&=0x0F;
  297.     TMOD|=0x20;
  298.     SCON=0x50;
  299.     PCON|=0x80;
  300.     TH1 = 0xF3;
  301.     TL1 = 0xF3;
  302.     ES = 1;                //使能串口中断 ,无论是TI/RI出现,只要中断打开,单片机就进入中断函数。
  303.     TR1 = 1;
  304.                 //ET1 = 0;//禁止T1中断
  305. }
  306. /*******************************************************************************
  307. * 函数名                                                : void IT1Init(void)
  308. * 函数功能                                        : 串口中断函数
  309. * 输入                                                : 无
  310. * 输出                                                : 无
  311. *******************************************************************************/
  312. void Usart() interrupt 4
  313. {

  314.         //uchar receiveData;
  315.         //receiveData=SBUF;//出去接收到的数据
  316.         RI = 0;//清除接收中断标志位
  317.         
  318.         //SBUF=receiveData;//将接收到的数据放入到发送寄存器
  319.         //while(!TI);                         //等待发送数据完成
  320.         //TI=0;                                                 //清除发送完成标志
  321.         //massage[0]=0;
  322.         


  323. }
  324. /*******************************************************************************
  325. * 函数名                                                : void send_byte(uchar by)
  326. * 函数功能                                        : 串口发送字节函数
  327. * 输入                                                : 无
  328. * 输出                                                : 无
  329. *******************************************************************************/
  330. void send_byte(uchar by)
  331.         {

  332.     SBUF = by;
  333.     while(!TI);//当写下这句的时候,就不要在中断函数里面在写TI = 0;这句了,不然进入中断函数将TI清零之后,程序就会一直卡在这里
  334.     TI = 0;       //在这里将TI清零
  335.         }
  336. /*发送一个字符串*/
  337. /*******************************************************************************
  338. * 函数名                                                : void send_string(uchar *p)
  339. * 函数功能                                        : 串口发送字符串函数
  340. * 输入                                                : 无
  341. * 输出                                                : 无
  342. *******************************************************************************/
  343. void send_string(uchar *p)
  344.         {

  345.     while(*p!= '\0')
  346.                         {
  347.    
  348.         send_byte(*p);
  349.         p++;

  350.                         }
  351.         }
  352. /*******************************************************************************
  353. * 函数名                                                : void DtoA(unsigned long dat, unsigned char* buffer)
  354. * 函数功能                                        : 串口发送字符串函数
  355. * 输入                                                : 无
  356. * 输出                                                : 无
  357. *******************************************************************************/
  358.         
  359. void DtoA(uint dat, unsigned char* buffer)
  360. {
  361. uint tmp = 0;
  362. char length = 0;
  363. tmp = dat;
  364. while(tmp != 0)//求出数字的实际长度
  365. {
  366. tmp = tmp/10;
  367. length++;
  368. }
  369. buffer[length] = '\0';//长度数为字符串截止位
  370. length--;

  371. while(length >= 0)//数字的低位放入数组的高位
  372. {
  373. tmp = dat%10;
  374. buffer[length--] = 0x30|tmp;

  375. dat = dat/10;
  376. }
  377. }
复制代码
全部资料51hei下载地址:
PID恒温控制器.zip (113.68 KB, 下载次数: 20)



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

使用道具 举报

沙发
ID:507401 发表于 2019-4-25 12:58 | 只看该作者
沒有看到PID實現的函數呀!
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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