永发信息网

8位单片机PID控制PWM的算法如何实现,C语言计算?

答案:3  悬赏:30  手机版
解决时间 2021-03-27 14:09
  • 提问者网友:却不属于对方
  • 2021-03-27 00:06
8位单片机PID控制PWM的算法如何实现,C语言计算?
最佳答案
  • 五星知识达人网友:洎扰庸人
  • 2021-03-27 01:32
PID控制在8位单片机中仍然有广泛的应用,比如温度控制,利用比例、积分、微分补偿来做恒温补偿控制,当然由于有这些数学处理,用C语言相对方便一些,以下是一个具体的实例。
#include  
#include  
#include  
#include  
struct PID {  
unsigned int SetPoint; // 设定目标 Desired Value  
unsigned int Proportion; // 比例常数 Proportional Const  
unsigned int Integral; // 积分常数 Integral Const  
unsigned int Derivative; // 微分常数 Derivative Const  
unsigned int LastError; // Error[-1]  
unsigned int PrevError; // Error[-2]  
unsigned int SumError; // Sums of Errors  
};  
struct PID spid; // PID Control Structure  
unsigned int rout; // PID Response (Output)  
unsigned int rin; // PID Feedback (Input)  
sbit data1=P1^0;  
sbit clk=P1^1;  
sbit plus=P2^0;  
sbit subs=P2^1;  
sbit stop=P2^2;  
sbit output=P3^4;  
sbit DQ=P3^3;  
unsigned char flag,flag_1=0;  
unsigned char high_time,low_time,count=0;//占空比调节参数  
unsigned char set_temper=35;  
unsigned char temper;  
unsigned char i;  
unsigned char j=0;  
unsigned int s;  
 
void delay(unsigned char time)  
{  
     unsigned char m,n;  
     for(n=0;n     for(m=0;m<2;m++){}  
}  
 
void write_bit(unsigned char bitval)  
{  
  EA=0;  
  DQ=0;  
if(bitval==1)  
{  
  _nop_();  
  DQ=1;  
}  
 delay(5);  
 DQ=1;  
_nop_();  
_nop_();  
EA=1;  
}  
 
void write_byte(unsigned char val)  
{  
     unsigned char i;  
    unsigned char temp;  
    EA=0;  
    TR0=0;  
for(i=0;i<8;i++)  
{  
  temp=val>>i;  
  temp=temp&1;  
  write_bit(temp);  
}  
  delay(7);  
// TR0=1;  
  EA=1;  
}  
 
unsigned char read_bit()  
{  
unsigned char i,value_bit;  
EA=0;  
DQ=0;  
_nop_();  
_nop_();  
DQ=1;  
for(i=0;i<2;i++){}  
value_bit=DQ;  
EA=1;  
return(value_bit);  
}  
 
unsigned char read_byte()  
{  
unsigned char i,value=0;  
EA=0;  
for(i=0;i<8;i++)  
{  
if(read_bit())  
value|=0x01<delay(4);  
}  
EA=1;  
return(value);  
}  
 
unsigned char reset()  
{  
unsigned char presence;  
EA=0;  
DQ=0;  
delay(30);  
DQ=1;  
delay(3);  
presence=DQ;  
delay(28);  
EA=1;  
return(presence);  
}  
 
void get_temper()  
{  
unsigned char i,j;  
do  
{  
   i=reset();  
}  while(i!=0);  
     i=0xcc;  
   write_byte(i);  
   i=0x44;  
   write_byte(i);  
   delay(180);  
do  
{  
   i=reset();  
}  while(i!=0);  
   i=0xcc;  
   write_byte(i);  
   i=0xbe;  
   write_byte(i);  
   j=read_byte();    
   i=read_byte();  
   i=(i<<4)&0x7f;  
   s=(unsigned int)(j&0x0f);     //得到小数部分 
   s=(s*100)/16;  
   j=j>>4;  
   temper=i|j;  
}  
 
void PIDInit (struct PID *pp)  
{  
memset ( pp,0,sizeof(struct PID));    //全部初始化为0 
}  
 
unsigned int PIDCalc( struct PID *pp, unsigned int NextPoint )  
{  
unsigned int dError,Error;  
Error = pp->SetPoint - NextPoint;          // 偏差     
pp->SumError += Error;                     // 积分     
dError = pp->LastError - pp->PrevError;    // 当前微分   
pp->PrevError = pp->LastError;     
pp->LastError = Error;  
return (pp->Proportion * Error             // 比例项     
+ pp->Integral * pp->SumError              // 积分项  
+ pp->Derivative * dError);                // 微分项  
}  
 
void compare_temper()  
{  
unsigned char i;  
if(set_temper>temper)      //是否设置的温度大于实际温度 
{  
   if(set_temper-temper>1)  //设置的温度比实际的温度是否是大于1度 
  {  
   high_time=100;      //如果是,则全速加热 
   low_time=0;  
  }  
       else  //如果是在1度范围内,则运行PID计算 
  {  
    for(i=0;i<10;i++)  
  {  
    get_temper();   //获取温度 
     rin = s; // Read Input  
    rout = PIDCalc ( &spid,rin ); // Perform PID Interation  
  }  
    if (high_time<=100)  
      high_time=(unsigned char)(rout/800);  
    else  
          high_time=100;  
      low_time= (100-high_time);  
  }  
}  
else if(set_temper<=temper)  
{  
   if(temper-set_temper>0)  
  {  
    high_time=0;  
    low_time=100;  
  }  
   else  
  {  
     for(i=0;i<10;i++)  
   { 
         get_temper();  
         rin = s; // Read Input  
     rout = PIDCalc ( &spid,rin ); // Perform PID Interation  
   }  
     if (high_time<100)  
      high_time=(unsigned char)(rout/10000);  
       else  
      high_time=0;  
      low_time= (100-high_time);  
  }  
}  
// else  
// {}  
}  
 
void serve_T0() interrupt 1 using 1  
{  
if(++count<=(high_time))  
output=1;  
else if(count<=100)  
{  
output=0;  
}  
else  
count=0;  
TH0=0x2f;  
TL0=0xe0;  
}  
 
void serve_sio() interrupt 4 using 2  
{  
 
}  
void disp_1(unsigned char disp_num1[6])  
{  
unsigned char n,a,m;  
for(n=0;n<6;n++)  
{  
// k=disp_num1[n];  
 for(a=0;a<8;a++)  
 {  
     clk=0;  
  m=(disp_num1[n]&1);  
  disp_num1[n]=disp_num1[n]>>1;  
  if(m==1)  
   data1=1;  
  else  
   data1=0;  
   _nop_();  
   clk=1;  
   _nop_();  
 }  
}  
}  
 
void display()  
{  
unsigned char code number[]={0xfc,0x60,0xda,0xf2,0x66,0xb6,0xbe,0xe0,0xfe,0xf6};  
unsigned char disp_num[6];  
unsigned int k,k1;  

k=high_time;  
k=k%1000;  
k1=k/100;  
if(k1==0)  
disp_num[0]=0;  
else  
disp_num[0]=0x60;  
k=k%100;  
disp_num[1]=number[k/10];  
disp_num[2]=number[k%10];  
k=temper;  
k=k%100;  
disp_num[3]=number[k/10];  
disp_num[4]=number[k%10]+1;  
disp_num[5]=number[s/10];  
disp_1(disp_num);  
}  
 
void main()  
{  
unsigned char z; 
unsigned char a,b,flag_2=1,count1=0;  
unsigned char phil[]={2,0xce,0x6e,0x60,0x1c,2}; 
TMOD=0x21;  
TH0=0x2f;  
TL0=0x40;  
SCON=0x50;  
PCON=0x00;  
TH1=0xfd;  
TL1=0xfd;  
PS=1;  
EA=1;  
EX1=0;  
ET0=1;  
ES=1;  
TR0=1;  
TR1=1;  
high_time=50;  
low_time=50;  
PIDInit ( &spid );    // Initialize Structure  
spid.Proportion = 10; // Set PID Coefficients  比例常数 Proportional Const  
spid.Integral = 8;    //积分常数 Integral Const  
spid.Derivative =6;   //微分常数 Derivative Const  
spid.SetPoint = 100; // Set PID Setpoint 设定目标 Desired Value  
while(1)  
 {  
if(plus==0)  
 { 
EA=0;  
for(a=0;a<5;a++)  
for(b=0;b<102;b++){}  
if(plus==0)  
  { 
set_temper++;  
flag=0;  
  } 
 }  
else if(subs==0)  
  {  
for(a=0;a<5;a++)  
for(b=0;a<102;b++){}  
if(subs==0)  
{  
 set_temper--;  
 flag=0;  
}  
  }  
else if(stop==0)  
{  
     for(a=0;a<5;a++)  
    for(b=0;b<102;b++){}  
    if(stop==0)  
{  
   flag=0;  
   break;  
}  
   EA=1;  
}  
       get_temper();  
   b=temper;  
if(flag_2==1)  
  a=b;  
if((abs(a-b))>5)  
  temper=a;  
else  
  temper=b;  
  a=temper;  
  flag_2=0;  
if(++count1>30)  
{  
  display();  
  count1=0;  
}  
  compare_temper();  
}  
   TR0=0;  
   z=1;  
while(1)  
{  
    EA=0;  
if(stop==0)  
{  
     for(a=0;a<5;a++)  
    for(b=0;b<102;b++){}  
    if(stop==0)  
    disp_1(phil);  
// break;  
}  
EA=1;  
}  

我要举报
如以上回答内容为低俗、色情、不良、暴力、侵权、涉及违法等信息,可以点下面链接进行举报!
点此我要举报以上问答信息
大家都在看
推荐资讯