ADC 与电流采样:多通道同步采样技术
系列:电机控制系列 - 第 7 篇 目标平台:STM32F407ZGT6 阅读时间:30 分钟
前言
电流采样是 FOC 的眼睛:
- ❌ 采样不准 → FOC 失效
- ❌ 采样太慢 → 带宽受限
- ❌ 采样不同步 → 误差放大
本篇目标:
- ✅ 掌握 ADC 多通道同步采样
- ✅ 理解采样时刻选择
- ✅ 实现电流校准
一、电流采样方式
1.1 采样电阻法
低侧采样(常用):
U_dc
│
┌─┴─┐
│ Q1│ 上桥臂
└─┬─┘
├──── A 相
┌─┴─┐
│ Q4│ 下桥臂
└─┬─┘
│
┌─┴─┐
│Rs │ 采样电阻
└─┬─┘
│
GND
I_a = V_Rs / Rs优点:
- ✅ 成本低
- ✅ 简单可靠
- ❌ 只能采样导通时刻
高侧采样:
U_dc
│
┌─┴─┐
│Rs │ 采样电阻
└─┬─┘
┌─┴─┐
│ Q1│
└─┬─┘
└──── A 相优点:
- ✅ 可连续采样
- ❌ 共模电压高(需要隔离运放)
- ❌ 成本高
1.2 霍尔传感器
闭环霍尔(高精度):
┌─────┐
────┤ 霍尔 ├──── I_in
│传感器│
└──┬──┘
│
输出电压 ∝ 电流优点:
- ✅ 隔离、安全
- ✅ 精度高(0.1%)
- ❌ 成本高(¥50-200)
二、ADC 配置
2.1 三重 ADC 同步模式
STM32F407 ADC 特性:
- 3 个 ADC(ADC1, ADC2, ADC3)
- 最高 2.4 MSPS
- 12-bit 分辨率
三重同步模式:
触发信号 ────┬─── ADC1 → CH1 (电流 A)
├─── ADC2 → CH2 (电流 B)
└─── ADC3 → CH3 (电流 C)
同时采样,同时转换2.2 寄存器配置
/**
* @brief ADC 三重模式初始化
*/
void ADC_Triple_Init(void) {
// 1. 使能时钟
RCC->APB2ENR |= RCC_APB2ENR_ADC1EN | RCC_APB2ENR_ADC2EN | RCC_APB2ENR_ADC3EN;
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN | RCC_AHB1ENR_GPIOBEN;
// 2. GPIO 配置(PA1, PA2, PA3)
GPIOA->MODER |= (3 << GPIO_MODER_MODE1_Pos) | // 模拟模式
(3 << GPIO_MODER_MODE2_Pos) |
(3 << GPIO_MODER_MODE3_Pos);
// 3. ADC 通用配置
ADC->CCR |= (0 << ADC_CCR_ADCPRE_Pos) | // PCLK2 / 2 = 42 MHz
(3 << ADC_CCR_MULTI_Pos) | // 三重模式
ADC_CCR_DDS; // DMA 使能
// 4. ADC1 配置(主 ADC)
ADC1->CR1 |= ADC_CR1_SCAN; // 扫描模式
ADC1->SQR3 = 1; // 通道 1
ADC1->CR2 |= ADC_CR2_DMA | ADC_CR2_ADON;
// 5. ADC2 配置(从 ADC)
ADC2->CR1 |= ADC_CR1_SCAN;
ADC2->SQR3 = 2; // 通道 2
ADC2->CR2 |= ADC_CR2_DMA | ADC_CR2_ADON;
// 6. ADC3 配置(从 ADC)
ADC3->CR1 |= ADC_CR1_SCAN;
ADC3->SQR3 = 3; // 通道 3
ADC3->CR2 |= ADC_CR2_DMA | ADC_CR2_ADON;
// 7. DMA 配置
RCC->AHB1ENR |= RCC_AHB1ENR_DMA2EN;
DMA2_Stream0->PAR = (uint32_t)&(ADC->CDR); // 公共数据寄存器
DMA2_Stream0->M0AR = (uint32_t)adc_buffer; // 缓冲区
DMA2_Stream0->NDTR = 3; // 3 个数据
DMA2_Stream0->CR |= DMA_SxCR_CIRC | // 循环模式
DMA_SxCR_MINC | // 内存递增
(1 << DMA_SxCR_MSIZE_Pos) | // 16-bit
DMA_SxCR_EN;
}2.3 触发方式
定时器触发(推荐):
// TIM1 CC4 事件触发 ADC
TIM1->CCR4 = TIM1->ARR / 2; // PWM 中点触发
TIM1->CR2 |= (1 << TIM_CR2_MMS_Pos); // CC4 为触发输出
ADC1->CR2 |= (2 << ADC_CR2_EXTSEL_Pos) | // TIM1_CC4 触发
ADC_CR2_EXTEN; // 上升沿为什么在中点采样?
- PWM 开关瞬间 → 电流振荡
- 中点采样 → 稳定、准确
三、采样时刻优化
3.1 PWM 同步采样
PWM 波形:
┌───────┐
│ │
─────┘ └─────
└── T ──┘
最佳采样点:
┌───────┐
│ ▲ │ ← 中点采样
─────┘ │ └─────
│
触发 ADC代码实现:
// TIM1 CC4 配置为 PWM 中点触发
void TIM1_Set_ADC_Trigger(void) {
// CC4 比较值 = ARR / 2(PWM 周期中点)
TIM1->CCR4 = TIM1->ARR / 2;
// CC4 输出比较模式
TIM1->CCMR2 |= (1 << TIM_CCMR2_OC4M_Pos); // 匹配时触发
// 使能 CC4
TIM1->CCER |= TIM_CCER_CC4E;
}3.2 死区期间采样
问题:死区期间电流不可测
解决:避开死区
// 计算安全采样窗口
float T_dead = 500e-9f; // 500ns
float T_settle = 200e-9f; // 稳定时间 200ns
// 采样点应在 PWM 中点 ± (T_dead + T_settle)四、电流校准
4.1 零点校准
typedef struct {
float offset[3]; // 零点偏置
float gain[3]; // 增益
} Current_Calib_t;
/**
* @brief 零点校准(电机不通电)
*/
void Current_Calibrate_Zero(Current_Calib_t *calib, uint16_t *adc_raw) {
// 采样 1000 次取平均
int32_t sum[3] = {0};
for (int i = 0; i < 1000; i++) {
ADC_Start();
while (!ADC_Complete());
sum[0] += adc_raw[0];
sum[1] += adc_raw[1];
sum[2] += adc_raw[2];
}
calib->offset[0] = sum[0] / 1000.0f;
calib->offset[1] = sum[1] / 1000.0f;
calib->offset[2] = sum[2] / 1000.0f;
}4.2 增益校准
/**
* @brief 增益校准(施加已知电流)
*/
void Current_Calibrate_Gain(Current_Calib_t *calib, float I_known) {
uint16_t adc_raw[3];
// 施加已知电流 I_known
// ...
// 采样
ADC_Read(adc_raw);
// 计算增益
float adc_delta = adc_raw[0] - calib->offset[0];
calib->gain[0] = I_known / adc_delta;
// 同理计算 B、C 相
}4.3 实际电流计算
void Current_Get_Real(Current_Calib_t *calib, uint16_t *adc_raw,
float *ia, float *ib, float *ic) {
*ia = (adc_raw[0] - calib->offset[0]) * calib->gain[0];
*ib = (adc_raw[1] - calib->offset[1]) * calib->gain[1];
*ic = (adc_raw[2] - calib->offset[2]) * calib->gain[2];
// 基尔霍夫电流定律:ia + ib + ic = 0
// 可用于校验
}五、常见问题
5.1 采样噪声大
解决方法:
- 硬件滤波(RC 低通)
- 软件滤波(移动平均)
- PCB 布局优化
// 移动平均滤波
#define FILTER_SIZE 5
float Current_Filter(float new_val) {
static float buffer[FILTER_SIZE] = {0};
static int index = 0;
buffer[index] = new_val;
index = (index + 1) % FILTER_SIZE;
float sum = 0;
for (int i = 0; i < FILTER_SIZE; i++) {
sum += buffer[i];
}
return sum / FILTER_SIZE;
}5.2 采样不同步
解决方法:
- ✅ 使用三重 ADC 模式
- ✅ 硬件触发
- ❌ 软件触发(不同步)
六、总结
电流采样要点:
- 低侧采样(性价比高)
- 三重 ADC 同步采样
- PWM 中点触发
- 零点 + 增益校准
下一篇:编码器与位置检测