大家好,我用tm4c123gh6pm这款launchpad做一个控制的系统,这个系统有两个环,内环使用adc0采样一个交流通道,16次硬件平均后触发中断进行一次
浮点pid运算,这样
内环的运行速度是62.5k左右,然后外环使用adc1采样一个交流通道和两个直流通道,64次硬件平均后触发中断,进行次1次浮点pid,这样
外环运行速率就是1Msps/64/3大约为5.2K。
现在的问题是,adc采样和外环是都没问题的,内环我通过反转IO来观察,发现根本没有60K,波形紊乱,大约只有20多k,FPU我是
#include "driverlib/fpu.h"
ROM_FPUEnable();
ROM_FPULazyStackingEnable();
这样初始化的,但是发现加不加没有明显变化,听说CCS里process options中浮点支持选项默认开启FPU我就没有深究这一点,然后我在项目属性里把编译器优化里的size-speed开到最大,没有明显变化,float-point mode选为relaxed,现在一下子速度就上去了,
但是不论是速度快或慢,我总发现单步跟踪时有些语句不能到达,甚至观察有些语句比如一个0.17 * 1竟然返回了0,所以我现在一头雾水,不知道接下来该怎么调试,
不知道是FPU没有开启成功造成的浮点混乱还是TM4不能运算这么快速度。
现在我自己感觉可能是1、编译器优化选项开的过大,数据精度损失。2、或者是这两个环都是在中断里面执行的,没有处理好中断应该注意的问题(中断里面的变量我后来都加上了volatile,但是没有变化)3、FPU没有开启成功,运算速度跟不上中断速度导致数据混乱。4.不知道如果我用IQMath能不能快点,有做过的坛友们看看可不可行
我在deyisupport上提问没有回答,来论坛找找高手们,希望大家不吝赐教,项目比较急,谢谢大家了。
下面附上关键地方的代码
/******************adc初始化*********************/
void initADC(void) {
//首先配置ADC0为电流内环高速采样中断
ROM_ADCSequenceConfigure(ADC0_BASE, ac_cur_sequence, ADC_TRIGGER_ALWAYS, 3);//配置AD采样序列,持续触发采样,最低优先级
ROM_ADCHardwareOversampleConfigure(ADC0_BASE,16); //8位的硬件平均值滤波
ROM_ADCSequenceStepConfigure(ADC0_BASE, ac_cur_sequence, 0,ADC_CTL_CH0 | ADC_CTL_IE |ADC_CTL_END);//CH0<-->PE3,差分采样CH0通道数据,步进0,采样接收产生中断信号
ROM_ADCSequenceEnable(ADC0_BASE, ac_cur_sequence); //使能ADC_IN使用的采样序列
ROM_ADCIntEnable(ADC0_BASE, ac_cur_sequence);
ROM_IntEnable(INT_ADC0SS0);
ROM_IntMasterEnable(); //使能中断
ROM_ADCIntClear(ADC0_BASE, ac_cur_sequence); //清零中断标志
//然后配置ADC1为电压外环低速采样
ROM_ADCSequenceConfigure(ADC1_BASE, other_sequence, ADC_TRIGGER_ALWAYS, 2);//配置AD采样序列,定时器触发采样,高于内环优先级
ROM_ADCHardwareOversampleConfigure(ADC1_BASE,64); //8位的硬件平均值滤波
ROM_ADCSequenceStepConfigure(ADC1_BASE, other_sequence, 0,ADC_CTL_CH1); //步骤0
ROM_ADCSequenceStepConfigure(ADC1_BASE, other_sequence, 1,ADC_CTL_CH2); //步骤1
ROM_ADCSequenceStepConfigure(ADC1_BASE, other_sequence, 2,ADC_CTL_CH4 | ADC_CTL_IE |ADC_CTL_END); //步骤2,最后产生中断
ROM_ADCSequenceEnable(ADC1_BASE, other_sequence); //使能ADC_IN使用的采样序列
ROM_ADCIntEnable(ADC1_BASE, other_sequence);
ROM_IntEnable(INT_ADC1SS1);
ROM_IntMasterEnable(); //使能中断
ROM_ADCIntClear(ADC1_BASE, other_sequence); //清零中断标志
}
/*************************adc0 高速电流反馈层************************/
float cur_delta;
float modle_factor_add;
uint32_t ac_cur_advalue;
void adcsq0Int() {
ROM_GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_4, 0);
ROM_GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_4, GPIO_PIN_4);
ROM_ADCSequenceDataGet(ADC0_BASE, ac_cur_sequence, &ac_cur_advalue);
ac_cur_now = ac_cur_advalue / 4095.0 * 3.3; //当前交流电流值
cur_delta = ac_cur_now - cur_point; //计算当前电流与指令电流的误差
modle_factor_add = PidDeltaCal(&pid_delta_ac, cur_delta); //pid当前电流误差
modle_factor = modle_factor + modle_factor_add; //计算累加量
modle_factor = modle_factor * 500;
//然后调制PWM脉宽值
if (modle_factor > 200 && modle_factor < 800) //为了安全,限制范围在20%~80%
adjustPWMWidth((unsigned int) (1000 - modle_factor)); //反向调制
ROM_GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_4, 0);
ROM_ADCIntClear(ADC0_BASE, ac_cur_sequence);
}
/*************************adc1电压外环计算*************************/
/*
* other_value[3]数组的值依次是 VAC/VDC/IDC
*/
uint32_t sin_para = 0;
float volt_delta;
float ism_factor_add;
void adcsq1Int() {
ROM_GPIOPinWrite(GPIO_PORTA_BASE, GPIO_PIN_2, 0);
ROM_GPIOPinWrite(GPIO_PORTA_BASE, GPIO_PIN_2, GPIO_PIN_2);
ROM_ADCSequenceDataGet(ADC1_BASE, other_sequence, other_value); //读取直流电压值
dc_volt_now = other_value[1] / 4095.0 * 3.3; //获得当前直流电压值
dc_cur_now = other_value[2] / 4095.0 * 3.3; //当前直流电流
ac_volt_now = other_value[0] / 4095.0 * 3.3; //当前交流电压
volt_delta = dc_volt_now - volt_ref; //计算Vdc - Vref误差值(-2048~2048)
ism_factor_add = PidDeltaCal(&pid_delta_dc, volt_delta);//计算PID调节(输出控制在)
ism_factor = ism_factor + ism_factor_add; //累加增量式PID的输出结果
//TODO 切断外环测试
ism_factor = 1;
sin_para++;
ac_volt_now = 3.3 * sinf(sin_para / 104 * 2 * M_PI);
// cur_point = ism_factor * ac_volt_now; //计算当前电流 期望逼近量
cur_point = ac_volt_now; //计算当前电流期望逼近量
if (sin_para > 104)
sin_para = 0;
ROM_GPIOPinWrite(GPIO_PORTA_BASE, GPIO_PIN_2, 0);
ROM_ADCIntClear(ADC1_BASE, other_sequence);
}
此帖出自
小平头技术问答
这个我也是本版的一个坛友Linchpin的笔记发现的,感谢@Linchpin的总结与分享
解决了就好 哈哈
一周热门 更多>