嵌入式开发--无刷电机FOC控制--用定时器事件驱动ADC采样

用定时器事件驱动ADC采样

FOC驱动无刷电机,需要在3路下桥导通时采样,即PWM波形的低电平中心点。

常规做法是定时器产生中断,在中断内开启ADC,然后退出中断,再响应ADC中断。一个控制周期需要2次进入中断。

本文的做法是配置好定时器和ADC,响应ADC中断。省掉进中断并开启ADC这个过程。只需要进一次中断。

事件驱动的优点:事件输出,和响应事件,都是硬件连接与驱动的,响应时间短,只需要一个时钟周期就可以开启ADC,不需要进中断,也就不占用MCU资源,高效。

驱动波形

在无刷电机的FOC开发时,需要中心对称的3路同步,或6路同步互补PWM波形来驱动3个半桥控制电机的运行。

3路PWM驱动时,是驱动上桥臂的,下桥臂的波形是由芯片内部的反相器生成的,如图就是上桥臂的驱动波形。

为什么要用中心对称的3路PWM波形?

起点对齐的3路波形的当然也可以使得电机转起来,但是在每个PWM周期起点的那个时刻,3路桥臂需要精确的从同时截止变为同时导通,而MOS管的一致性是达不到要求的,不可能3路同时开启,而是3路先后导通,所以电机的电流可能会有异常的毛刺,使得控制精度下降。

而中心对称的3路PWM波,在每次波形变化时,都只有一路发生跳变,也就不会产生异常的电流毛刺。控制精度更高。

相电流的ADC采样时刻

ADC采集相电流时,采样电阻通常接在下桥臂的。所以需要在下桥臂导通的中心点进行ADC采集相电流,也就是上图低电平的中点,即虚线时刻。

驱动方式比较

可以使用TIM1输出3路或6路PWM,中心对齐模式。

ADC采样时刻,可以用:

1 TIM1的比较中断或更新中断,在中断内启动ADC采样。

2 TIM1的事件输出,由事件驱动ADC进行采样。

方案1需要软件配合,进中断会有延迟。

方案2由芯片内部的硬件驱动,没有延迟,且不会增加MCU的负载,显然更优。

CubeMX配置

引脚配置

MCU选用STM32G431RBT6,定时器1的3个通道PC0,1,2用于3路PWM的输出。

第4个通道用于输出PWM比较的事件,驱动ADC采样,而不需要从引脚输出信号。所以设为No Output。


上图是实际工程使用。在测试中,为了方便观察波形,可以临时将通道4设置为PWM输出,即下图。这样做的结果是,既输出波形,也输出事件。

定时器设置

这部分是设置定时器周期的,主频170M,按图设置即PWM频率25K。向上计数到3400,到设定值后向下计数到0,即为一个定时器周期。

这里是设置输出比较事件,OC4REF,由于这个信号是触发信号,所以它是用翻转表示信号的状态。在一个周期内会输出2次翻转,一次是上升沿,一次下降沿。

在响应这个事件的时候,是可以选择边缘的,即上升沿或下降沿,或上升+下降。

在FOC控制中,ADC需要在下桥臂导通的中心点采样,所以在ADC设置中,根据需要响应其中一个边缘即可,重点:OC4REF

这里是设置通道1,2,3的PWM占空比,其中1700,2100,1900这几个值的改变,就可以改变每个通道的占空比,可以设置为0~3400,对应于0-100的占空比。

这里设置通道4,即比较通道事件的时刻。注意Pulse 3135这个值,在CubeMX生成的初始化代码中,是下面这一行,位于"adc.h"文件中。

c 复制代码
sConfigOC.Pulse = 3135;

调整这个值,就可以改变TIM1_CH4通道的宽度。全面会用到。

ADC设置

这里是ADC的基本设置,基础频率是170M,ADC频率设置为最快,12位分辨率,右对齐。需要采样3路相电流,所以需要选择队列模式依次采样(3路不能同时采样),在队列采样完成后,输出ADC中断。禁止规则模式,使用注入模式,这是由于注入模式的优先级更高,缓存寄存器更多,可以将每一路的数据存放在自己单独的寄存器中。而且注入模式可以打断规则模式,优先采样。所以相电流采样一般用注入模式,母线电压检测,和温度检测一般用规则模式。

我的配置中是将ADC1用注入模式做相电流采样,ADC2用规则模式做母线电压和温度检测。ADC2不是本文讨论重点,略过。

这里是注入模式下的设置,使用3个ADC通道,图中仅展示了1个通道,其他2个通道自行配置即可。

软件编写

软件中主要是使能定时器和ADC,以及中断。

c 复制代码
  //TIM1 6路驱动信号
  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);

	//使能通道4的输出,用于测试,正式项目不用
  HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_4);
  
  //启动ADC的注入中断
  HAL_ADCEx_InjectedStart_IT(&hadc1);

软件使能定时器输出,和ADC注入中断,即可以观察相应的输出波形了。

c 复制代码
void ADC1_2_IRQHandler(void)
{
  /* USER CODE BEGIN ADC1_2_IRQn 0 */
  LED_B(1);
  /* USER CODE END ADC1_2_IRQn 0 */
  HAL_ADC_IRQHandler(&hadc1);
  HAL_ADC_IRQHandler(&hadc2);
  /* USER CODE BEGIN ADC1_2_IRQn 1 */
  LED_B(0);
  /* USER CODE END ADC1_2_IRQn 1 */
}

在ADC的中断内,添加输出电平控制以便观察ADC中断触发的时机,高电平表示ADC转换完成,并进中断的时刻。

波形分析

定时器1通道4的触发输出事件,是下降沿触发,也就是下图中红色箭头时刻点,位于定时器向上计数周期的末期。

ADC采样完成后会触发中断,在下图中是蓝箭头指示的时刻。

红蓝箭头中间的,就是ADC采样转换的时间,可以看到它位于3路PWM低电平的中心点。

最佳状态是:TIM1_CH4的上升沿,与ADC中断的上升沿重合。这样说明ADC采样期间就是TIM1_CH4的低电平期间,也就是3路PWM的低电平中心点,在时序上是非常精确的中心点。

如何用它们重合?

还记得前文提到的这一句吗?就是改变这个值。

c 复制代码
sConfigOC.Pulse = 3135;

在正式应用中,需要保留TIM1_CH4通道,关闭其输出,如下图

相关推荐
一路往蓝-Anbo2 小时前
【第42期】调试进阶(一):IDE中的Register与Memory窗口
c语言·开发语言·ide·stm32·单片机·嵌入式硬件
boneStudent2 小时前
STM32工业HMI控制系统
stm32·单片机·嵌入式硬件
广药门徒3 小时前
嵌入式存储芯片驱动解析:标准化接口与STM32 FMC配置指南
stm32·单片机·嵌入式硬件
清风6666663 小时前
基于单片机的汽车尾气智能检测与发动机异常燃烧报警系统
单片机·嵌入式硬件·毕业设计·课程设计·期末大作业
诺狞猫3 小时前
超声波测距装置课程设计报告
单片机·嵌入式硬件·课程设计
richxu202510013 小时前
嵌入式学习之路->stm32篇-->(8)I2C通讯(上)
stm32·嵌入式硬件·学习
小范馆4 小时前
ESP8266-01S学习笔记
笔记·stm32·学习·esp8266-01s
国科安芯4 小时前
微小卫星红外相机双MCU冗余架构的抗辐照可靠性评估
人工智能·单片机·嵌入式硬件·数码相机·架构·自动化·安全性测试
电子阿板4 小时前
STM32G0B1 NRST复位和其它IO复用了,如何设置成专用复位引脚,
stm32·单片机·嵌入式硬件