STM32F405 FOC 使用Timer 触发 ADC
- 1. ADC采集模式
- 2. 高级Timer模式
- 3. ADC1 连续采集
- 3.1 DMA软件触发
- 3.2 DMA+TIM触发
- 4. ADC 注入模式采集
- 5. 最终使用方法
1. ADC采集模式
根据STM32F405数据手册,可以看到ADC block diagram,ADC主要有两种触发模式:
- regular conversion mode:常规通道
- injected conversion mode:注入通道
2. 高级Timer模式
这里我们用到的是高级定时器的TRGO功能
3. ADC1 连续采集
连续采集有两种实现方式:
3.1 DMA软件触发
转换完成中断中,再次启动DMA转换
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *hadc)
{
printf("%d \t %d \t %d \t %d \r\n",adc1_value[0], adc1_value[1], adc1_value[2], adc1_value[3]);
HAL_ADC_Start_DMA(&hadc1, (uint32_t *)adc1_value, ADC_CHNNELS);
}
3.2 DMA+TIM触发
DMA+TIM触发,由TIM trigger event触发DMA采集,只需要在main函数中启动一次DMA采集即可
参考 STM32CubeMX | HAL库的ADC多通道数据采集(轮训、DMA、DMA+TIM)、读取内部传感器温度)配置,但是发现只能启动一次DMA,测试发现需要将ADC1的DMA continuous request设置为enable
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_DMA_Init();
MX_USART2_UART_Init();
MX_ADC1_Init();
MX_TIM3_Init();
/* USER CODE BEGIN 2 */
printf("init finished \r\n");
HAL_Delay(100);
HAL_UARTEx_ReceiveToIdle_DMA(&huart2, rcv_buff, sizeof(rcv_buff));
HAL_TIM_Base_Start(&htim3);
HAL_ADC_Start_DMA(&hadc1, (uint32_t *)ADC_Value, ADC_CHNNELS);
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin);
commander_run();
HAL_Delay(500);
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
4. ADC 注入模式采集
-
启动TIM1,默认设置占空比50%
-
启动ADC中断,注入模式
__HAL_ADC_ENABLE_IT(&hadc1, ADC_IT_JEOC);
HAL_ADCEx_InjectedStart(&hadc1);
/*启动TIM1 */
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_TIMEx_PWMN_Start(&htim1, TIM_CHANNEL_1);
HAL_TIMEx_PWMN_Start(&htim1, TIM_CHANNEL_2);
HAL_TIMEx_PWMN_Start(&htim1, TIM_CHANNEL_3);
/*启动ADC1,regular conversion DMA模式*/
HAL_ADC_Start_DMA(&hadc1, (uint32_t *)adc1_value, ADC_CHNNELS);
/*启动ADC1,Enable the ADC end of conversion interrupt.*/
__HAL_ADC_ENABLE_IT(&hadc1, ADC_IT_JEOC);
HAL_ADCEx_InjectedStart(&hadc1);
- 在ADC注入中断回调函数中采集,并通过PC4引脚查看是否有输出
这里设置TIM1的Repetition Counter = 1, 每2次计数周期触发一次Trigger out event。通道2-PWM-CH1(24KHz),通道1-PC4脚(12KHz)。
可以看到PWM-CH1通道周期24KHz,一个计数周期3500,每2个计数周期(7000),触发一次Trigger out event,中断内PC4转换电平。
void HAL_ADCEx_InjectedConvCpltCallback(ADC_HandleTypeDef *hadc)
{
m0_phB = hadc->Instance->JDR1;
m0_phC = hadc->Instance->JDR2;
HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_4);
}
PS:小问题,这里是PWM1通道高电平打开时,触发ADC转换。实际FOC中需要下管为高时采样。需要把PWM CH polarity和PWM CHN polarity设置为low。但是这样设置会导致FOC计算出来的Ta,Tb,Tc参数都需要调整
5. 最终使用方法
采用TIM1的Channel4作为Trigger Event,以此来触发ADC采样。而不用第2节中的Timer update Event。
ADC设置不用改变,仍然使用注入模式,Trigger source 选择Timer1 Trigger out event
参考:
- STM32 定时器触发 ADC 多通道采集,DMA搬运至内存
- STM32CubeMX | HAL库的ADC多通道数据采集(轮训、DMA、DMA+TIM)、读取内部传感器温度
- 野火STM32电机系列(六)Cubemx配置ADC规则和注入通道
- 电机FOC控制(三)STM32 CUBEMX 配置ADC采样
- 电机FOC控制(二)STM32 CUBEMX 配置三相PWM互补输出