新闻  |   论坛  |   博客  |   在线研讨会
PID算法程序
yanghongjun | 2010-06-17 15:50:47    阅读:22507   发布文章

#include <C8051F020.H>
#include <string.h>
#include <math.h>
//void PIDInit(PID *PP);
/*定义结构体和公用体*/
#define N  8
typedef struct PID{
unsigned int setpoint;  /*设定值*/
unsigned int proportion;      /*比例系数*/
unsigned int integral;      /*积分系数*/
unsigned int derivative;      /*微分系数 */
unsigned int lasterror;      /*前一拍误差*/
unsigned int preerror;      /*前两拍误差*/
 }PID;
 
 union stu{
unsigned  int value;
unsigned char num[2];
 }laser;

union dat{
 unsigned char dd[2];
 unsigned int number;
 }collect;

/*函数声明部分*/
unsigned int PIDcal(PID *pp,int thiserror);
 void PIDInit(PID *PP);
 void PortInit(void);
 unsigned int get_ad(void);
 unsigned int filter_valve(void);
 void Delayms(void);

 /*主函数部分*/
 void main(void)
 {

  PID vPID;     /*定义结构体变量名*/
unsigned  int verror;
unsigned  int Error;
unsigned  int tempi;
unsigned  char LASERH,LASERL; /*误差的高低字节变量*/

  WDTCN=0xde;
 WDTCN=0xad;
//portinit();
PIDInit(&vPID);
vPID.proportion=10;  /*设置PID比例系数为10*/ 
vPID.integral=10;  /*设定PID积分系数 为10*/
vPID.derivative=10;  /*设定PID微分系数为10*/
vPID.setpoint=50;  /*根据实际情况设定*/

IE= 0x80;

while(1)
{
verror=filter_valve();  /*得到AD的滤波输出值 */
Error=vPID.setpoint-verror; /*得到误差值*/
tempi=PIDcal(&vPID,Error); /*调用PID算法函数 得到误差增量*/

laser.value+=tempi;  
LASERH=laser.num[0]; /*value与num[2]为共同体,变量名为laser*/
LASERL=laser.num[1]; /*存放高低字节*/
}
 }

/*PID算法函数,返回误差增量*/
unsigned int PIDcal(PID *pp,int thisError){
unsigned int pError,dError,iError;
unsigned int templ;
 pError=thisError-pp->lasterror;    
 iError=thisError;
 dError=thisError-2*(pp->lasterror)+pp->preerror;
 templ=pp->proportion*pError+pp->integral*iError+pp->derivative*dError;   /*增量计算*/

 pp->preerror=pp->lasterror;  /*存放误差用于下次运算*/
 pp->lasterror=thisError;

 return ((int)(templ>>8));
 }

 /*测量值*/

/*float measure(void)       已知A B 角为锐角
{      /* COSA=1/7   SIN(A+B)=14分之5倍根号3 */
/*long float value;       /*求COSB*/
/*float  A,B;
A=acos(1/7);
B=asin((5/14)*sqrt(3))-A;
if((0<A<pi/2)&&(0<B<pi/2)) return cos(B);
 } */

 /*得到ADC转换值*/
 unsigned int get_ad(void)
{
  while(AD0INT==0);
  {
  AD0INT=0;
  collect.dd[1]=ADC0H;
  collect.dd[0]=ADC0L;
  return (collect.number);
  }
}

void Timer3_ISR(void) interrupt 14
{
TMR3CN=0x7f;
//AMUX0SL=0x00;
AD0BUSY=1;
}


void Timer3_Init(unsigned char Highcounts,unsigned char Lowcounts)
 {
  TMR3CN=0x01;   /*禁止定时器3;清TF3,采用SYSCLK为时基*/
  TMR3RLH=-Highcounts; /*初始化重装载值*/
  TMR3RLL=-Lowcounts;

  TMR3L=0xff;   /*设置为立即重装在*/
  TMR3H=0xff;

  EIE2|= 0x01;   /*允许定时3中断*/
  TMR3CN|=0x06;   /*启动定时器3*/
 }

 void ADCInit(void)
 {
  ADC0CF=0x00;  /*选择ADC0的转换始终为系统时钟,增益为1*/
  ADC0CN=0xc0;  /*允许ADC0准备转换,定义低功耗跟踪方式,置AD0BUSY位为1启动ADC,寄存器数据右对齐*/
  AMX0CF=0x01;  /*选择AIN0和AIN!为通道0差分输入的正负端*/
 }
 
 /*PID初始化*/
void PIDInit(PID *PP)
 {
  memset(PP,0,sizeof(PID));
 } 

/*数字算术滤波子程序*/
unsigned int filter_valve(void)
{
unsigned char i,j,temp;
unsigned char count;
unsigned int  valve_buf[N];
unsigned int sum=0;
for(count=0;count<N;count++)
{
valve_buf[count]=get_ad();
Delayms();
}
for(j=0;j<N-1;j++)
 { for(i=0;i<N-j;i++)
 {
  if(valve_buf[i]>valve_buf[i+1])
  {
   temp=valve_buf[i];
   valve_buf[i]=valve_buf[i+1];
   valve_buf[i+1]=temp;

  }
 }
 }
for(count=1;count<N-1;count++)
 {
  sum+=valve_buf[count];
  return (unsigned int)(sum/(N-2));
 }
}
 
/*延时子程序*/
void Delayms(void)
{
unsigned int ms;
unsigned char i;
while(ms--)
 {
 for(i=0;i<120;i++);
 }
}

*博客内容为网友个人发布,仅代表博主个人观点,如有侵权请联系工作人员删除。

参与讨论
登录后参与讨论
推荐文章
最近访客