基于STM32实现模拟脉冲对电机的控制

功能

  1. 通过模拟脉冲实现对两路电机的控制
  2. 可电机进行使能、方向、速度的调节

一、简介

整个设计的思路比较巧妙,通过一个基本定时器实现不仅可以实现对两路电机的进行控制,还能对步进电机实现加减速控制,具体的实现过程见代码。

二、具体的代码

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);
	}
}

猜你喜欢

转载自blog.csdn.net/qq_37120496/article/details/115175984