主题中讨论的其他器件:MSP-IQMATHLIB
工具/软件:Code Composer Studio
我已经编写了一个用于在电机上实现 PID 控制的代码。 代码如下:
#include /** * main.c */ int main (void){ WDTCTL = WDTPW + WDTHOLD;//禁用看门狗计时器 P2DIR = BIT2;//选择和设置计时器模块的输出位 P2SEL = BIT2; BCSCTL1 = CALBC1_16MHz;//将时钟频率设置为16MHz ;/CACT_TAC1MHz 计时器= CC1000;/CACT_TACT_TALP0;//将时钟频率设置为16MHz; //为要生成的 PWM 总时间提供计数 TA1CCTL1 = OUTMOD_7;//将计时器模式设置为在设置复位模式下计数 TA1CTL = MC_1 + ID_0 + TASSEL_2 + TACLR; //MC_1是模式控制1它意味着定时器在增模式中计数 //ID_0是时钟分频器1、TASSEL_2选择 SMCLK 和 TACLR 清除定时器(这使定时器从0开始计数) //ADC 模块 ADC10CTL0 = ADC10ON + ADC10IE + SREF_1 + REFON + REMSC 5V + REF2 + REF2 + MCU_5V; //启用中断,将基准设置为2.5V ADC10CTL1 = ADC10DIV_0 + CONSEQ_2;//时钟分频和 CONSEQ_2用于单通道重复转换 ADC10AE0 = INCH_0;//通道0上可用的输入(即引脚 A0 ADC10CTL0 |= ENC + ADC10SC;//开始转换 (BIS_1 ),同时启用中断 #pragma vector = ADC10_Vector __interrupt void ADC10_interrupt (void){ P2DIR |= 0x01;//set P2.0 P2OUT |= 0x01;//将 P2.0设置为高电平(用于检查循环运行所需的时间) float SET_point = 2.24、t_on;//设置点为2.24V float Kp = 1、IMKp = 1、Imax = 2.24、IMKp = 1、Imax = 2.24、IMKp = 1、IMKp = 2.24、IM pi_term、pi_min = 0、pi_max = 2; 静态浮点 i_term = 0; int adc_val = ADC10MEM;//将 ADC 值分配给变量 float adc_out =(float)(adc_val * 2.5/1024);//根据基准将十六进制值缩放到电压、给定 float 错误= set_point - adc_out; //从 ADC 获取错误和设定点 //比例项 p_term = Kp *错误; //积分项 静态浮点 i_temp = 0; i_temp = I_temp +错误;//计算积分项 if (i_temp > Imax)//积分抗饱和 i_temp = Imax; 否则 if (i_temp < in)/i_imp = iimp-in; I_term = ki * I_temp;//final I_term //spi term /* float d_temp = error;//检查这是否存在静态 d_term = Kd *(d_temp-error);//检查计算*//PI term pi_term = p_term + i_term; //剪切输出 pi_term = p_if (pi_term = p_max) = p_term = p_term = p_max;// p_term = p_term = p_term = p_max (pi_term = p_term = p_min) T_ON =(pi_term * 1000)/pi_max; TA1CCR1 = t_on;//根据 pi_term P2OUT ^= 0x01设置导通时间;//将 P2.0设置为低电平(用于检查循环运行所需的时间) _BIS_SR (GIE);//全局中断使能 }
我所面临的问题是:
1) 1)我必须计算 PI 环路运行所需的时间。 为此、我在控制环路的开头将一个引脚设为高电平、并在末尾将其切换 我已经检查了 DSO 上该引脚的输出。 令人惊讶的是、中断只被调用一次。 因此、我在运行代码时只会在示波器上看到一个尖峰。
2) 2)因此、我尝试将控制环路置于 while (1){}循环中。 现在、当我重复这里的相同过程时、要切换引脚、我观察到完全不同的意外行为。 当我在开始时将引脚保持为高电平、并在结束时切换时、DSO 会显示一个时序图、其中高电平脉冲持续280微秒的较长时间、低电平脉冲持续0.5微秒。 这似乎是正确的。 但是、当我以另一种方式执行它时、即在环路的开头、将引脚设置为低电平。 DSO 向我显示占空比为50%的脉冲、时间周期为(2*280)微秒。
#include /** * main.c */ int main (void){ WDTCTL = WDTPW + WDTHOLD;//禁用看门狗计时器 P2DIR = BIT2;//选择和设置计时器模块的输出位 P2SEL = BIT2; BCSCTL1 = CALBC1_16MHz;//将时钟频率设置为16MHz ;/CACT_TAC1MHz 计时器= CC1000;/CACT_TACT_TALP0;//将时钟频率设置为16MHz; //为要生成的 PWM 总时间提供计数 TA1CCTL1 = OUTMOD_7;//将计时器模式设置为在设置复位模式下计数 TA1CTL = MC_1 + ID_0 + TASSEL_2 + TACLR; //MC_1是模式控制1它意味着定时器在增模式中计数 //ID_0是时钟分频器1、TASSEL_2选择 SMCLK 和 TACLR 清除定时器(这使定时器从0开始计数) //ADC 模块 ADC10CTL0 = ADC10ON + ADC10IE + SREF_1 + REFON + REMSC 5V + REF2 + REF2 + MCU_5V; //启用中断、将基准设置为2.5V ADC10CTL1 = ADC10DIV_0 + CONSEQ_2;//时钟分频和 CONSEQ_2用于单通道重复转换 ADC10AE0 = INCH_0;//通道0上可用的输入如 A0引脚 A0 ADC10CTL0 |= ENC + ADC10SC;//开始转换 while = 0xP201;//设置 P2DIR = 0x00;// //将 P2.0设置为低电平(用于检查循环运行所需的时间) float set_point = 2.24、t_on;//设置点为2.24V float Kp = 1、ki = 1、p_term、Imax = 2.24、Imin = 0、 pi_term、pi_min = 0、pi_max = 2; 静态浮点 i_term = 0; int adc_val = ADC10MEM;//将 ADC 值分配给变量 float adc_out =(float)(adc_val * 2.5/1024);//根据基准将十六进制值缩放到电压、给定 float 错误= set_point - adc_out; //从 ADC 获取错误和设定点 //比例项 p_term = Kp *错误; //积分项 静态浮点 i_temp = 0; i_temp = I_temp +错误;//计算积分项 if (i_temp > Imax)//积分抗饱和 i_temp = Imax; 否则 if (i_temp < in)/i_imp = iimp-in; I_term = ki * I_temp;//final I_term //spi term /* float d_temp = error;//检查这是否存在静态 d_term = Kd *(d_temp-error);//检查计算*//PI term pi_term = p_term + i_term; //剪切输出 pi_term = p_if (pi_term = p_max) = p_term = p_term = p_max;// p_term = p_term = p_term = p_max (pi_term = p_term = p_min) T_on =(pi_term * 1000)/pi_max; TA1CCR1 = t_on;//根据 pi_term P2OUT ^= 0x01设置导通时间;//设置 P2.0翻转(用于检查循环运行所需的时间) //_BIS_SR (GIE);//全局中断启用 }