4. ADC多通道同步采样配置
任务目标
本案例完成三相电流采样所需的ADC多通道同步采样配置。以STM32G4系列(内置3个ADC,支持注入组同步模式)为例,配置ADC1/ADC2/ADC3的注入通道,分别采样U相、V相、W相电流,由定时器触发实现三通道同步转换,转换完成后通过DMA将结果搬运至内存。
硬件连接与前置条件
- 三相电流经采样电阻+运放后,分别接入MCU的PA0(ADC1_IN1)、PA1(ADC2_IN1)、PA2(ADC3_IN1)
- 使用TIM1的TRGO事件作为ADC同步触发源,频率与PWM载波一致(如20kHz)
- 需在CubeMX中完成时钟配置(ADC时钟设为系统时钟的1/4,即42.5MHz@170MHz主频)
关键完整代码
/* main.c 中用户代码区 */
/* 注入通道转换结果存储(3相) */
volatile uint16_t adc_inj_result[3];
/* ADC注入通道配置结构体 */
static void ADC_Injection_Config(void)
{
ADC_InjectionConfTypeDef sConfigInjected = {0};
/* ADC1:注入通道1 = IN1(U相) */
sConfigInjected.InjectedChannel = ADC_CHANNEL_1;
sConfigInjected.InjectedRank = ADC_INJECTED_RANK_1;
sConfigInjected.InjectedNbrOfConversion = 1;
sConfigInjected.InjectedSamplingTime = ADC_SAMPLINGTIME_12CYCLES_5;
sConfigInjected.ExternalTrigInjecConv = ADC_EXTERNAL_TRIGINJECCONV_T1_TRGO;
sConfigInjected.ExternalTrigInjecConvEdge = ADC_EXTERNAL_TRIGINJECCONVEDGE_RISING;
sConfigInjected.AutoInjectedConv = DISABLE;
sConfigInjected.InjectedOffsetNumber = ADC_INJECTED_SOFTWARE_OFFSET_NONE;
sConfigInjected.InjectedOffset = 0;
if (HAL_ADCEx_InjectedConfigChannel(&hadc1, &sConfigInjected) != HAL_OK)
{
Error_Handler();
}
/* ADC2:注入通道1 = IN1(V相) */
sConfigInjected.InjectedChannel = ADC_CHANNEL_1;
if (HAL_ADCEx_InjectedConfigChannel(&hadc2, &sConfigInjected) != HAL_OK)
{
Error_Handler();
}
/* ADC3:注入通道1 = IN1(W相) */
sConfigInjected.InjectedChannel = ADC_CHANNEL_1;
if (HAL_ADCEx_InjectedConfigChannel(&hadc3, &sConfigInjected) != HAL_OK)
{
Error_Handler();
}
}
/* 同步触发启动:使能3个ADC的注入组转换 */
static void ADC_SyncTrigger_Start(void)
{
/* 使能注入转换完成中断(可选,用于调试) */
HAL_ADCEx_InjectedStart_IT(&hadc1);
HAL_ADCEx_InjectedStart_IT(&hadc2);
HAL_ADCEx_InjectedStart_IT(&hadc3);
}
/* 注入转换完成回调:读取3个ADC的注入通道结果 */
void HAL_ADCEx_InjectedConvCpltCallback(ADC_HandleTypeDef *hadc)
{
if (hadc->Instance == ADC1)
{
adc_inj_result[0] = HAL_ADCEx_InjectedGetValue(&hadc1, ADC_INJECTED_RANK_1);
}
else if (hadc->Instance == ADC2)
{
adc_inj_result[1] = HAL_ADCEx_InjectedGetValue(&hadc2, ADC_INJECTED_RANK_1);
}
else if (hadc->Instance == ADC3)
{
adc_inj_result[2] = HAL_ADCEx_InjectedGetValue(&hadc3, ADC_INJECTED_RANK_1);
}
}
/* 主函数中调用(在MX_ADC1_Init等初始化之后) */
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_DMA_Init();
MX_ADC1_Init();
MX_ADC2_Init();
MX_ADC3_Init();
MX_TIM1_Init();
ADC_Injection_Config();
ADC_SyncTrigger_Start();
/* 启动TIM1产生TRGO触发信号 */
HAL_TIM_Base_Start(&htim1);
while (1)
{
/* 主循环:adc_inj_result[0..2] 即为同步采样的三相电流ADC值 */
}
}
关键配置说明
- 同步机制:3个ADC的注入组均配置为TIM1_TRGO上升沿触发,同一时刻启动转换,实现硬件级同步采样
- 采样时刻:TIM1_TRGO由更新事件产生,对应PWM周期起始点,此时三相下桥臂导通,采样电流为真实相电流
- 结果读取:每个ADC仅配置1个注入通道,转换完成后进入回调,分别读取对应ADC的结果寄存器
验证方法
- 编译烧录后,在回调函数中设置断点,观察三个ADC是否在同一个TIM1中断周期内依次进入回调
- 用信号发生器在PA0/PA1/PA2输入1.5V直流偏置+0.5Vpp正弦波,读取adc_inj_result数组,确认三通道波形一致且无相位差
- 预期输出:当输入为1.5V直流时,12位ADC(参考电压3.3V)的转换结果约为
1.5/3.3*4095 ≈ 1861,三个通道读数偏差应在±5 LSB以内
常见问题
- 触发不生效:确认TIM1_TRGO已正确映射(通过TIM1的CR2寄存器设置MMS=更新事件),且ADC外部触发极性配置为上升沿
- 结果始终为0:检查注入通道是否已使能,以及是否调用了
HAL_ADCEx_InjectedStart_IT启动转换 - 三通道不同步:确认3个ADC的触发源均为TIM1_TRGO,且未使用软件触发