STM32F429:使用HAL库精确控制步进电机脉冲数的PWM中断

这两天在调步进电机,希望是使得步进电机每次都达到期望的高度。在查了一天的资料,发现大部分上传的资料都是使用CubeMX生成的,可复制性很高,但未免有失可读性,故上传我的心得经验。

本来原子哥的例程里有整合度很高的,已经封装好的精确控制步进电机前进距离的函数。无奈例程使用了高级定时器TIM8,TIM8需要复用的引脚会影响到CAN的通讯,无奈自行研究,最终决定通过PWM中断,计数脉冲数,以此实现精确控制步进电机的步距角。

话不多说,先谈谈我遇到的坑吧,我个人算是新手,所以在一开始调步进电机时,连初始化和基本步骤都不是很明白,所以下文会从最基础的地方开始。

第一次我选择了定时器4的通道2作为PWM的输出口,然而很快我就发现了TIM4_ CHANNEL2的对应引脚是PD13,复用了PD13 作为PWM输出口后,步进电机出现了上下乱移,不受程序控制的情况,无奈作罢。

第二次,我选择了定时器4通道1,引脚是PD12。于是进入了正常设置环节,

第一个Driverinit,初始化了PF7,PF9作为编码器的DIR+,和DIR-来控制方向。具体可参见备注。

第二个是定时器中断处理函数,调用的是TIM4的句柄。

第三个是TIM4的PWM波初始化。

其中关于2,3点的理解出了偏差,这是我踩得最大的坑!!!没有之一!!!

首先我要强调的是HAL_TIM_PWM_Start和HAL_TIM_PWM_Start_IT的区别。在我的理解中,使用前者只能成功设置时钟输出PWM波,而不能调用中断。而后者才是时钟中断的开启门户。

由于想要使用PWM中断,又因为对定义的不明确,我认为的是,既然在TIM4的PWMinit中,已经使用了HAL_TIM_PWM_Start_IT(&TIM4_Handler,TIM_CHANNEL_1)这个函数来开启了时钟4和时钟4的pwm通道中断,那么当然不需要再对定时器本身的中断处理函数进行设置。

也就是说,一开始我想当然地忘记了调用TIM4_IRQHandler设置定时器中断。

实际上,PWM中断应该是这样的一个调用过程。

首先进入时钟4的时钟中断,然后通过对各种电平的变化读取,会调用到图中重点标注的

HAL_TIM_PWM_PulseFinishedCallback函数,即我们控制PWM精确脉冲数的核心回调函数。

如上,这也就是必须要调用定时器中断处理函数的原因。


 

其次要强调的是PWM的MSP回调函数设置问题,如下图:

 PWM_MspInit是定时器的底层驱动,值得注意的是,此函数会被HAL_TIM_PWM_Init()函数调用。

如图所示,我们首先定义一个GPIO类型的结构体,然后使能引脚所属的GPIOD时钟。

然后对PD12进行各种初始化设置,最后在HAL_GPIO_Init函数中对引脚初始化。

最后也是很容易踩坑的一点,忘记设置中断优先级,即

HAL_NVIC_SetPriority(TIM4_IRQn,2,2);    //设置中断优先级,抢占优先级1,子优先级2
    HAL_NVIC_EnableIRQ(TIM4_IRQn);          //开启TIM4中断   

这也是值得很多和我一样忽视了初始化重要性的新人朋友值得注意的一点,有中断,就要使能中断,并且设置优先级。

最后是HAL_TIM_PWM_PulseFinishedCallback的,没有什么技术化的细节。定义一个静态变量i,产生一个脉冲就i++一次。达到1000时,使能HAL_TIM_PWM_Stop_IT函数,直接关闭时钟4通道一的PWM输出。

最后的最后,还有一个小问题,这样设置的话,HAL_TIM_PWM_Start_IT在初始化时就被调用了,所以如果你设置正确,一打开板子就会使得步进电机前进。所以我们可以先在TIM4_PWM_INIT中注释掉这个函数,或者在main函数中先调用一次HAL_TIM_PWM_Stop_IT,停止PWM输出。

谢谢各位了,最后还是我的hxd提醒我了我的错误,我才能正常驱使步进电机前进固定距离。有什么问题,也欢迎大家在评论区和我交流。

附上约尔美图一张,希望大家天天开心,每天都有新进步新收获。

 

物联沃分享整理
物联沃-IOTWORD物联网 » STM32F429:使用HAL库精确控制步进电机脉冲数的PWM中断

发表评论