3、电流采样与ADC配置:双电阻/单电阻采样策略,GD32 ADC同步触发
电流采样是FOC控制环的「眼睛」。采样不准,后面PARK变换、PI调节全是白算。我见过不少工程师在仿真里跑得挺好,一上硬件电流波形就全是毛刺,查到最后都是ADC采样时序没对齐。
这一章咱们就聚焦GD32的ADC怎么配,才能让电流环跑得稳。双电阻和单电阻两种方案我都会讲,但说实话,工业产品里双电阻是主流,单电阻更多是为了省成本。
3.1 双电阻采样 vs 单电阻采样
先看个对比表格,心里有个底:
| 对比项 | 双电阻采样 | 单电阻采样 |
|---|---|---|
| 采样电阻数量 | 2个(下桥臂串联) | 1个(直流母线串联) |
| 相电流重构 | 直接测量两相,第三相计算 | 需根据开关状态重构 |
| 最低占空比限制 | 无 | 有(需保证采样窗口) |
| ADC通道数 | 2个(同步采样) | 1个 |
| 成本 | 略高 | 低 |
| 适用场景 | 高性能伺服、工业驱动 | 低成本风机、水泵 |
双电阻采样的原理很简单:在电机三相中任意两相下桥臂串联采样电阻,测出这两相电流,第三相用基尔霍夫定律算出来。我习惯测U相和V相,W相直接 Iw = -(Iu + Iv)。这样ADC只需要两个通道,同步触发一次就搞定。
单电阻采样呢?它只在直流母线上放一个电阻。你得根据当前PWM开关状态,在特定时刻采样母线电流,再反推出各相电流。说白了,就是「猜」出三相电流。我在一个风机项目里用过,为了省5毛钱成本,结果调试花了两周——每次换向区附近电流重构都会出问题。
核心结论:如果你的产品对低速性能、零速带载有要求,老老实实用双电阻。单电阻在占空比低于10%或高于90%时,采样窗口会被压缩,重构误差会急剧增大。
3.2 GD32 ADC同步触发机制
FOC电流环要求两相电流在同一时刻被采样。如果ADC分时采样,哪怕只差几个微秒,在高速旋转时都会引入相位误差。GD32的ADC支持多种触发源,我推荐用定时器的TRGO事件来同步触发。
具体怎么做?
- 配置定时器:以TIMER0为例,设置中心对齐PWM模式。在计数器上溢或下溢时产生TRGO信号。
- 配置ADC触发源:将ADC的触发源选择为TIMER0的TRGO。GD32的ADC有规则组和注入组,电流采样用规则组就够了。
- 配置采样时间:确保ADC采样窗口落在PWM下桥臂导通区间内。
我贴一段核心配置代码,这是我在GD32F303上验证过的:
// 配置TIMER0产生TRGO
timer_parameter_struct timer_initpara;
timer_initpara.period = 3999; // 10kHz PWM
timer_initpara.prescaler = 107; // 108MHz / 108 = 1MHz
timer_initpara.alignedmode = TIMER_COUNTER_CENTER_ALIGNED;
timer_initpara.counterdirection = TIMER_COUNTER_UP;
timer_initpara.clockdivision = TIMER_CKDIV_DIV1;
timer_init(TIMER0, &timer_initpara);
// 使能TRGO输出(上溢/下溢事件)
timer_master_slave_sync_config(TIMER0, TIMER_MASTER_SLAVE_MODE_ENABLE);
timer_trigger_output_config(TIMER0, TIMER_MASTER_TRGO_UPDATE);
// 配置ADC0触发源为TIMER0 TRGO
adc_external_trigger_source_config(ADC0, ADC_INSERTED_CHANNEL, ADC0_1_EXTTRIG_INSERTED_T0_TRGO);
adc_external_trigger_config(ADC0, ADC_INSERTED_CHANNEL, ENABLE);
我的习惯:采样点选在PWM计数器下溢时刻。这时候下桥臂全部导通,相电流刚好流过采样电阻,信号最稳定。上溢时刻也可以,但要注意死区时间的影响。
3.3 采样时序与PWM对齐
为什么采样时序这么重要?你想想看,PWM开关动作会在母线上产生巨大的电流尖峰。如果ADC刚好在开关时刻采样,读到的值全是噪声。
正确的做法是:把采样窗口放在PWM周期的中间区域,避开开关沿。对于中心对齐PWM,下溢时刻(计数器=0)和上溢时刻(计数器=period)都是理想的采样点。
我画了一张时序图,帮你理清关系:
从图上你能看到:ADC触发信号与PWM下溢时刻严格对齐。每次下溢,ADC同时采样两相电流。这个时序一旦确定,整个电流环的采样频率就固定了——就是PWM频率。
3.4 ADC配置实战要点
GD32的ADC有几个关键参数需要你注意:
- 分辨率:12位是标配,但如果你母线电压只有12V,建议用12位。如果母线是48V或更高,12位也够用,但要注意采样电阻的功耗。
- 采样时间:GD32的ADC采样时间可配置为1.5~239.5个ADC时钟周期。我一般设成13.5个周期,配合1MHz的ADC时钟,采样窗口约13.5μs。这个时间足够让采样电容稳定。
- 转换模式:用规则组连续转换,但触发源要选外部触发。别用软件触发,软件触发没法保证和PWM同步。
我曾经踩过的坑:ADC时钟频率不能超过14MHz(GD32F303数据手册写的)。有次我为了加快采样速度,把ADC时钟配到了18MHz,结果转换结果非线性,电流波形像锯齿。后来查了三天才发现是时钟超限了。
下面是一个完整的ADC初始化代码片段,双电阻采样用:
// ADC0和ADC1同步初始化
void adc_current_sampling_init(void)
{
// 使能ADC时钟
rcu_periph_clock_enable(RCU_ADC0);
rcu_periph_clock_enable(RCU_ADC1);
// ADC时钟配置:ADCCLK = 108MHz / 8 = 13.5MHz
rcu_adc_clock_config(RCU_ADCCK_APB2_DIV8);
// ADC0配置
adc_special_function_config(ADC0, ADC_SCAN_MODE, ENABLE);
adc_special_function_config(ADC0, ADC_CONTINUOUS_MODE, DISABLE);
adc_data_alignment_config(ADC0, ADC_DATAALIGN_RIGHT);
adc_channel_length_config(ADC0, ADC_REGULAR_CHANNEL, 2);
// 采样时间:13.5个周期
adc_sampling_time_configure(ADC0, ADC_CHANNEL_0, ADC_SAMPLETIME_13POINT5);
adc_sampling_time_configure(ADC0, ADC_CHANNEL_1, ADC_SAMPLETIME_13POINT5);
// 外部触发配置(TIMER0 TRGO)
adc_external_trigger_source_config(ADC0, ADC_REGULAR_CHANNEL, ADC0_1_EXTTRIG_REGULAR_T0_TRGO);
adc_external_trigger_config(ADC0, ADC_REGULAR_CHANNEL, ENABLE);
// 使能ADC
adc_enable(ADC0);
delay_1ms(1);
adc_calibration_enable(ADC0);
// ADC1配置(与ADC0相同)
// ... 省略重复代码
}
3.5 采样值到实际电流的转换
ADC读到的值是数字量,你得把它转成实际电流值。公式很简单:
I_actual = (ADC_value / 4096) * Vref / R_shunt / Gain
其中:
ADC_value:ADC转换结果(0~4095)Vref:ADC参考电压(通常3.3V)R_shunt:采样电阻阻值(常用0.01Ω或0.005Ω)Gain:运放放大倍数(通常20~50倍)
举个例子:ADC读到2048,Vref=3.3V,R_shunt=0.01Ω,Gain=20。那么实际电流 = (2048/4096) * 3.3 / 0.01 / 20 = 0.825A。
我的建议:在代码里用定点数做这个转换,别用浮点。GD32没有硬件浮点单元,浮点运算会拖慢电流环。我习惯把系数提前算好,存成Q15格式,每次采样后直接乘加就行。
3.6 单电阻采样的特殊处理
如果你非要用单电阻,有几个坑必须提前知道:
- 采样窗口限制:当占空比接近0%或100%时,下桥臂导通时间太短,采样电容来不及稳定。我建议在代码里做占空比钳位,最小占空比不低于10%。
- 换向区重构:在扇区切换时,两相同时换向,母线电流无法反映单相电流。这时候需要用上一周期的电流值做预测,或者插入额外的采样点。
- ADC触发策略:单电阻需要在PWM周期内触发两次ADC——一次在中心,一次在边沿。GD32的注入组可以做到,但配置起来比双电阻麻烦不少。
说实话,除非成本压力极大,否则我不推荐单电阻。省下的几毛钱,最后都花在调试时间上了。
3.7 本章小结
电流采样是FOC控制环的地基。双电阻方案稳定可靠,采样时序与PWM对齐是核心。GD32的ADC支持外部触发,用TIMER0的TRGO信号就能实现同步采样。配置时注意ADC时钟频率、采样时间、触发源选择这三个关键点。