概述
功能
- 通过模拟脉冲实现对两路电机的控制
- 可电机进行使能、方向、速度的调节
一、简介
整个设计的思路比较巧妙,通过一个基本定时器实现不仅可以实现对两路电机的进行控制,还能对步进电机实现加减速控制,具体的实现过程见代码。
二、具体的代码
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);
}
}
欢迎一起讨论技术问题,求关注!
最后
以上就是缥缈茉莉为你收集整理的基于STM32实现模拟脉冲对电机的控制的全部内容,希望文章能够帮你解决基于STM32实现模拟脉冲对电机的控制所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复