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

📄 main.c

📁 柴油发动机的电控PID代码。平台freescale的MC9S12DZ60单片机。核心算法
💻 C
📖 第 1 页 / 共 5 页
字号:
      button1_flag = 1;  //set
    }
  } 
  else
  {
    button1_flag = 0;  //clear
    PORTB_BIT6 = 0; //enable no rotation protection
  }    
  
  if(PORTA_BIT1 == 0)   //按钮1:停车
  {
    delay(); //delay 5ms,prevent twitter
    if(PORTA_BIT1 == 0)
      button2_flag = 1;  //set
  } 
  else
    button2_flag = 0;  //clear      
  
  if(PORTA_BIT2 == 0)   //按钮2:待定义
  {
    delay(); //delay 5ms,prevent twitter
    if(PORTA_BIT2 == 0)
      button3_flag = 1;  //set
  } 
  else
    button3_flag = 0;  //clear  
    
   if(PORTA_BIT3 == 0)   //按钮4:待定义
  {
    delay(); //delay 5ms,prevent twitter
    if(PORTA_BIT3 == 0)
      button4_flag = 1;  //set
  } 
  else
    button4_flag = 0;  //clear    
    
  /*if(first_ovrot_flag == 1)  //first over rotation
  {
    set_rot = 650;  //拉至怠速
    //open_ovrot();   //打开超速保护
  } */

 
  /*if(no_mrot_flag == 1)  //no main rotation
  {
    PORTA_BIT5 = 1;
  }
  else
  {
    PORTA_BIT5 = 0;
  }  

  if(no_srot_flag == 1)  //no sub rotation
  {
    PORTA_BIT6 = 1;
  }
  else
  {
    PORTA_BIT6 = 0;
  } */ 
}

/****************************************************************************
* 函数名称:get_rotation()																												
* 函数功能:采集反馈转速																													
* 入口参数:无																															
* 出口参数:无																																
*****************************************************************************/
void get_rotation(void) 
{
  uint t1,t2;
  //long int rotation;
  //uint rota;
  //rotation = pre_fb_rot;
  t1 = pre_tc0;
  t2 = TC0;
  pre_tc0 = t2;
  if(t1 != t2) //当前捕捉寄存器不等于0或者捕捉值变化,计算转速
  {
    if(t2 > t1) 
    {
      ltemp = 15000000/(t2-t1);
    }
    else 
    {
      ltemp = 15000000/(65535-t1+t2);
    }
  }
  fb_rot = (uint)(ltemp);
  //return(rota);
}

/****************************************************************************
* 函数名称:insert(uchar f)																											
* 函数功能:插值程序																								        
* 入口参数:f:1,主程序调用。0,中断调用																															*
* 出口参数:运算结果 uint result																														
****************************************************************************/     
int insert(uchar f) 
{
  //int resu;
  long int temppp;
  switch(f)
  {
    case 0:
    {
      temppp = x - x1;
      temppp *= (y2 - y1);
      temppp /= (x2 - x1);
      temppp += y1;// + temppp;
      //resu = (int)temppp;
      //result = y1 + (x-x1) * (y2-y1) / (x2-x1);
      //return((int)temppp);
      break; 
    }
    case 1:
    {
     //long int temppp;
      temppp = x12 - x11;
      temppp *= (y22 - y11);
      temppp /= (x22 - x11);
      temppp += y11;// + temppp;
      //resu = (int)temppp;
      //result = y1 + (x-x1) * (y2-y1) / (x2-x1);
      //return((int)tempp); 
      break;
    }
    default:
      break; 
  }
  return((int)temppp);
}
/****************************************************************************
* 函数名称:comp()																											
* 函数功能:限制数值程序																								        
* 入口参数:2个比较数																											
* 出口参数:返回结果																														
****************************************************************************/
int comp(int a,int b)
{
  if(a > b)
  {
    return(b);
  }
  else if(a < -b)
  {
    return(-b);
  }
  return(a);   
}

/****************************************************************************
* 函数名称:pid_rot()																										
* 函数功能:转速环pid子程序																							
* 入口参数:无																													
* 出口参数:无																													
*****************************************************************************/
void pid_rot(void) 
{
  /* 变量定义 */  
  //uint *p,*q;
  //uchar average_times;
  //int x1,x2,y1,y2,x;
  //uint cak_set_rot;
  //uint cak_fb_rot = fb_rot;
  
  //设定转速平滑滤波  
  pre_set_rot *= 7;
  pre_set_rot += set_rot;
  pre_set_rot /= 8;
  
  /* 计算偏差 */
  //if(state_flag != DYNAF) 
  //{
  /*cak_fb_rot[7] = cak_fb_rot[6];
  cak_fb_rot[6] = cak_fb_rot[5];
  cak_fb_rot[5] = cak_fb_rot[4];
  cak_fb_rot[4] = cak_fb_rot[3];
  cak_fb_rot[3] = cak_fb_rot[2];
  cak_fb_rot[2] = cak_fb_rot[1];
  cak_fb_rot[1] = cak_fb_rot[0];
  cak_fb_rot[0] = fb_rot;
  filtered_fb_rot = cak_fb_rot[0] + cak_fb_rot[1] + cak_fb_rot[2] 
  + cak_fb_rot[3] + cak_fb_rot[4] + cak_fb_rot[5] + cak_fb_rot[6] 
  + cak_fb_rot[7];
  filtered_fb_rot /= 8;*/              
  
  /*if((fb_rot <= nrm.rt540 - (int)SCHMITT) 
  || ((fb_rot <= nrm.rt540 + SCHMITT) && (average_times == 2))) 
  {
    average_times = 2;
  }
  
  if(((fb_rot <= nrm.rt540 + SCHMITT) && (average_times == 4)) ||
     ((fb_rot >= nrm.rt540 + SCHMITT) && (fb_rot <= nrm.rt541 
     - (int)SCHMITT)) ||
     ((fb_rot <= nrm.rt541 + SCHMITT) && (average_times == 4))) 
  {
    average_times = 4;
  }

  if(((fb_rot <= nrm.rt541 + SCHMITT) && (average_times == 8)) ||
     ((fb_rot >= nrm.rt541 + SCHMITT) && (fb_rot <= nrm.rt542 
     - (int)SCHMITT)) ||
     ((fb_rot <= nrm.rt542 + SCHMITT) && (average_times == 8))) 
  {
    average_times = 8;
  }
  
  if((fb_rot > nrm.rt542 + SCHMITT) || ((fb_rot <= nrm.rt542 + SCHMITT) 
  && (average_times == 16))) 
  {
    average_times = 16;
  } */
  if(fb_rot < nrm.rt540)
  {
    average_times = 2;
  }
  if((fb_rot > nrm.rt540 + SCHMITT) && fb_rot < nrm.rt541)
  {
    average_times = 4;
  }
  if((fb_rot > nrm.rt541 + SCHMITT) && fb_rot < nrm.rt542)
  {
    average_times = 8;
  }
  if(fb_rot > nrm.rt542 + SCHMITT) 
  {
    average_times = 16;
  }
  pre_fb_rot *= (average_times - 1);
  pre_fb_rot += fb_rot;
  pre_fb_rot /= average_times; 
  if( (nrm.rdrop == 255) || (stksi > MAXKI) ) 
  {
    drop_rot = 0; //调速率在16-255之外或者stksi大于MAXKI,调速率不起作用
  }
  else 
  {
    drop_rot = pre_fb_exe / nrm.rdrop;
    drop_rot *= 4;
  } /* end if */
  delta_rot = (pre_set_rot - (int)drop_rot) - pre_fb_rot;//get delta rotation
  
  //pid运算
  if((fb_rot > (rot.lmt2 + SCHMITT)) //判断进入哪个环 
     || ((fb_rot > rot.lmt2) && (rp_flag == 0)))
  {
    rp_flag = 0; //设置转速环运算标志 
    // KP 
    temp = delta_rot;
    temp = comp(temp,704);
    //参数动静态分离 
    /*if(state_flag == DYNAF) 
    {
      if(temp > nrm.rbandw) 
      {
        temp = 2*temp - (int)nrm.rbandw;
      }
      else if(temp < -(int)nrm.rbandw)
      {
        temp = 2*temp + (int)nrm.rbandw;
      } 
    } */
    //参数高低速分离
    if(fb_rot > nrm.rsphlsp + SCHMITT) //高速 
      stksp = nrm.rksp;
    else if(fb_rot < nrm.rsphlsp)  //低速
      stksp = nrm.rksp1;
    
    x1 = RPSEPA;
    y1 = LKSP;
    x2 = 1023;
    y2 = stksp;
    x = pre_fb_exe;
    if(x < x1)
    {
      caksp = LKSP;
    }
    else
    {
      caksp = insert(0);
    }
    temp *= (int)stksp; //here no insertion
    temp /= 10;
    temp1 = temp;
    //KD 
    temp = delta_rot - pre_delta_rot; //soft
    pre_delta_rot = delta_rot;
    temp = comp(temp,70);    
    // 参数高低速分离
    if(fb_rot > nrm.rsphlsp + SCHMITT) //高速 
      stksd = nrm.rksd;
    else if(fb_rot < nrm.rsphlsp)  //低速
      stksd = nrm.rksd1; 
    x1 = RPSEPA;
    y1 = LKSD;
    x2 = 1023;
    y2 = stksd;
    x = pre_fb_exe;
    if(x < x1)
    {
      caksd = LKSD; 
    }
    else 
    {
      caksd = insert(0);
    }    
    //参数动静态分离 
    /*if(state_flag == DYNAF) 
    {
      stksd *= 2;
    }  */
    
    temp *= (int)stksd; 
    temp /= 8;
    temp += kd_output;
    temp /= 2;
    temp = (temp + kd_output) / 2;
    temp2 = temp;
    kd_output = temp2;
    //KA 
    temp = kd_output - pre_kd_output;//soft
    pre_kd_output = kd_output;
    temp = comp(temp,80);                          
    temp *= (int)nrm.rdynaw;
    temp += ka_output;
    temp /= 2;
    temp = (temp + ka_output)/2;
    temp3 = temp;
    ka_output = temp3;  
    //KI 
    ltemp = comp(delta_rot,512);
    //temp = (long int)temp;
    sum_delta_rot += ltemp;
    if(sum_delta_rot > max_sum_rot)
      sum_delta_rot = max_sum_rot;
    else if(sum_delta_rot < min_sum_rot)
      sum_delta_rot = min_sum_rot;
    //参数高低速分离 
    if(fb_rot > nrm.rsphlsp + SCHMITT) //高速 
      stksi = nrm.rksi;
    else if(fb_rot < nrm.rsphlsp)  //低速
      stksi = nrm.rksi1;
    if(stksi >= MAXKI)                    
      temp4 = 0;  //积分超过最大,则取消积分
    ltemp = sum_delta_rot / (int)stksi;
    ltemp /= 2;
    temp4 = (int)ltemp;
    //rtemp4 = 0; //取消积分
    
    // 计算设定位置set_exe 
    //temp = temp1 + temp2 + temp3 + temp4; //PID
    temp = temp1 + temp2 + temp3;    //PD
    //rtempx = temp4;  //for 积分测试
    temp = comp(temp,limt1/2);
    temp += (limt1 / 2);
    set_exe = (uint)temp;
  }
  else   
  {
    rp_flag = 1; //设置位置环运算标志
    set_exe = limt1;
  }/* end if */
  //计算油量限制limt1
  if(pre_fb_rot >= rot.lmt12)
  {
    limt1 = 0;  //超速,油量限制归零
  }
  else if(pre_fb_rot <= rot.lmt1)
  {
    limt1 = oil.lmt1;
  }
  else
  {
    p = &rot.lmt1;
    q = &oil.lmt1;
    while(pre_fb_rot > *p)
    {
      p++;
      q++;
    } 
    //插值求油量限制limt1
    x2 = *p;
    y2 = *q;
    p--;
    q--;
    x1 = *p;
    y1 = *q;
    x = pre_fb_rot;
    limt1 = insert(0);
  }
  /*p = &rot.lmt1;
  q = &oil.lmt1;
  do //确定转速范围
  {
    p++;
    q++;
  }
  while(pre_fb_rot > *p);*/
  
  //计算max_sum_rot,min_sum_rot 
  //max_sum_rot = 2 * stksi * limt1 - OFFSET;
  //max_sum_rot = 9 * stksi * limt1 / 10;
  max_sum_rot = 9 * stksi;
  max_sum_rot *= limt1;
  max_sum_rot /= 10;
  min_sum_rot = limt1 * stksi; 
  min_sum_rot = -(long int)min_sum_rot;
  //dynamic-static separate
  if((set_rot >= SEPSPD) && ((delta_rot > (int)nrm.rbandw) 
     || (delta_rot < -(int)nrm.rbandw)))
  {
    state_flag = DYNAF;
    PORTB_BIT2 = 0;
  }  
  else 
  {
    state_flag = STATF;
    PORTB_BIT2 = 1;
  }
}

/****************************************************************************
* 函数名称:pid_exe()																												
* 函数功能:位置环pid子程序																							
* 入口参数:无																														
* 出口参数:无																														
****************************************************************************/
void pid_exe(void) 
{
  //变量定义  
  //int x1,x2,y1,y2,x;
  //计算偏差
  pre_set_exe += set_exe;
  pre_set_exe /= 2;
  pre_fb_exe += fb_exe;
  pre_fb_exe /= 2;
  delta_exe = pre_set_exe - pre_fb_exe;
  //插值求stpkp 
  x1 = PSEPA;
  y1 = LPKP;
  x2 = 1023;
  y2 = nrm.rpkp;
  x = pre_fb_exe;
  if(x > x1)
  {
    stpkp = insert(0);
  }
  else
  {
    stpkp = LPKP;
  } 
    
  //插值求stpkd
  y1 = LPKD;
  y2 = nrm.rpkd;
  if(x > x1)
  {
    stpkd = insert(0);
  }
  else 
  {
    stpkd = LPKD;
  }
  //PKP 
  temp = delta_exe;
  temp = comp(temp,255);// 偏差限制 
  temp *= (int)nrm.rpkp;//计算, 没用到插值
  temp /= 2; 
  temp1 = temp;  
  //PKD 
  temp = delta_exe - pre_delta_exe;  // 偏差计算 soft
  pre_delta_exe = delta_exe;
  //temp = hard_pkd - V0CNV;    //hard
  temp = comp(temp,255);//偏差限制
  temp *= (int)nrm.rpkd;//没用插值
  temp /= 2; 
  temp = (temp + pkd_exe) / 2;
  temp2 = temp;
  pkd_exe = temp2;
  //PKA 
  temp = pkd_exe - pre_pkd_exe; //偏差计算,soft
  pre_pkd_exe = pkd_exe;
  //temp = V0CNV - hard_pka  ;  //hard
  temp = comp(temp,127);//偏差限制
  temp *= (int)nrm.rpdynaw;
  temp /= 2;
  //temp = temp * (int)nrm.rpdynaw / 2;
  temp = (temp + pka_exe) / 2;
  temp3 = temp;

⌨️ 快捷键说明

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