搜索
bottom↓
回复: 9

AVR STUDIO4仿真中定时器T1工作在模式快速PWM,为什么是双斜坡计数?

[复制链接]

出0入0汤圆

发表于 2008-3-29 20:11:49 | 显示全部楼层 |阅读模式
用AVR STUDIO4仿真中定时器T1工作在模式快速PWM,应该是单斜坡计数,即计数到MAX后下一个周期变成0,再次向上进行计数。但我用软件进行仿真时,却发现计数到MAX后却是再做-1的双斜坡计数。我的程序是用CVAVR生成的,没有改过一个字节。是什么原因?

阿莫论坛20周年了!感谢大家的支持与爱护!!

月入3000的是反美的。收入3万是亲美的。收入30万是移民美国的。收入300万是取得绿卡后回国,教唆那些3000来反美的!

出0入0汤圆

发表于 2008-5-15 13:55:57 | 显示全部楼层
大哥我也遇到了你同样的问题,您解决了吗?能告诉我吗?

出0入0汤圆

发表于 2008-5-15 14:23:11 | 显示全部楼层
写一个单独的测试程序,进行模拟.如果有问题,将代码帖上来.

出0入0汤圆

发表于 2008-5-31 11:06:06 | 显示全部楼层
#include <mega16.h>
#include <math.h>
/*****************************************
pid定义
****************************************/
#define adc_result   100
#define kp            5
#define ki            2
#define kd            1
#define T            30
double PID_Calculate(double PIDe0);
double PID_turn(double p,double q);
double value_Calculate(void);
void compare_adc_result(void);
double value_Calculate(void);
static unsigned char pid_stste=0;
int PID_output=0;
unsigned char  PIDoutput1=0,PIDe1=0,PIDe2=0;
unsigned char  pi_PIDoutput1=0,pi_PIDe1=0,pi_PIDe2=0;
/********************************
先前设定量
********************************/
unsigned int time_value0=40;
unsigned int degree_value0=140; //从前面的程序中得来
/*******************************
定时器变量
********************************/
unsigned int key_stime_counter, key_stime_counter1,key_stime_counter2;
bit        key_stime_ok, key_stime_ok1= 1,key_stime_ok2 ,key_stime_ok3,time_compare_ok;

interrupt [TIM0_COMP] void timer0_comp_isr(void)
{
         //key_check();
      if (++key_stime_counter >=5)
             {  
                key_stime_counter = 0;
                key_stime_ok = 1;                // 10ms到
                //adc_degree=read_adc();
                //p+=adc_degree/10;
           if(++key_stime_counter1>=50)
                {   
                   key_stime_counter1 = 0;
                   key_stime_ok1= 1;
                   time_compare_ok=1;                                 //500ms到
                   // adc_result= p/5;
                   // p=0;
                   //   ADC_DISBUFFER();
                   //  ADC_TIMEDISBUFFER();
            if(++key_stime_counter2>=2)
                   {   
                        key_stime_counter2 = 0;
                        key_stime_ok2= 1;
                         key_stime_ok3= 1;
                        // display_adc();
                    }  
                 }
         }
}

// Timer 1 overflow interrupt service routine
interrupt [TIM1_OVF] void timer1_ovf_isr(void)
{
   OCR1A=PID_output;

}
/****************************************************
pid计算控制
***************************************************/
double PID_Calculate(double PIDe0)
   {   
  
      double sum_error;
      double h,temper;
      int PIDoutput;
      sum_error+=PIDe0;
      h=abs(PIDe0);
      if(h<=3)
          {
              
             PIDoutput=kp* PIDe0+ki*sum_error;                         //pi控制
           }   
              
       else
           {  
              
              temper=(kp+ki+kd)*PIDe0-(kp+2*kd)*PIDe1+kd*PIDe2;            //pid控制
              PIDoutput=PIDoutput1+temper;
             }

        PIDoutput1=PIDoutput;
        PIDe2=PIDe1;
        PIDe1=PIDe0;
              
       if(PIDoutput>=1024)                                          //当饱和时输出最大值
           {  
                return  1024;                 
           }
       else if(PIDoutput<=0)                                        //当小于零输0
            {  
                 return  0;     
            }
       else if(PIDoutput>=0&PIDoutput<=200)
             {   
                 return  PIDoutput;
             }
         
    }   
/**************************************
pi控制
****************************************/
double PD_Calculate(double PIDe0)
{   
        
        
        double pi_sum_error;
        int pi_PIDoutput;
        pi_sum_error+=PIDe0;
        pi_PIDoutput=kp* PIDe0+ki*pi_sum_error;                         //pi控制
        pi_PIDoutput1=pi_PIDoutput;
        pi_PIDe2=pi_PIDe1;
        pi_PIDe1=PIDe0;
        if(pi_PIDoutput>=1024)                                          //当饱和时输出最大值
           {  
                return  1024;                 
           }
        else if(pi_PIDoutput<=0)                                        //当小于零输0
            {  
                 return  0;     
            }
        else if(pi_PIDoutput>=0&pi_PIDoutput<=200)
             {   
                 return  pi_PIDoutput;
             }

}
/****************************************
pid差量计算
******************************************/

double PID_turn(double p,double q)
   {     
         double PID_e0;
         PID_e0=p-q;
         return   PID_e0;
   }
/********************************************
把区间分为2*timer_value0倍,控制温度沿曲线上升
********************************************/

double value_Calculate(void)
{
    double y;
    static unsigned char x=0;   
    if(key_stime_ok1)
     {                  
       key_stime_ok1= 0;

       if(x<=time_value0)
          {
              x+=0.5;
           }
       }
      y=(degree_value0-160)/(time_value0*time_value0)*(x-T-time_value0)+160;
        return y;
}
/**************************************
检测值比较判断
**************************************/            
void compare_adc_result(void)
   {   

       static unsigned char x=3;
       double PID_OUT, PID_in;
       switch(pid_stste)
           {
               case 0:
                      if(adc_result<125)
                          {  
                             double h0,error0;
                             PID_OUT=adc_result;
                             PID_in=120;
                             error0=PID_turn(PID_in,PID_OUT);
                             h0=abs(error0);
                             if(h0<=3)
                                    {   
                                        if(time_compare_ok)
                                          {
                                              time_compare_ok=0;
                                              --x;
                                              if(x==0)
                                                {   
                                                    x=3;
                                                    ++pid_stste;
                                                 }
                                            }
                                     }
                                                                  
                             PID_output=255;
                          }
                       else ++pid_stste;
                       break;

                case 1:   
                       if(adc_result<=145)
                            {   
                                  double h1,error1;  
                                  PID_OUT=adc_result;
                                  PID_in=degree_value0;
                                  error1=PID_turn(PID_in,PID_OUT);
                                  h1=abs(error1);                              
                                 if(h1<=3)
                                       {   
                                          if(time_compare_ok)
                                            {  
                                                 time_compare_ok=0;
                                                 --x;
                                                 if(x==0)
                                                    {   
                                                       x=3;
                                                       ++pid_stste;
                                                     }
                                              }
                                        }
                                 
                                 PID_output=PID_Calculate(error1);
                                
                            }
                       else ++pid_stste;
                        break;
               
                case 2:  
                        if(adc_result<=165)
                           {
                                 double h2,error2;
                                 PID_in=value_Calculate();
                                 PID_OUT=adc_result;
                                 error2=PID_turn(PID_in, PID_OUT);
                                 h2=abs(error2);
                                 if(h2<=3)
                                       {   
                                          if(time_compare_ok)
                                               {  
                                                 time_compare_ok=0;
                                                 --x;
                                                 if(x==0)
                                                    {   
                                                       x=3;
                                                       ++pid_stste;
                                                     }
                                              }
                                        }
                         PID_output=PID_Calculate(error2);
                             }
                         else ++pid_stste;
                         break;

                case 3:        
                         if(adc_result<=230)
                             {  
                                 double h3,error3;
                                 PID_OUT=adc_result;
                                 PID_in=230;
                                 error3=PID_turn(PID_in, PID_OUT);
                                 h3=abs(error3);
                                 if(h3<=3)
                                    {   
                                        if(time_compare_ok)
                                          {  
                                              time_compare_ok=0;
                                              --x;
                                              if(x==0)
                                                {   
                                                    x=3;
                                                    ++pid_stste;
                                                 }
                                            }
                                     }
                                                                  
                              
                                PID_output=PD_Calculate(error3);
                          }
                         else ++pid_stste;
                         break;
                case 4:
                         PID_output=0;
                         pid_stste=0;
                        
                         //stop_flag=1;
                         //stop_device();
                         pid_stste=0;
                         break;
                 }
    }
void main(void)
{

PORTD=0x00;
DDRD=0x20;
ASSR=0x00;
TCCR0=0x0C;
TCNT0=0x00;
OCR0=0x7C;
TCCR1A=0xC3;
TCCR1B=0x05;
TCNT1H=0x00;
TCNT1L=0x00;
OCR1AH=0x00;
OCR1AL=0x56;
OCR1BH=0x00;
OCR1BL=0x00;
ASSR=0x00;
TIMSK=0x06;
ACSR=0x80;
SFIOR=0x00;
#asm("sei")

while (1)
      {
      compare_adc_result();

      };
}
用AVR STUDIO4仿真就是出不来效果,想请教马潮老师

出0入0汤圆

发表于 2008-5-31 11:07:15 | 显示全部楼层
结果是双边PWM不是单边的

出0入0汤圆

发表于 2008-5-31 18:24:22 | 显示全部楼层
3楼,测试T1快速PWM,也不用这么长的程序吧.

出0入0汤圆

发表于 2008-6-1 11:58:51 | 显示全部楼层
我试过了,这个好象是AVR STUDIO的问题.

我在里面模拟了M16的T0的快速PWM是正确的,但是T1的几个快速PWM都是双向计数方式,与手册不不符.

但模拟128的T1,快速PWM却是对的.

应该以手册为准,AVR STUDIO有问题.

出0入0汤圆

发表于 2008-6-3 00:31:16 | 显示全部楼层
谢谢马潮老师!!!!!!!!!太感谢了!!!
那个我弄错了,以为是传一部分代码上来,下次明白了

出0入0汤圆

 楼主| 发表于 2008-6-18 13:55:33 | 显示全部楼层
忘记留下结论了,确实是AVR STUDIO的问题,硬件实际运行没有错。

出0入0汤圆

发表于 2011-11-3 17:51:04 | 显示全部楼层
今天遇到和你差不多的问题,感觉PWM时,AVR STUDIO 不给力啊
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-4-27 11:04

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

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