找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1979|回复: 4
收起左侧

为什么我的单片机程序输出PWM频率2-3秒才反应一次呢求大佬

[复制链接]
ID:688939 发表于 2020-3-18 00:09 | 显示全部楼层 |阅读模式
  1. #include <main.h>                                       
  2. int  PWM_I,PWM_P;
  3. unsigned char  count  ,        high_time=0;                //占空比调节
  4. bit  flag;               
  5. uint temp_m1=0;
  6. int temp_m=0;  //温度放大100倍后的中转值
  7. int set_temp=0; //设置温度*100


  8. void InitTimer0(void)                                           //
  9. {
  10.     TMOD = 0x01;
  11.     TH0 = 0x28;
  12.     TL0 = 0x00;
  13.     EA = 1;
  14.     ET0 = 1;
  15.     TR0 = 1;


  16. }


  17. void  pid_control ()                         //PID控制
  18. {
  19.         if(set_temp>temp_m)
  20.         {
  21.         if(set_temp-temp_m>250)           //如果设定温度大于实际温度2.5度
  22.                 high_time=100;                           //全力加热
  23.                 else                                                                   //否则
  24.                 {
  25.            PWM_I=pid_calc(&temp_PID,temp_m);                  //  高电平输出PID计算值
  26.                         if(high_time<=100)
  27.                         high_time= PWM_I;                                                        //限制高电平最大100
  28.                         else
  29.                                 high_time=100;        
  30.         }
  31. }
  32.         else
  33.          high_time=0;                   //实际大于设定时输出低电平
  34. }




  35. void Timer0Interrupt(void) interrupt 1                //PWM波输出
  36. {
  37.         if(++count<=(high_time))           //
  38.         PWM=0;
  39.         else if(count<=100)
  40.         PWM=1;
  41.         else
  42.         count=0;
  43.     TH0 = 0x28;
  44.     TL0 = 0x00;
  45. }










  46. void main()//主函数
  47. {


  48.            InitTimer0();                                                         //定时器初始化
  49.     init();//初始化函数
  50.         pid_init (&temp_PID);                                        //PID初始化
  51.     temp_PID.Proportion =60;              //设置PID比例系数
  52.     temp_PID.Integral   =5;                            //设置PID积分系数
  53.     temp_PID.Derivative =2;                            //设置PID微分系数


  54.         
  55.   while(1)
  56.         {
  57.                 temp_control();//控制按键函数
  58.                
  59.                 temp_m1=get_temp(Ds18b20ReadTemp());                         //提取计算温度值


  60.                 display_real_tenp(temp_m1);                                                                 //显示函数          刷新温度        


  61.                  temp_m=unnormal_proccessing(temp_m1);                 //计数值=60  赋值温度放大100倍温度转换函数*100
  62.         
  63.                 pid_control();


  64.                                 PWM_P=high_time;
  65.                         LcdWriteCom(0x80+0X40+0x0C);
  66.                                 LcdWriteData('0'+PWM_P/100);
  67.                                  LcdWriteCom(0x80+0X40+0x0D);
  68.                                 LcdWriteData('0'+PWM_P%100/10);
  69.                                 LcdWriteCom(0x80+0X40+0x0E);
  70.                                 LcdWriteData('0'+PWM_P%10);
  71.                  }


  72.         }               




  73. void init()//初始化函数
  74. {
  75.         uint i,j;
  76.         //函数初始化


  77.         LcdInit();//LCD初始化函数
  78.         Ds18b20Init();                   //18b20初始化
  79.         
  80.         //I/O口初始化
  81.         PWM=0;//不制热


  82.         
  83.         //LCD初始化显示
  84.         LcdWriteCom(0x80);//第一行显示
  85.         j=strlen(num1);
  86.         for(i=0; i<j; i++)
  87.         {
  88.                 LcdWriteData(num1[i]);        [/i][i]
  89.                 delay_ms(1);
  90.         }
  91.         LcdWriteCom(0x80+0x40);//第二行显示
  92.         j=strlen(num2);
  93.         for(i=0; i<j; i++)
  94.         {
  95.                 LcdWriteData(num2[i]);        [/i][i]
  96.                 delay_ms(1);
  97.         }
  98.         LcdWriteCom(0x04);  //关闭写一个指针加1


  99. }


  100. uint get_temp(uint temp)//计算温度函数
  101. {
  102.         float tp;
  103.         
  104.         tp=temp;//因为数据处理有小数点所以将温度赋给一个浮点型变量
  105.         //如果温度是正的那么,那么正数的原码就是补码它本身
  106.         temp=tp*0.0625*100+0.5;        
  107.         //留两个小数点就*100,+0.5是四舍五入,因为C语言浮点数转换为整型的时候把小数点
  108.         //后面的数自动去掉,不管是否大于0.5,而+0.5之后大于0.5的就是进1了,小于0.5的就
  109.         //算加上0.5,还是在小数点后面。
  110.         return temp;
  111. }


  112. void display_real_tenp(uint temp)//实时温度显示函数
  113. {
  114.         uchar datas[] = {0, 0, 0, 0}; //定义数组


  115.         datas[0] = temp % 10000 / 1000;
  116.         datas[1] = temp % 1000 / 100;
  117.         datas[2] = temp % 100 / 10;
  118.         datas[3] = temp % 10;

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


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


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


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


  129.         
  130. }


  131. void temp_control()//控制温度上下限函数
  132. {
  133.         if(limit_choise==0)//选择按键
  134.         {
  135.                 delay_ms(5);
  136.                 if(limit_choise==0)
  137.                 {
  138.                         while(!limit_choise);
  139.                         limit_choise_num++;
  140.                         if(limit_choise_num>=2)
  141.                         {
  142.                                 limit_choise_num=0;
  143.                         }
  144.                 }
  145.         }
  146.         if(limit_choise_num==0)//正常显示
  147.         {
  148.                 LcdWriteCom(0x0c);//关闭光标
  149.         
  150.         }
  151.                         
  152.         if(limit_choise_num==1)//调节上限温度
  153.         {
  154.                 LcdWriteCom(0x80+0X40+2);
  155.                 LcdWriteCom(0x0f);//开启光标
  156.                 if(increase_temperature==0)//增加温度
  157.                 {
  158.                         delay_ms(5);
  159.                         if(increase_temperature==0)
  160.                         {
  161.                                 while(!increase_temperature);
  162.                                 up_limit_temp++;
  163.                                 if(up_limit_temp>=100)
  164.                                 {
  165.                                         up_limit_temp=0;
  166.                                 }
  167.                                 //写入新数据
  168.                                 LcdWriteCom(0x80+0X40+0x03);
  169.                                 LcdWriteData('0'+up_limit_temp/10);
  170.                                 LcdWriteCom(0x80+0X40+0x04);
  171.                                 LcdWriteData('0'+up_limit_temp%10);
  172.                                 LcdWriteCom(0x80+0X40+2);//光标回写
  173.                         }
  174.                 }
  175.                 if(reduce_temperature==0)//减少温度
  176.                 {
  177.                         delay_ms(5);
  178.                         if(reduce_temperature==0)
  179.                         {
  180.                                 while(!reduce_temperature);
  181.                                 up_limit_temp--;
  182.                                 if(up_limit_temp<0)
  183.                                 {
  184.                                         up_limit_temp=99;
  185.                                 }
  186.                                 //写入新数据
  187.                                 LcdWriteCom(0x80+0X40+0x03);
  188.                                 LcdWriteData('0'+up_limit_temp/10);
  189.                                 LcdWriteCom(0x80+0X40+0x04);
  190.                                 LcdWriteData('0'+up_limit_temp%10);
  191.                                 LcdWriteCom(0x80+0X40+2);//光标回写
  192.                         }
  193.                 }


  194.         }
  195.          set_temp=up_limit_temp*100;                   //放大100倍计算
  196.         temp_PID.SetPoint   =set_temp;
  197.         
  198. }


  199. int unnormal_proccessing(uint temp)//温度转换函数
  200. {
  201.         uchar datas[] = {0, 0, 0, 0}; //定义数组
  202.         int temp1=0;


  203.         datas[0] = temp % 10000 / 1000;
  204.         datas[1] = temp % 1000 / 100;
  205.         datas[2] = temp % 100 / 10;
  206.         datas[3] = temp % 10;
  207.         temp1=datas[0]*1000+datas[1]*100+datas[2]*10+datas[3];//实际的温度乘以100
  208.          return temp1;


  209. }
复制代码
回复

使用道具 举报

ID:688939 发表于 2020-3-18 09:39 | 显示全部楼层
有没有大佬帮忙看一下
回复

使用道具 举报

ID:158375 发表于 2020-3-18 12:43 | 显示全部楼层
估计是定时中断的处理问题:
// Timer0 中断
void Timer0Interrupt(void) interrupt 1    //PWM波输出
  {
  if(++count <= (high_time))     //
    PWM=0;
  else
    if(count <= 100)
      PWM=1;
    else
      count=0;
      TH0 = 0x28;
      TL0 = 0x00;
  }
------
逻辑弄清,才能控制。
回复

使用道具 举报

ID:213173 发表于 2020-3-18 21:51 | 显示全部楼层
郗乐斌 发表于 2020-3-18 09:39
有没有大佬帮忙看一下

用了一个ds18b20温度LCD显示程序给你改成0~120都可调恒温控制程序,仿真正常,实际电路可能还要进一步完善。
0~120度PWM恒温控制LCD显示 仿真.zip (162.29 KB, 下载次数: 7)
回复

使用道具 举报

ID:688939 发表于 2020-3-21 22:09 | 显示全部楼层
wulin 发表于 2020-3-18 21:51
用了一个ds18b20温度LCD显示程序给你改成0~120都可调恒温控制程序,仿真正常,实际电路可能还要进一步完 ...

谢谢你的仿真非常稳定, 但是程序好像有些问题,关键这个不是PID控制吧
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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