stm32利用GPIO延时模拟脉冲控制控制步进电机

本文介绍了如何使用STM32的通用定时器控制步进电机实现正反转和速度调节。通过配置GPIO引脚,设置使能、方向和脉冲信号,结合延迟函数实现方波模拟,从而控制步进电机按指定角度和细分值转动。同时,给出了主函数中根据按键输入调整转动方向和角度的示例代码。
摘要由CSDN通过智能技术生成

主函数

使用STM32的通用定时器定时,控制步进电机正反转和启停。
学习目的:学习步进电机和步进电机驱动器的基本使用方法。

步进电机驱动器:
    ENA+ <---> 3V3
    ENA- <---> PB12
    DIR+ <---> 3V3
    DIR- <---> PB14
    PUL+ <---> 3V3
    PUL- <---> PC6

头文件

#ifndef __BSP_STEP_MOTOR_INIT_H
#define __BSP_STEP_MOTOR_INIT_H

#include "stm32f1xx.h"
#include "stm32f1xx_hal.h"

//引脚定义
/*******************************************************/
//Motor 使能 
#define MOTOR_EN_PIN                    GPIO_PIN_12
#define MOTOR_EN_GPIO_PORT              GPIOB
#define MOTOR_EN_GPIO_CLK_ENABLE()      __HAL_RCC_GPIOB_CLK_ENABLE()

//Motor 方向 
#define MOTOR_DIR_PIN                   GPIO_PIN_14
#define MOTOR_DIR_GPIO_PORT             GPIOB
#define MOTOR_DIR_GPIO_CLK_ENABLE()     __HAL_RCC_GPIOB_CLK_ENABLE()

//Motor 脉冲

#define MOTOR_PUL_PIN                   GPIO_PIN_6
#define MOTOR_PUL_GPIO_PORT             GPIOC
#define MOTOR_PUL_GPIO_CLK_ENABLE()     __HAL_RCC_GPIOC_CLK_ENABLE()

/************************************************************/
#define HIGH GPIO_PIN_SET       //高电平
#define LOW  GPIO_PIN_RESET     //低电平

#define ON  LOW                 //开
#define OFF HIGH                //关

#define CW  HIGH                //顺时针
#define CCW LOW                 //逆时针


//控制使能引脚
/* 带参宏,可以像内联函数一样使用 */
#define MOTOR_EN(x)         HAL_GPIO_WritePin(MOTOR_EN_GPIO_PORT,MOTOR_EN_PIN,x)
#define MOTOR_PLU(x)        HAL_GPIO_WritePin(MOTOR_PUL_GPIO_PORT,MOTOR_PUL_PIN,x)
#define MOTOR_DIR(x)        HAL_GPIO_WritePin(MOTOR_DIR_GPIO_PORT,MOTOR_DIR_PIN,x)

extern void stepper_Init(void);
extern void stepper_turn(int tim,float angle,float subdivide,uint8_t dir);
#endif /* __STEP_MOTOR_INIT_H */

  tim               方波周期 单位MS 周期越短频率越高,转速越快 细分为1时最少10ms

 angle           需要转动的角度值

 dir                选择正反转(取值范围:0,1) 

subdivide     细分值
 

步距角1.8,细分数为1时,电机转一圈需要的脉冲数:n=360/1.8=200脉冲

根据细分数求得步距角被分成多少个方波

n=(int)(angle/(1.8/subdivide));

#include "./stepper/bsp_stepper_init.h"
#include "./led/bsp_led.h"   
#include "./delay/core_delay.h"   
#include "stm32f1xx.h"

/**
  * @brief  步进电机旋转
  * @param  tim         方波周期 单位MS 周期越短频率越高,转速越快 细分为1时最少10ms
  * @param  angle       需要转动的角度值
  * @param  dir       选择正反转(取值范围:0,1) 
  * @param  subdivide   细分值
  * @note   无
  * @retval 无
  */
void stepper_turn(int tim,float angle,float subdivide,uint8_t dir)  
{
  int n,i;
  /*根据细分数求得步距角被分成多少个方波*/
  n=(int)(angle/(1.8/subdivide));
  if(dir==CW) //顺时针
  {
    MOTOR_DIR(CW);
  }
  else if(dir==CCW)//逆时针
  {
    MOTOR_DIR(CCW);
  }
  /*开使能*/
  MOTOR_EN(HIGH);
  /*模拟方波*/
  for(i=0;i<n;i++)
  {   
    MOTOR_PLU(HIGH);
    delay_us(tim/2);
    MOTOR_PLU(LOW);
    delay_us(tim/2);
  }
  /*关使能*/
  MOTOR_EN(LOW);
}


/**
  * @brief  引脚初始化
  * @retval 无
  */
void stepper_Init()
{
  /*定义一个GPIO_InitTypeDef类型的结构体*/
  GPIO_InitTypeDef  GPIO_InitStruct;

  /*开启Motor相关的GPIO外设时钟*/
  MOTOR_DIR_GPIO_CLK_ENABLE();
  MOTOR_PUL_GPIO_CLK_ENABLE();
  MOTOR_EN_GPIO_CLK_ENABLE();

  /*选择要控制的GPIO引脚*/                                 
  GPIO_InitStruct.Pin = MOTOR_DIR_PIN;  

  /*设置引脚的输出类型为推挽输出*/
  GPIO_InitStruct.Mode  = GPIO_MODE_OUTPUT_PP;  

  GPIO_InitStruct.Pull =GPIO_PULLUP;

  /*设置引脚速率为高速 */   
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;

  /*Motor 方向引脚 初始化*/
  HAL_GPIO_Init(MOTOR_DIR_GPIO_PORT, &GPIO_InitStruct); 

  /*Motor 脉冲引脚 初始化*/
  GPIO_InitStruct.Pin = MOTOR_PUL_PIN;  
  HAL_GPIO_Init(MOTOR_PUL_GPIO_PORT, &GPIO_InitStruct); 

  /*Motor 使能引脚 初始化*/
  GPIO_InitStruct.Pin = MOTOR_EN_PIN; 
  HAL_GPIO_Init(MOTOR_EN_GPIO_PORT, &GPIO_InitStruct);  

  /*关掉使能*/
  MOTOR_EN(LOW);

}

主函数 

#include "main.h"
#include <stdlib.h>
#include "./stepper/bsp_stepper_init.h"
#include "./usart/bsp_debug_usart.h"
#include "./led/bsp_led.h"
#include "./key/bsp_key.h" 


/**
  * @brief  主函数
  * @param  无
  * @retval 无
  */
int main(void) 
{
  int key_val=0;
  int i=0;
  int dir_val=0;
  int angle_val=90;
  
  /* 初始化系统时钟为72MHz */
  SystemClock_Config();
  /*初始化USART 配置模式为 115200 8-N-1,中断接收*/
  DEBUG_USART_Config();
  printf("按下按键1可修改旋转方向、按下按键2可修改旋转角度\r\n");
  /*按键初始化*/
  Key_GPIO_Config();
  /*步进电机初始化*/
  stepper_Init();
  /*开启步进电机使能*/
  while(1)
  {     
    if( Key_Scan(KEY1_GPIO_PORT,KEY1_PIN) == KEY_ON  )
    {
      /*改变方向*/
      dir_val=(++i % 2) ? CW : CCW;
      MOTOR_DIR(dir_val);
      key_val = ON;
    }
    if( Key_Scan(KEY2_GPIO_PORT,KEY2_PIN) == KEY_ON  )
    {
      /*改变角度*/
      angle_val=angle_val+90;
      key_val = ON;
    }
    if( key_val == ON  )
    {
      /*打印状态*/
      if(dir_val)
        printf("顺时针旋转 %d 度,",angle_val);
      else
        printf("逆时针旋转 %d 度,",angle_val);
      
      printf("正在运行中......\r\n");
      stepper_turn(100,angle_val,32,dir_val);
      key_val = OFF;
    }
  }
} 

/**
  * @brief  System Clock Configuration
  *         The system Clock is configured as follow : 
  *            System Clock source            = PLL (HSE)
  *            SYSCLK(Hz)                     = 72000000
  *            HCLK(Hz)                       = 72000000
  *            AHB Prescaler                  = 1
  *            APB1 Prescaler                 = 2
  *            APB2 Prescaler                 = 1
  *            HSE Frequency(Hz)              = 8000000
  *            HSE PREDIV1                    = 2
  *            PLLMUL                         = 9
  *            Flash Latency(WS)              = 0
  * @param  None
  * @retval None
  */
void SystemClock_Config(void)
{
  RCC_ClkInitTypeDef clkinitstruct = {0};
  RCC_OscInitTypeDef oscinitstruct = {0};
  
  /* Enable HSE Oscillator and activate PLL with HSE as source */
  oscinitstruct.OscillatorType  = RCC_OSCILLATORTYPE_HSE;
  oscinitstruct.HSEState        = RCC_HSE_ON;
  oscinitstruct.HSEPredivValue  = RCC_HSE_PREDIV_DIV1;
  oscinitstruct.PLL.PLLState    = RCC_PLL_ON;
  oscinitstruct.PLL.PLLSource   = RCC_PLLSOURCE_HSE;
  oscinitstruct.PLL.PLLMUL      = RCC_PLL_MUL9;
  if (HAL_RCC_OscConfig(&oscinitstruct)!= HAL_OK)
  {
    /* Initialization Error */
    while(1); 
  }

  /* Select PLL as system clock source and configure the HCLK, PCLK1 and PCLK2 
     clocks dividers */
  clkinitstruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2);
  clkinitstruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  clkinitstruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  clkinitstruct.APB2CLKDivider = RCC_HCLK_DIV1;
  clkinitstruct.APB1CLKDivider = RCC_HCLK_DIV2;  
  if (HAL_RCC_ClockConfig(&clkinitstruct, FLASH_LATENCY_2)!= HAL_OK)
  {
    /* Initialization Error */
    while(1); 
  }
}

  • 5
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值