手写STM32 FOC记录-----pwm触发adc电流采样
PWM的配置详见上一章节。
ADC配置需要使用 PWM 和 ADC 的同步机制,ADC 的采样由 TIM1 的 CCR4在 0 矢量中心附近触发:

首先配置三相电流和母线电压的ADC通道,此处根据硬件平台原理图去配置


然后是ADC基本配置


全部默认即可,说明一下,使用CubeMX配置ADC,使用注入组就用不到规则组。


这里配置比较关键,重点是以下几项,详细说明下:
Number Of Conversions :使用到注入组的通道个数3
External Trigger Source :外部触发源,使用前边说的定时器1的通道四作为触发源。
External Trigger Edge :外部触发极性,选择下降沿
Injected Rank :这个就是注入序列,一旦ADC开始注入转换,就会按照Rank1-2-3-4的顺序依次进行采样,每个rank只能选择一个对应的通道。每个通道对应ADC输入引脚
Sampling Time :采样时间,因为foc电流采样是一个分秒必争的过程,所以采样时间尽可能的要短。
其他配置均默认即可。
最后配置一个测试IO口,每次AD采集就翻转一下IO状态,便于使用示波器测试ADC的采样时间点。CubeMX生成代码。

还是跟上一章节一样,做一个测试文件,将要测试的模块都在测试文件中实现,在主函数中调用需要测试的模块即可。在测试文件中添加test_PWM_ADC_init,主函数调用

void test_PWM_ADC_init(void)
{
HAL_TIM_Base_Start(&htim1);
HAL_TIM_PWM_Start(&htim1,TIM_CHANNEL_1);
HAL_TIM_PWM_Start(&htim1,TIM_CHANNEL_2);
HAL_TIM_PWM_Start(&htim1,TIM_CHANNEL_3);
HAL_TIM_PWM_Start(&htim1,TIM_CHANNEL_4);
HAL_TIMEx_PWMN_Start(&htim1,TIM_CHANNEL_1);
HAL_TIMEx_PWMN_Start(&htim1,TIM_CHANNEL_2);
HAL_TIMEx_PWMN_Start(&htim1,TIM_CHANNEL_3);
__HAL_TIM_SetCompare(&htim1,TIM_CHANNEL_1,0.2*PWM_PERIOD);
__HAL_TIM_SetCompare(&htim1,TIM_CHANNEL_2,0.2*PWM_PERIOD);
__HAL_TIM_SetCompare(&htim1,TIM_CHANNEL_3,0);
HAL_ADCEx_InjectedStart(&hadc1);
HAL_ADCEx_InjectedStart(&hadc2);
__HAL_ADC_ENABLE_IT(&hadc1, ADC_IT_JEOC);
__HAL_ADC_ENABLE_IT(&hadc2, ADC_IT_JEOC);
__HAL_TIM_ENABLE_IT(&htim1, TIM_IT_UPDATE);
__HAL_TIM_SetCompare(&htim1,TIM_CHANNEL_4,PWM_PERIOD-1); //TIM1通道4的PWM配置 关联ADC采样时间 // 在PWM波的正中间采样
}

在中断文件stm32g4xx_it.c中ADC1_2_IRQHandler处添加测试引脚翻转函数,测试ADC的采样时间点

完成以上操作之后,就可以下载到板子中测试了。测试方法是,使用三根示波器表笔,分别接一路PWM,PWMN,TEST_PIN,波形显示如下图:

上图中,黄线是PWM,蓝线为PWMN,紫线为测试引脚波形。可以看出,ADC 中断采样周期和 PWM 周期一致。
最后一步就是测试ADC是否配置成功,看看ADC能否采集到数据。

uint16_t PA1_adc_value,PB11_adc_value,PA0_adc_value,PA7_adc_value;
void test_get_ADC_value(void)
{
PA1_adc_value = HAL_ADCEx_InjectedGetValue(&hadc1,ADC_INJECTED_RANK_1);
PB11_adc_value = HAL_ADCEx_InjectedGetValue(&hadc1,ADC_INJECTED_RANK_2);
PA0_adc_value = HAL_ADCEx_InjectedGetValue(&hadc1,ADC_INJECTED_RANK_3);
PA7_adc_value = HAL_ADCEx_InjectedGetValue(&hadc2,ADC_INJECTED_RANK_1);
}
编写测试接口函数test_get_ADC_value,将其放到中断文件stm32g4xx_it.c中ADC1_2_IRQHandler处调用。

仿真看看读取到的变量结果,如果我们将这个通道连接到VCC,数据会变成0x0FFF左右,接到GND,数据变成0x0000。

以上工程源代码,包括cubemx 生成的ioc文件都可以开源,有需要的小伙伴记得点赞之后私信哟