⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pidcode.txt

📁 pid闭环控制的几个比较好的源码
💻 TXT
📖 第 1 页 / 共 2 页
字号:
PID算法汇集(C语言)
/*main.c*/
/*DA模块两路(OUT1、OUT2)输出三角波经AD10次采样并与之比较经数字滤波、双闭环PID调节后PWM生成以及经逆变后电压控制*/
#include "global.c"
void  SystemInit();
void  SPI_Init();
void  DA_OUT(unsigned CHANNEL,unsigned int RNG,unsigned int SPI_DATA);
void  AD_Sample();
void  Que();
void  ADCINT();
void  PWM_Init();
void  KickDog();
unsigned int i,j,numled0,AD_0,AD_8,AD_FLAG=0,AD0[10],AD8[10],Voltage=0,RESULT_0,RESULT_8,t0=0,t1=0,t2=625,t3=625,t0_back=0,PB6_FLAG=0;
unsigned int T1;
float U_KP=10,U_KI=0.1,U_KD=0.8,U_REF=310,U_EK,U_EK1,U_EK2,U_RK,U_RK1,U_U,U_ELPI,
             I_KP=10,I_KI=0.1,I_REF,I_EK,I_EK1,I_EK2,I_RK,I_RK1,I_U,U_MAX=80,U_MIN=20,I_MIN=200,I_MAX=1000;
    
float AD_SIG0=0.0,AD_SIG8=0.0;
main()
{
 SystemInit();
 MCRA=MCRA & 0xC0FF;       //IOPB0-6设为IO口模式
 PBDATDIR=0xFFC2;         //所有LED=0 
 PBDATDIR=PBDATDIR |0x003D;   //所有LED=1  
 SPI_Init();
 PWM_Init();            //定时器、EVA初始化
 asm(" CLRC INTM ");
          
 while(1)
   {
      if(AD_FLAG==1)                
       { 
        AD_FLAG=0;
         for(i=0;i<10;i++) 
         { 
          AD_Sample();   
          AD0[i]=RESULT_0;
          AD8[i]=RESULT_8;
         }
         Que();   //数字滤波(去极值平均滤波)
           ADCINT();     //PIADJUSTS()
           
          
        }
   }
} 
void  SystemInit()
{
  
 asm(" SETC INTM "); /* 关闭总中断 */
 asm(" CLRC  SXM  "); /* 禁止符号位扩展 */ 
 asm(" CLRC  CNF  ");    /* B0块映射为 on-chip DARAM*/
 asm(" CLRC  OVM  ");    /* 累加器结果正常溢出*/
 SCSR1=0x83FE;          /* 系统时钟CLKOUT=20*2=40M */
          /* 打开ADC,EVA,EVB,CAN和SCI的时钟*/
 WDCR=0x006F;   /* 禁止看门狗,看门狗时钟64分频 */ 
 KickDog();       /* 初始化看门狗 */  
    IFR=0xFFFF;    /* 清除中断标志 */
    IMR=0x0003;    /* 打开中断1、2*/      
    
}
void  SPI_Init()
{
  
    MCRB=MCRB | 0x0014;     //SPISIMO,SPICLK特殊功能方式 
    PBDATDIR=PBDATDIR | 0x0002;     //CS_DA=1
    SPICCR=0x004a;          //11bit数据
    SPICTL=0x0006;          //禁止中断
    SPIBRR=0x0027;           //1M波特率,40M/40=1M
    SPICCR=SPICCR | 0x80;   
}
void DA_OUT(unsigned CHANNEL,unsigned int RNG,unsigned int SPI_DATA)
{  
    unsigned char flag=0;
    SPITXBUF=(CHANNEL<<14)|(RNG<<13)|(SPI_DATA<<5) ;      //bit10,9~CHANNEL;bit8~RNG倍数
    while(1)
    {
    flag=SPISTS&0x40;
    if(flag==0x40)     break;
    }
    SPIRXBUF=SPIRXBUF;/*虚读寄存器以清除中断标志*/      
    PBDATDIR=PBDATDIR & 0xFFFD;  //CS_DA=0,更新模拟信号输出   
    for(i=0;i<5;i++);              //延时
    PBDATDIR=PBDATDIR | 0x0002;     //CS_DA=1,锁存数据   
    
}
void AD_Sample()
{   
    ADCTRL1=0x4000;   /* ADC模块复位 */
    asm(" NOP ");
    ADCTRL1=0x0020;         /* 自由运行,启动/停止模式,双排序器工作模式 */
    
    MAXCONV=0x0000; 
    CHSELSEQ1=0x0000;       //第0通道
    ADCTRL2=0x4000;         //复位使排序器指针指向CONV00
    ADCTRL2=0x2000;   /* 启动ADC转换 */
    while( (ADCTRL2&0x1000)==0x1000);  /*等待转换完成 */
    asm(" NOP ");
    asm(" NOP "); 
    RESULT_0=RESULT0>>6; 
            
    MAXCONV=0x0000;         //第8通道          
    CHSELSEQ3=0x0008;
    ADCTRL2=0x0040;
    ADCTRL2=0x0020;
    while( (ADCTRL2&0x0010)==0x0010);  
    asm(" NOP ");
    asm(" NOP ");
    RESULT_8=RESULT8>>6;           
    
 }
void Que()
{
   unsigned int MaxAD0=0;
   unsigned int MinAD0=AD0[0];
   unsigned int MaxAD8=0;
   unsigned int MinAD8=AD8[0];
   unsigned int tempAD0=0;
   unsigned int tempAD8=0;
   for(j=0;j<10;j++)
   {
      if(AD0[j]>MaxAD0)   MaxAD0=AD0[j];
      else if(AD0[j]<MinAD0)   MinAD0=AD0[j]; 
      if(AD8[j]>MaxAD8)   MaxAD8=AD8[j];
      else if(AD8[j]<MinAD8)   MinAD8=AD8[j];  
     
   }  
   for(j=0;j<10;j++)
   {
      tempAD0=tempAD0+AD0[j];
      tempAD8=tempAD8+AD8[j];
    } 
    AD_0=(tempAD0-MaxAD0-MinAD0)/8; 
    AD_8=(tempAD8-MaxAD8-MinAD8)/8; 
    AD_SIG0=AD_0*4.983/1023;      //1023~3.3*(10+5.1)/10=4.983V,对应满量程
    AD_SIG8=AD_8*4.983/1023;            //电路中采用的是5.1k和10k的电阻分压
    asm(" NOP ");          //请将光标移到此处设置断点,并用debug->Animate监测数据
}      
// AD中断服务子程序
void  ADCINT()
{
   asm(" clrc    SXM"); // 抑制符号位扩展
   
   U_RK1=U_RK;     
   U_EK=AD0[i]-U_REF;                     
   U_U=U_RK1+U_KP*(U_EK-U_EK1)+U_KI*U_EK+U_KD*(U_EK-2*U_EK1+U_EK2);
   
   if(U_U<=1000) I_REF=0;             
   else if(U_U>1000) {I_REF=I_MAX;        
   U_EK2=U_EK1;U_EK1=U_EK;}                        
 
    
   I_RK1=I_RK;
   I_EK=AD8[i]-I_REF;
   I_U=I_RK1+I_KP*(I_EK-I_EK1)+I_KI*I_EK;
   T1=t2+t3;
   if(I_U<=625) t3=625;           // 输出更新脉冲截止时间t3         
   else if(I_U>=1875)t3=1875;         
   else t3=t3+50;                   
   
   asm(" clrc INTM");
}
void PWM_Init()           
{ 
    MCRA=MCRA | 0x00C0;
    EVAIMRA=0x0080;   //  定时器1周期中断使能 
    EVAIFRA=0xFFFF;   //  清除中断标志 
    GPTCONA=0x0100;         //  定时器1周期中断标志启动AD转换      
 T1CNT=0;
 T1CON=0x0C4E;            //增/减模式, TPS系数40M/16=2.5M,T1使能
   
    ACTRA=0x0006;          
    DBTCONA=0x0530;          //使能死区定时器1,分频40M/16=2.5M,死区时间5*0.4us=2us  
    T1PR=T1;                  
    CMPR1=t2;              //占空比为0-100%             
 
 COMCONA=0xA600;         
         
}  
void c_int2()               /*定时器1中断服务程序*/
{
    if(PIVR!=0x27)
  {   asm(" CLRC INTM ");
   return;
  }
 T1CNT=0; 
 t1++;
 numled0--;
 if(numled0==0)
 {
  numled0=200;
  if((PBDATDIR & 0x0001)==0x0001) 
   PBDATDIR=PBDATDIR & 0xFFFE;     //IOPB0=0;LED灭  
  else
   PBDATDIR=PBDATDIR |0x0101;      //IOPB0=1;LED亮 
 }
 if(Voltage<0) Voltage=0;
    DA_OUT(0,0,Voltage);                //Voltage范围0-255对应0-3.3V
    DA_OUT(1,0,Voltage);                //Voltage范围0-255对应0-3.3V
    DA_OUT(2,0,192);                //2.475V,Voltage范围0-255对应0-3.3V
    DA_OUT(3,0,128);                //1.65V,Voltage范围0-255对应0-3.3V
    if(t0<255)  Voltage++;
      else  Voltage--; 
    if(Voltage<0) Voltage=0;
    if(t0==508)     t0=0;
    t0++;  
     if((AD_FLAG==0)&((t1%100)==0))     //定时AD采样
      {  
     AD_FLAG=1;
     }
    
       EVAIFRA=0x80;
       asm(" CLRC INTM ");
}
void KickDog()   
{
 WDKEY=0x5555;
 WDKEY=0xAAAA;
}
 
/*====================================================================================================
    这是从网上找来的一个比较典型的PID处理程序,在使用单片机作为控制cpu时,请稍作简化,具体的PID
参数必须由具体对象通过实验确定。由于单片机的处理速度和ram资源的限制,一般不采用浮点数运算,
而将所有参数全部用整数,运算到最后再除以一个2的N次方数据(相当于移位),作类似定点数运算,可
大大提高运算速度,根据控制精度的不同要求,当精度要求很高时,注意保留移位引起的“余数”,做好余
数补偿。这个程序只是一般常用pid算法的基本架构,没有包含输入输出处理部分。
=====================================================================================================*/
#include <string.h>
#include <stdio.h>
/*====================================================================================================
    PID Function
    
    The PID (比例、积分、微分) function is used in mainly
    control applications. PIDCalc performs one iteration of the PID
    algorithm.
    While the PID function works, main is just a dummy program showing
    a typical usage.
=====================================================================================================*/
typedef struct PID {
        double  SetPoint;           //  设定目标 Desired Value
        double  Proportion;         //  比例常数 Proportional Const
        double  Integral;           //  积分常数 Integral Const

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -