CUBEMX教程—— STM32F407实现多步进电机型加减速全过程

时间:2024-04-10 20:58:18

cubemx配置图

先配置定时器,选择定时器8,内部时钟源,通道1,2,3,4

CUBEMX教程—— STM32F407实现多步进电机型加减速全过程

 时钟配置,查看手册可以知道TIM8连接在APB2,定时器8时钟频率为168M。CUBEMX教程—— STM32F407实现多步进电机型加减速全过程

 定时器8参数配置

CUBEMX教程—— STM32F407实现多步进电机型加减速全过程

定时器8GPIO设置 

CUBEMX教程—— STM32F407实现多步进电机型加减速全过程

定时器8 中断设置(比较中断)

CUBEMX教程—— STM32F407实现多步进电机型加减速全过程 

生成代码

代码修改

1、生成S型加速点比较值及自动重装载值

添加bsp_stepmotor.c文件,主要是计算加速过程中确定加速点的自动重装载值,以及编写比较中断产生后回调函数中每个电机通道的状态机变化。

内容为:

#include "bsp_stepmotor.h"
#include "tim.h"
#include "math.h"

uint16_t step_to_run[4]={6800,6800,6800,6800}; //要匀速运行的步数       总共运行步数 = ACCELERATED_SPEED_LENGTH*2 + step_to_run                   
float fre[ACCELERATED_SPEED_LENGTH]; //数组存储加速过程中每一步的频率 
unsigned short period[ACCELERATED_SPEED_LENGTH]; //数组储存加速过程中每一步定时器的自动装载值     


void CalculateSModelLine(float fre[], unsigned short period[], float len, float fre_max, float fre_min, float flexible)
{
    int i=0;
    float deno ;
    float melo ;
    float delt = fre_max-fre_min;
    for(; i<len; i++)
    {
        melo = flexible* (i-len/2) / (len/2);
        deno = 1.0f / (1 + expf(-melo));  //expf is a library function of exponential(e)?
        fre[i] = delt * deno + fre_min;
        period[i] = (unsigned short)(10000000.0f / fre[i]); // 10000000 is the timer driver frequency
    }
    return ;
}

void HAL_TIM_OC_DelayElapsedCallback(TIM_HandleTypeDef *htim)
{
	static uint32_t count[4]={0,0,0,0};
	static uint32_t num_callback[4]={0,0,0,0};
	static uint8_t status[4]={1,1,1,1};
	if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1)
	{
        
		num_callback[0]++;
		if(num_callback[0]%2==0)
		{
			switch(status[0])
	          {
	              case ACCEL://加速
                        __HAL_TIM_SetAutoreload(&htim8,period[count[0]]);
	                    __HAL_TIM_SET_COMPARE(&htim8,TIM_CHANNEL_1,period[count[0]]/2);
	                    count[0]++;
	                    if(count[0]>=ACCELERATED_SPEED_LENGTH)
	                    {
	                        status[0]=3;
	                    }                        
	                  break;
	              case RUN://匀速
	                     step_to_run[0]--;
	                     if(step_to_run[0]<1)
	                       status[0]=2;     
	                   break;
	              case DECEL://减速
	                     count[0]--;
                        __HAL_TIM_SetAutoreload(&htim8,period[count[0]]);
	                    __HAL_TIM_SET_COMPARE(&htim8,TIM_CHANNEL_1,period[count[0]]/2);
	                    if(count[0]<1)
	                        status[0]=0;
	                   break;
	              case STOP://停止
	                   // 关闭通道
	                  TIM_CCxChannelCmd(TIM8, TIM_CHANNEL_1, TIM_CCx_DISABLE);        
	                  __HAL_TIM_CLEAR_FLAG(&htim8, TIM_FLAG_CC1);
	                   break;
	          
	          }
		}

	}
	else if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_2)
	{
        num_callback[1]++;
		if(num_callback[1]%2==0)
		{
              switch(status[1])
	          {
	              case ACCEL://加速
                        __HAL_TIM_SetAutoreload(&htim8,period[count[1]]);
	                    __HAL_TIM_SET_COMPARE(&htim8,TIM_CHANNEL_2,period[count[1]]/2);
	                    count[1]++;
	                    if(count[1]>=ACCELERATED_SPEED_LENGTH)
	                    {
	                        status[1]=3;
	                    }                        
	                  break;
	              case RUN://匀速
	                     step_to_run[1]--;
	                     if(step_to_run[1]<1)
	                       status[1]=2;     
	                   break;
	              case DECEL://减速
	                     count[1]--;
                        __HAL_TIM_SetAutoreload(&htim8,period[count[1]]);
	                    __HAL_TIM_SET_COMPARE(&htim8,TIM_CHANNEL_2,period[count[1]]/2);
	                    if(count[1]<1)
	                        status[1]=0;
	                   break;
	              case STOP://停止
	                   // 关闭通道
	                  TIM_CCxChannelCmd(TIM8, TIM_CHANNEL_2, TIM_CCx_DISABLE);        
	                  __HAL_TIM_CLEAR_FLAG(&htim8, TIM_FLAG_CC2);
	                   break;
	          
	          }
        }
		

	}
	else if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_3)
	{
		num_callback[2]++;
		if(num_callback[2]%2==0)
		{
               switch(status[2])
	          {
	              case ACCEL://加速
                        __HAL_TIM_SetAutoreload(&htim8,period[count[2]]);
	                    __HAL_TIM_SET_COMPARE(&htim8,TIM_CHANNEL_3,period[count[2]]/2);
	                    count[2]++;
	                    if(count[2]>=ACCELERATED_SPEED_LENGTH)
	                    {
	                        status[2]=3;
	                    }                        
	                  break;
	              case RUN://匀速
	                     step_to_run[2]--;
	                     if(step_to_run[2]<1)
	                       status[2]=2;     
	                   break;
	              case DECEL://减速
	                     count[2]--;
                        __HAL_TIM_SetAutoreload(&htim8,period[count[2]]);
	                    __HAL_TIM_SET_COMPARE(&htim8,TIM_CHANNEL_3,period[count[2]]/2);
	                    if(count[2]<1)
	                        status[2]=0;
	                   break;
	              case STOP://停止
	                   // 关闭通道
	                  TIM_CCxChannelCmd(TIM8, TIM_CHANNEL_3, TIM_CCx_DISABLE);        
	                  __HAL_TIM_CLEAR_FLAG(&htim8, TIM_FLAG_CC3);
	                   break;
	          
	          }
        }
	}
	else if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_4)
	{
		num_callback[3]++;
		if(num_callback[3]%2==0)
		{
              switch(status[3])
	          {
	              case ACCEL://加速
                        __HAL_TIM_SetAutoreload(&htim8,period[count[3]]);
	                    __HAL_TIM_SET_COMPARE(&htim8,TIM_CHANNEL_4,period[count[3]]/2);
	                    count[3]++;
	                    if(count[3]>=ACCELERATED_SPEED_LENGTH)
	                    {
	                        status[3]=3;
	                    }                        
	                  break;
	              case RUN://匀速
	                     step_to_run[3]--;
	                     if(step_to_run[3]<1)
	                       status[3]=2;     
	                   break;
	              case DECEL://减速
	                     count[3]--;
                        __HAL_TIM_SetAutoreload(&htim8,period[count[3]]);
	                    __HAL_TIM_SET_COMPARE(&htim8,TIM_CHANNEL_4,period[count[3]]/2);
	                    if(count[3]<1)
	                        status[1]=0;
	                   break;
	              case STOP://停止
	                   // 关闭通道
	                  TIM_CCxChannelCmd(TIM8, TIM_CHANNEL_4, TIM_CCx_DISABLE);        
	                  __HAL_TIM_CLEAR_FLAG(&htim8, TIM_FLAG_CC4);
	                   break;
	          
	          }
        }
	}
  
}

 

#ifndef __bsp_stepmotor_H
#define __bsp_stepmotor_H
#include "tim.h"
#ifdef __cplusplus
 extern "C" {
#endif
     
#define S_ACCEL 1    
#define T_ACCEL 0
     
/* S型加速参数 */
#define ACCELERATED_SPEED_LENGTH 3000  //定义加速度的点数(其实也是3000个细分步的意思),调这个参数改变加速点
#define FRE_MIN 500  //最低的运行频率,调这个参数调节最低运行速度
#define FRE_MAX 35000 //最高的运行频率,调这个参数调节匀速时的最高速度35000


     
#define STOP                                  0 // 加减速曲线状态:停止
#define ACCEL                                 1 // 加减速曲线状态:加速阶段
#define DECEL                                 2 // 加减速曲线状态:减速阶段
#define RUN                                   3 // 加减速曲线状态:匀速阶段

 

     
void CalculateSModelLine(float fre[], unsigned short period[], float len, float fre_max, float fre_min, float flexible);    

#endif




/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

设置完定时器各通道参数及回调函数后即可在main函数中启动定时器

    ...////省略部分代码
    CalculateSModelLine(fre,period,ACCELERATED_SPEED_LENGTH,FRE_MAX,FRE_MIN,4);
    HAL_TIM_Base_Start(&htim8);//启动定时器
	HAL_TIM_OC_Start_IT(&htim8, TIM_CHANNEL_1);//启动定时器8通道1比较输出中断
	HAL_TIM_OC_Start_IT(&htim8, TIM_CHANNEL_2);//启动定时器8通道2比较输出中断
	HAL_TIM_OC_Start_IT(&htim8, TIM_CHANNEL_3);//启动定时器8通道3比较输出中断
	HAL_TIM_OC_Start_IT(&htim8, TIM_CHANNEL_4);//启动定时器8通道4比较输出中断
    while(1)
    ...//省略部分代码

这样代码就完成,烧写进去后每次复位开机可以看到4个电机开始S型加速运行一周,如果需要对电机做不同的加速修改相应的参数即可

单个电机S型加速过程参见上一篇博客

步进电机S型加速