AVR STUDIO4仿真中定时器T1工作在模式快速PWM,为什么是双斜坡计数?
用AVR STUDIO4仿真中定时器T1工作在模式快速PWM,应该是单斜坡计数,即计数到MAX后下一个周期变成0,再次向上进行计数。但我用软件进行仿真时,却发现计数到MAX后却是再做-1的双斜坡计数。我的程序是用CVAVR生成的,没有改过一个字节。是什么原因? 大哥我也遇到了你同样的问题,您解决了吗?能告诉我吗? 写一个单独的测试程序,进行模拟.如果有问题,将代码帖上来. #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 charPIDoutput1=0,PIDe1=0,PIDe2=0;
unsigned charpi_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 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 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) //当饱和时输出最大值
{
return1024;
}
else if(PIDoutput<=0) //当小于零输0
{
return0;
}
else if(PIDoutput>=0&PIDoutput<=200)
{
returnPIDoutput;
}
}
/**************************************
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) //当饱和时输出最大值
{
return1024;
}
else if(pi_PIDoutput<=0) //当小于零输0
{
return0;
}
else if(pi_PIDoutput>=0&pi_PIDoutput<=200)
{
returnpi_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仿真就是出不来效果,想请教马潮老师 结果是双边PWM不是单边的 3楼,测试T1快速PWM,也不用这么长的程序吧. 我试过了,这个好象是AVR STUDIO的问题.
我在里面模拟了M16的T0的快速PWM是正确的,但是T1的几个快速PWM都是双向计数方式,与手册不不符.
但模拟128的T1,快速PWM却是对的.
应该以手册为准,AVR STUDIO有问题. 谢谢马潮老师!!!!!!!!!太感谢了!!!
那个我弄错了,以为是传一部分代码上来,下次明白了 忘记留下结论了,确实是AVR STUDIO的问题,硬件实际运行没有错。 今天遇到和你差不多的问题,感觉PWM时,AVR STUDIO 不给力啊
页:
[1]