帮忙改下430程序

2019-03-24 12:52发布

小弟使用msp430和WDD35精密电位器(角度反馈),加入PID控制直流电机转动角度的,帮忙看下程序哪里写的不对了,谢谢了。

#include  <msp430x14x.h>
#include  "BoardConfig.h"
#include  "cry1602.h"
#define   Num_of_Results   32
uchar shuzi[] = {"0123456789."};
uchar tishi[] = {"The volt is:"};
static uint results[Num_of_Results];    //保存ADC转换结果的数组                                                     // is not used for anything.
void Trans_val(uint Hex_Val);           //十六进制转十进制
/**************************AD采样*********************************/
void EnableAD()
{
  P6SEL |= 0x02;                            // 使能ADC通道
  ADC12CTL0 = ADC12ON+SHT0_8+MSC;           // 打开ADC,设置采样时间
  ADC12CTL1 = SHP+CONSEQ_2+ CSTARTADD_1;    // 使用采样定时器
  ADC12MCTL1=INCH_1;                        //ref+=AVcc,channel=A1
  ADC12IE = 0x02;                           // 使能ADC中断
  ADC12CTL0 |= ENC;                         // 使能转换
  ADC12CTL0 |= ADC12SC;                     // 开始转换
}
/***********定义结构体*****************/
typedef struct PID
{
    int SetPoint;           //设定目标  Desired Value
    double Proportion;      //比例常数  Proportional Const
    double Integral;        //积分常数  Integral Const
    double Derivative;      //微分常数  Derivative Const
    int LastError;          //Error[-1]
    int PrevError;          //Error[-2]
} PID;
/******************定义相关宏********************/
#define P_DATA  1
#define I_DATA  0
#define D_DATA  0
#define HAVE_NEW_ANGLE 0X01  //?????
static PID sPID;
static PID *sptr = &sPID;
int g_CurrentAngle;
int g_Flag;
/******************PID 参数初始化***************/
void IncPIDInit(void)
{
    sptr->LastError = 0;             //Error[-1]
    sptr->PrevError = 0;             //Error[-2]
    sptr->Proportion = P_DATA;       //比例常数  Proportional Const
    sptr->Integral = I_DATA;         //积分常数  Integral Const
    sptr->Derivative = D_DATA;       //微分常数  Derivative Const
    sptr->SetPoint =100;             //目标是 100
}
/*******************PID计算************************/
int IncPIDCalc(int NextPoint)
{
    int iError, iIncpid;                     //当前误差
    iError = sptr->SetPoint - NextPoint;     //增量计算
    iIncpid = sptr->Proportion * iError      //E[k]项
              - sptr->Integral * sptr->LastError     //E[k-1]项
              + sptr->Derivative * sptr->PrevError;  //E[k-2]项
    sptr->PrevError = sptr->LastError;       //存储误差,用于下次计算
    sptr->LastError = iError;
    return(iIncpid);                         //返回增量值
}
/************************主函数****************************/
void main(void)
{
  WDTCTL = WDTPW+WDTHOLD;                   //关闭看门狗
  BoardConfig(0xb8);                        //关闭数码管、流水灯、4245
  
  IncPIDInit();                  //PID的参数初始化, 以设定工作需要的P,I,D参数.
  g_CurrentAngle=0;              //全局变量也初始化
  g_Flag=0;                      //全局变量也初始化
  
  LcdReset();                               //复位1602液晶
  DispNChar(2,0,12,tishi);                  //显示提示信息
  Disp1Char(11,1,'V');                      //显示电压单位
  EnableAD();                               //开始采样角度值
  TACTL=TASSEL0+TACLR+MC0;
  CCTL0=0X00;
  CCTL1=0X00;
  CCR0=330;
  CCTL1=OUTMOD_7;
  _EINT();
While(1)
    {
        if (g_Flag& HAVE_NEW_ANGLE)      //g_Flag& HAVE_NEW_VELOCITY==1,说明新的采样,已经有了,要多新的采样速度,进行PID运算
        {
            U0+= IncPIDCalc(CurrentAngle);  //根据采样的当前角度,进行pid运算,计算增量数值,然后复制给U0以调节角度
            g_Flag&=~ HAVE_NEW_ANGLE;           //设置完新的角度,将标志位复位,防止没有采样新的角度,再次进入if中,重复进行PID运算.
        }
    }
}
/********************定时器中断******************/
#pragma vector=TIMERA1_VECTOR
__interrupt void TIMER_A(void)
{
    CurrentAngle =GetCurrentAngle;        //定时器中断,采样角度,复制给CurrentAngle
    g_Flag|= HAVE_NEW_ANGLE;              //每次进入中断,将标志位置一
}
/*******************************************
函数名称:ADC12ISR
功    能:ADC中断服务函数,在这里用多次平均的
          计算P6.0口的模拟电压数值,输出PWM
参    数:无      
返回值  :无
********************************************/
#pragma vector=ADC_VECTOR
__interrupt void ADC12ISR (void)
{
  static uint index = 0;
  unsigned long AA;
  uint BB;
  results[index++] = ADC12MEM1;               // Move results
  if(index == Num_of_Results)
  {
        uchar i;
        unsigned long sum = 0;
        index = 0;
        for(i = 0; i < Num_of_Results; i++)
        {
            sum += results;
        }
            sum >>= 5;                            //除以32
        Trans_val(sum);
      AA=sum;
      AA=(AA<<5)+sum;
      AA=(AA<<3)+(AA<<1);
      BB=AA>>12;
        if(BB<=5)   
           CCR1=0;
        else CCR1=BB;
      P1DIR |=0X04;      //P1.2输出
      P1SEL |=0X04;
  }        
}
/*******************************************
函数名称:Trans_val
功    能:将16进制ADC转换数据变换成三位10进制
          真实的模拟电压数据,并在液晶上显示
参    数:Hex_Val--16进制数据
          n--变换时的分母等于2的n次方      
返回值  :无
********************************************/
void Trans_val(uint Hex_Val)
{
    unsigned long caltmp;
    uint Curr_Volt;
    uchar t1,i;
    uchar ptr[4];
   
    caltmp = Hex_Val;
    caltmp = (caltmp << 5) + Hex_Val;           //caltmp = Hex_Val * 33
    caltmp = (caltmp << 3) + (caltmp << 1);     //caltmp = caltmp * 10
    Curr_Volt = caltmp >> 12;                   //Curr_Volt = caltmp / 2^n
    ptr[0] = Curr_Volt / 100;                   //Hex->Dec变换
    t1 = Curr_Volt - (ptr[0] * 100);
    ptr[2] = t1 / 10;
    ptr[3] = t1 - (ptr[2] * 10);
    ptr[1] = 10;                                //shuzi表中第10位对应符号"."
    //在液晶上显示变换后的结果
    for(i = 0;i < 4;i++)
      Disp1Char((6 + i),1,shuzi[ptr]);   
} 此帖出自小平头技术问答
0条回答

一周热门 更多>

相关问题

    相关文章