Realize the control of motor by analog pulse based on STM32

Features

  1. Realize the control of two motors by analog pulse
  2. Motor can be adjusted to enable, direction and speed

1. Introduction

The idea of ​​the whole design is relatively clever, through a basic timer to achieve not only the control of the two-way motors, but also the acceleration and deceleration control of the stepping motor, the specific implementation process is shown in the code.

Second, the specific code

bsp_motor.h

#ifndef _BSP_MOTOR_H
#define _BSP_MOTOR_H
/*********************************** 引入头文件 start *************************************/
#include "stm32f4xx.h"
/************************************ 引入头文件 end *************************************/

/************************************* 宏定义  start *************************************/
#define PULSE_HIGH 			GPIO_SetBits(GPIOB,GPIO_Pin_13)		//脉冲引脚置低
#define PULSE_LOW 			GPIO_ResetBits(GPIOB,GPIO_Pin_13)	//脉冲引脚置高
#define PULSE_TOGGLE 		PBout(13)									//脉冲引脚反转

#define ENA_HIGH 			GPIO_SetBits(GPIOG,GPIO_Pin_0)		//使能引脚置高 --失能
#define ENA_LOW 			GPIO_ResetBits(GPIOG,GPIO_Pin_0)	//使能引脚置低 --使能

#define DIR_HIGH 			GPIO_SetBits(GPIOF,GPIO_Pin_14)		//方向引脚 --前进
#define DIR_LOW 			GPIO_ResetBits(GPIOF,GPIO_Pin_14)	//方向引脚 --后退
/************************************* 宏定义  end **************************************/

typedef struct
{
    
    
	uint8_t 		channel;	
	
	GPIO_TypeDef* 	PULSE_GPIOx;		//脉冲端口
	uint32_t 		PULSE_GPIO_Pin;   	//脉冲引脚

	GPIO_TypeDef* 	ENA_GPIOx;			//使能端口
	uint32_t 		ENA_GPIO_Pin;   	//使能引脚
	
	GPIO_TypeDef* 	DIR_GPIOx;			//方向端口
	uint32_t 		DIR_GPIO_Pin;   	//方向引脚
	
}Motor_InitTypeDef;
/*********************************** 函数声明  start ************************************/
void Motor_InitTypeDef_Init(Motor_InitTypeDef* motor_InitTypeDef);
void motor_dir(uint8_t dir);
void motor_ena(uint8_t ena);
/************************************ 函数声明  end *************************************/
#endif

bsp_motor.c

#include "bsp_motor.h"

uint8_t motor1_flag = 1;		//脉冲标志位 	1:使能		0:失能
uint8_t motor2_flag = 1;		//脉冲标志位 	1:使能		0:失能


uint8_t channel1 = 0;			//电机1通道使能
uint8_t channel2 = 0;			//电机2通道使能

Motor_InitTypeDef* motor1_InitTypeDef;				//电机1结构体
Motor_InitTypeDef* motor2_InitTypeDef;				//电机结构体

/**************************************************************************************
  * name        : void Motor_GPIO_COnfig(void)
  * Function    : 电机相关引脚的配置
  * Parameters  : void
  * Returns     : NULL
  * Author      : 那些你很冒险的梦
  * Check       :
  * Date        : 2021/3/20
**************************************************************************************/
void Motor_GPIO_Config(Motor_InitTypeDef* motor_InitTypeDef)
{
    
    
	GPIO_InitTypeDef  GPIO_InitStructure;
	//打开时钟
	//RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB|RCC_AHB1Periph_GPIOG|RCC_AHB1Periph_GPIOF, ENABLE);

	if(motor_InitTypeDef->PULSE_GPIOx == GPIOA | motor_InitTypeDef->PULSE_GPIOx == GPIOA | motor_InitTypeDef->DIR_GPIOx == GPIOA)
	{
    
    
		RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
	}
	if(motor_InitTypeDef->PULSE_GPIOx == GPIOB | motor_InitTypeDef->PULSE_GPIOx == GPIOB | motor_InitTypeDef->DIR_GPIOx == GPIOB)
	{
    
    
		RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
	}
	if(motor_InitTypeDef->PULSE_GPIOx == GPIOC | motor_InitTypeDef->PULSE_GPIOx == GPIOC | motor_InitTypeDef->DIR_GPIOx == GPIOC)
	{
    
    
		RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE);
	}
	if(motor_InitTypeDef->PULSE_GPIOx == GPIOD | motor_InitTypeDef->PULSE_GPIOx == GPIOD | motor_InitTypeDef->DIR_GPIOx == GPIOD)
	{
    
    
		RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);
	}
	if(motor_InitTypeDef->PULSE_GPIOx == GPIOE | motor_InitTypeDef->PULSE_GPIOx == GPIOE | motor_InitTypeDef->DIR_GPIOx == GPIOE)
	{
    
    
		RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE, ENABLE);
	}
	if(motor_InitTypeDef->PULSE_GPIOx == GPIOF | motor_InitTypeDef->PULSE_GPIOx == GPIOF | motor_InitTypeDef->DIR_GPIOx == GPIOF)
	{
    
    
		RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF, ENABLE);
	}
	if(motor_InitTypeDef->PULSE_GPIOx == GPIOG | motor_InitTypeDef->PULSE_GPIOx == GPIOG | motor_InitTypeDef->DIR_GPIOx == GPIOG)
	{
    
    
		RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOG, ENABLE);
	}
	
	/*************************************** 脉冲引脚  start **************************************/
	GPIO_InitStructure.GPIO_Pin = motor_InitTypeDef->PULSE_GPIO_Pin;				//引脚
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;									//模式
	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;		
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
	GPIO_Init(motor_InitTypeDef->PULSE_GPIOx, &GPIO_InitStructure);
	PULSE_LOW;
	/*************************************** 脉冲引脚  end **************************************/
	
	/************************************** 使能引脚  start  ************************************/
	GPIO_InitStructure.GPIO_Pin = motor_InitTypeDef->ENA_GPIO_Pin;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
	GPIO_Init(motor_InitTypeDef->PULSE_GPIOx, &GPIO_InitStructure);
	/************************************** 使能引脚 end  *************************************/
	
	/**************************** 方向引脚  START**************************/   
	GPIO_InitStructure.GPIO_Pin = motor_InitTypeDef->DIR_GPIO_Pin;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
	GPIO_Init(motor_InitTypeDef->DIR_GPIOx, &GPIO_InitStructure);
	/************************************** 方向引脚 end  *************************************/
}


/**************************************************************************************
  * name        : void Motor_InitTypeDef_Init(Motor_InitTypeDef* motor_InitTypeDef)
  * Function    : 电机初始化
  * Parameters  : motor_InitTypeDef:电机配置结构体
  * Returns     : NULL
  * Author      : 那些你很冒险的梦
  * Check       :
  * Date        : 2021/3/20
**************************************************************************************/
void Motor_InitTypeDef_Init(Motor_InitTypeDef* motor_InitTypeDef)
{
    
    
	if(motor_InitTypeDef->channel == 1)
	{
    
    
		channel1 = 1;
		motor1_InitTypeDef = motor_InitTypeDef;
	}
	if(motor_InitTypeDef->channel == 2)
	{
    
    
		channel2 = 1;
		motor2_InitTypeDef = motor_InitTypeDef;
	}
	Motor_GPIO_Config(motor_InitTypeDef);
}

/**************************************************************************************
  * name        : void Motor_GPIO_COnfig(void)
  * Function    : 方向控制
  * Parameters  : 1:使能 0:失能
  * Returns     : NULL
  * Author      : 那些你很冒险的梦
  * Check       :
  * Date        : 2021/3/20
**************************************************************************************/
void motor_dir(uint8_t dir)
{
    
    
	if(dir==1)
	{
    
    
		GPIO_ResetBits(GPIOF,GPIO_Pin_14);
	}else{
    
    
		GPIO_SetBits(GPIOF,GPIO_Pin_14);
	}
}

/**************************************************************************************
  * name        : void Motor_GPIO_COnfig(void)
  * Function    : 使能控制
  * Parameters  : start 1:顺时针 0:逆时针
  * Returns     : NULL
  * Author      : 那些你很冒险的梦
  * Check       :
  * Date        : 2021/3/20
**************************************************************************************/
void motor_ena(uint8_t ena)
{
    
    
	if(ena==1)
	{
    
    
		motor1_flag=0;
	}else{
    
    
		motor1_flag=1;
	}
}

timer.c

#include "timer.h"
#include "led.h"
#include "bsp_motor.h"								  



extern uint8_t motor1_flag;		//产生脉冲标志位    1:表示产生脉冲    0表示不产生脉冲
extern uint8_t motor2_flag;		//产生脉冲标志位    1:表示产生脉冲    0表示不产生脉冲

extern uint8_t channel1;
extern uint8_t channel2;

extern Motor_InitTypeDef* motor1_InitTypeDef;		//电机控制结构体1
extern Motor_InitTypeDef* motor2_InitTypeDef;		//电机控制结构体2

int speed1=0;					//速度控制变量1
int speed2=0;					//速度控制变量2
/**************************************************************************************
  * name        : TIM3_Int_Init(u16 arr,u16 psc)
  * Function    : 定时器3配置函数
  * Parameters  : arr:自动重装载值    psc:预分频系数
  * Returns     : NULL
  * Note        :
  * Author      : 那些你很冒险的梦
  * Check       :
**************************************************************************************/

void TIM3_Int_Init(u16 arr,u16 psc)
{
    
    
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
	NVIC_InitTypeDef NVIC_InitStructure;
	/********************************* 定时器配置  start *********************************/
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE); 			//开启定时器3的时钟
	TIM_TimeBaseInitStructure.TIM_Period = arr; 					//重装载寄存器的值
	TIM_TimeBaseInitStructure.TIM_Prescaler=psc;  					//预分频系数
	TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up; 	//设置向上计数
	TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1; 
	TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitStructure);
	TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE); 						//中断使能
	TIM_Cmd(TIM3,ENABLE); 											//定时器使能
	/********************************* 定时器配置  end *********************************/
	
	/*************************** 中断优先级结构体配置  start ***************************/
	NVIC_InitStructure.NVIC_IRQChannel=TIM3_IRQn; 					//配置中断源
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0x01; 		//抢占优先级
	NVIC_InitStructure.NVIC_IRQChannelSubPriority=0x03; 			//子优先级
	NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;					//使能
	NVIC_Init(&NVIC_InitStructure);
	/**************************** 中断优先级结构体配置  end ***************************/
}

/**************************************************************************************
  * name        : TIM3_IRQHandler(void)
  * Function    : 定时器3中断服务函数
  * Parameters  : void
  * Returns     : NULL
  * Note        :
  * Author      :那些你很冒险的梦
  * Check       :
**************************************************************************************/

int temp1=0;
int temp2=0;
void TIM3_IRQHandler(void)
{
    
    
	if(TIM_GetITStatus(TIM3,TIM_IT_Update)==SET) 
	{
    
    
		//判定通道1是否开启
		if(channel1==1)
		{
    
    
			//将脉冲进行反转
			if(motor1_flag==1)
			{
    
    
				
				if(temp1<speed1)
				{
    
    
					temp1++;
				}else if(temp1==speed1 && speed1 != 0)
				{
    
    
					motor1_InitTypeDef->PULSE_GPIOx->ODR ^= motor1_InitTypeDef->PULSE_GPIO_Pin;//脉冲引脚电平反转
					temp1=0;
				
				}else if(temp1>speed1)
				{
    
    
					temp1=0;
				}
				

			}
		}
		
		//判定通道2是否开启
		if(channel2==1)
		{
    
    
			//将脉冲进行反转
			if(motor2_flag==1)
			{
    
    
				
				if(temp2<speed2)
				{
    
    
					temp2++;
				}else if(temp2==speed1 && speed2 != 0)
				{
    
    
					motor2_InitTypeDef->PULSE_GPIOx->ODR ^= motor2_InitTypeDef->PULSE_GPIO_Pin;//脉冲引脚电平反转
					temp2=0;
				}else if(temp2>speed2)
				{
    
    
					temp2=0;
				}
			}
		}
	}
	TIM_ClearITPendingBit(TIM3,TIM_IT_Update); 
}

main.c

#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "led.h"
#include "timer.h"
#include "bsp_motor.h"
#include "bsp_hmi.h"
 
extern uint8_t isFinish;		//1:数据接收完成   0:表示数据接收未完成
extern HMI_Struct hmi_Struct;
extern int speed1;
int main(void)
{
    
     
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);	//中断配置
	delay_init(168); 								//延时配置
	LED_Init();										//LED配置
 	TIM3_Int_Init(10,6400-1);						//打开定时器配置
	uart_init(115200);								//打开串口配置

	//配置电机结构体
	Motor_InitTypeDef motor_InitTypeDef;
	motor_InitTypeDef.channel = 1;					//使能通道
	motor_InitTypeDef.PULSE_GPIOx = GPIOF;
	motor_InitTypeDef.PULSE_GPIO_Pin = GPIO_Pin_3;
	
	motor_InitTypeDef.ENA_GPIOx = GPIOG;
	motor_InitTypeDef.ENA_GPIO_Pin = GPIO_Pin_0; 
	
	motor_InitTypeDef.DIR_GPIOx = GPIOF;
	motor_InitTypeDef.DIR_GPIO_Pin = GPIO_Pin_14;
	
	Motor_InitTypeDef_Init(&motor_InitTypeDef);
	
	hmi_Struct.com = USART1;
	
//	speed1 = 1;
	
//	HMI_WriteBuf(&hmi_Struct,01);
//	HMI_WriteBuf(&hmi_Struct,02);
//	HMI_SendCode(&hmi_Struct);
//	Set_Motor_Speed(16);
//	ENA_LOW;		//使能
//	speed1 = 1;
	while(1)
	{
    
    
		//HMI_Decode(&hmi_Struct,isFinish);
	}
}

Guess you like

Origin blog.csdn.net/qq_37120496/article/details/115175984