黄工无刷电机学习
直播中

王鹏

8年用户 1420经验值
私信 关注
[问答]

怎样通过模拟脉冲去实现对两路电机的控制呢

怎样通过模拟脉冲去实现对两路电机的控制呢?具体的实现过程是怎样的?

回帖(2)

王露

2021-10-8 10:08:47
  功能
  通过模拟脉冲实现对两路电机的控制
  可电机进行使能、方向、速度的调节
  一、简介
  整个设计的思路比较巧妙,通过一个基本定时器实现不仅可以实现对两路电机的进行控制,还能对步进电机实现加减速控制,具体的实现过程见代码。
  二、具体的代码
  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);
  }
  }
举报

姬盼希

2021-10-8 10:08:48
1
举报

更多回帖

发帖
×
20
完善资料,
赚取积分