【STM32】STM32之DRV8834电机驱动(IO方式)

本篇博文最后修改时间:2017年02月12日,13:32。


一、简介

本文介绍如何使用STM32通过DRV8834控制步进电机,使用IO方式控制转动


二、实验平台

库版本:STM32F10x_StdPeriph_Lib_V3.5.0

编译软件:MDK4.53

硬件平台:STM32开发板(主芯片stm32f103c8t6)

仿真器:JLINK


版权声明

博主:甜甜的大香瓜

声明:喝水不忘挖井人,转载请注明出处。

原文地址:http://blog.csdn.NET/feilusia

联系方式:[email protected]

香瓜BLE之CC2541群:127442605

香瓜BLE之CC2640群:557278427

香瓜BLE之Android群:541462902

香瓜单片机之STM8/STM32群:164311667
甜甜的大香瓜的小店(淘宝店):https://shop217632629.taobao.com/?spm=2013.1.1000126.d21.hd2o8i

四、 实验前提
1、在进行本文步骤前,请先 阅读 以下博文:

2、在进行本文步骤前,请先 实现以下博文:
1)《STM32之系统滴答定时器》:http://blog.csdn.net/feilusia/article/details/52835711

五、基础知识

1、DRV8834是什么?

答:DRV8834是一个电机驱动芯片,它能控制1个步进电机或2个直流电机的方向、步长、停转


六、实验步骤

1、编写并添加DRV8834电机驱动

1)编写驱动DRV8834.c(存放在“……\HARDWARE”)

//******************************************************************************            
//name:             DRV8834.c           
//introduce:        DRV8834驱动    
//author:           甜甜的大香瓜                   
//email:            [email protected]       
//QQ group          香瓜单片机之STM8/STM32(164311667)                    
//changetime:       2016.10.18     
//******************************************************************************   
#include "stm32f10x.h"
#include "DRV8834.h"
#include "GUA_SysTick.h"

/*********************宏定义************************/   
#define DRV8834_STEP_PER_CIRCLE                  (int32)(15331)   //电机转动一圈的步数

#ifndef U8  
typedef unsigned char U8;  
#endif  
  
#ifndef U16  
typedef unsigned short U16;  
#endif  

#ifndef U32  
typedef unsigned long U32;  
#endif  

#ifndef int32  
typedef signed long int32;  
#endif 

//引脚宏定义
#define GUA_DRV8834_SLEEP										GPIOA
#define GUA_DRV8834_SLEEP_PIN								GPIO_Pin_7

#define GUA_DRV8834_M1											GPIOB
#define GUA_DRV8834_M1_PIN									GPIO_Pin_10

#define GUA_DRV8834_M0											GPIOB
#define GUA_DRV8834_M0_PIN									GPIO_Pin_11

#define GUA_DRV8834_DIR											GPIOB
#define GUA_DRV8834_DIR_PIN									GPIO_Pin_1

#define GUA_DRV8834_STEP										GPIOB
#define GUA_DRV8834_STEP_PIN								GPIO_Pin_0

/*********************内部变量************************/  
//MOTOR_CONFIG stMotor_Config = {0x00000000,1500, 0x00, 0x00000000, MOTOR_CONFIG_STATUS_IDLE, 0x00000000}; //初始化电机参数为0步,1500个脉冲每秒的速度,整步,本次电机转动时长,空闲,当前为0位置
MOTOR_CONFIG stMotor_Config = {6000, 500, 0x00, 0x00000000, MOTOR_CONFIG_STATUS_IDLE, 0x00000000}; //初始化电机参数为0步,1500个脉冲每秒的速度,整步,本次电机转动时长,空闲,当前为0位置

/*********************内部函数************************/ 
static void DRV8834_IO_Init(void);
static void DRV8834_Set_Direction(int nDirection);
static void DRV8834_Set_Size(U8 nSize);

//******************************************************************************            
//name:             DRV8834_IO_Init           
//introduce:        电机驱动的IO初始化         
//parameter:        none                 
//return:           none         
//author:           甜甜的大香瓜                 
//email:            [email protected]     
//QQ group          香瓜单片机之STM8/STM32(164311667)                  
//changetime:       2016.10.18                     
//******************************************************************************
static void DRV8834_IO_Init(void)
{	
	//IO结构体
	GPIO_InitTypeDef GPIO_InitStructure;
		
	//时钟使能
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB, ENABLE); 	
	
	//SLEEP配置
	GPIO_InitStructure.GPIO_Pin = GUA_DRV8834_SLEEP_PIN;  		
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GUA_DRV8834_SLEEP, &GPIO_InitStructure);	
	
	//M1配置
	GPIO_InitStructure.GPIO_Pin = GUA_DRV8834_M1_PIN;  		
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GUA_DRV8834_M1, &GPIO_InitStructure);	
	
	//M0配置
	GPIO_InitStructure.GPIO_Pin = GUA_DRV8834_M0_PIN;  		
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GUA_DRV8834_M0, &GPIO_InitStructure);	

	//DIR配置
	GPIO_InitStructure.GPIO_Pin = GUA_DRV8834_DIR_PIN;  		
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GUA_DRV8834_DIR, &GPIO_InitStructure);	
	
	//STEP配置
	GPIO_InitStructure.GPIO_Pin = GUA_DRV8834_STEP_PIN;  		
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GUA_DRV8834_STEP, &GPIO_InitStructure);	
}

//******************************************************************************        
//name:             DRV8834_Control
//introduce:        DRV8834的配置      
//parameter:        nDRV8834_control:需要配置的参数;nDRV8834_control_vaule:配置的数值         
//return:           none      
//author:           甜甜的大香瓜                 
//email:            [email protected]     
//QQ group          香瓜单片机之STM8/STM32(164311667)                  
//changetime:       2016.10.18                     
//******************************************************************************
void DRV8834_Control(U8 nDRV8834_control, U8 nDRV8834_control_vaule)
{
  switch(nDRV8834_control)
  {
    //睡眠模式选择
    case DRV8834_CONTROL_SLEEP: 
    {                  
      //睡眠
      if(nDRV8834_control_vaule == DRV8834_CONTROL_SLEEP_ON)
      {
        GPIO_WriteBit(GUA_DRV8834_SLEEP, GUA_DRV8834_SLEEP_PIN, Bit_RESET);		//SLEEP 0       
      }
      
      //禁止睡眠
      if(nDRV8834_control_vaule == DRV8834_CONTROL_SLEEP_OFF)
      {
        GPIO_WriteBit(GUA_DRV8834_SLEEP, GUA_DRV8834_SLEEP_PIN, Bit_SET);			//SLEEP 1      
      }
      
      break;          
    }

    //步数选择
    case DRV8834_CONTROL_MICROSTEP: 
    {                  
      //满步(M1=0, M0=0)
      if(nDRV8834_control_vaule == DRV8834_CONTROL_MICROSTEP_FULL)
      {
        GPIO_WriteBit(GUA_DRV8834_M1, GUA_DRV8834_M1_PIN, Bit_RESET);					//M1  0        
        GPIO_WriteBit(GUA_DRV8834_M0, GUA_DRV8834_M0_PIN, Bit_RESET);					//M0  0      
      }
      
      //1/2步(M1=0, M0=1)
      if(nDRV8834_control_vaule == DRV8834_CONTROL_MICROSTEP_1_2)
      {
        GPIO_WriteBit(GUA_DRV8834_M1, GUA_DRV8834_M1_PIN, Bit_RESET);					//M1  0        
        GPIO_WriteBit(GUA_DRV8834_M0, GUA_DRV8834_M0_PIN, Bit_SET);						//M0  1      
      }
/*      
      //1/4步(M1=0, M0=Z)
      if(nDRV8834_control_vaule == DRV8834_CONTROL_MICROSTEP_1_4)
      {
        GPIO_WriteBit(GUA_DRV8834_M1, GUA_DRV8834_M1_PIN, Bit_RESET);					//M1  0        
        GPIO_WriteBit(GUA_DRV8834_M0, GUA_DRV8834_M0_PIN, GPIO_MODE_OUT_OD_HIZ_FAST);        // M0  Z       
      }
*/
      //1/8步(M1=1, M0=0)
      if(nDRV8834_control_vaule == DRV8834_CONTROL_MICROSTEP_1_8)
      {
        GPIO_WriteBit(GUA_DRV8834_M1, GUA_DRV8834_M1_PIN, Bit_SET);						//M1  1       
        GPIO_WriteBit(GUA_DRV8834_M0, GUA_DRV8834_M0_PIN, Bit_RESET);					//M0  0       
      }
      
      //1/16步(M1=1, M0=1)
      if(nDRV8834_control_vaule == DRV8834_CONTROL_MICROSTEP_1_16)
      {
        GPIO_WriteBit(GUA_DRV8834_M1, GUA_DRV8834_M1_PIN, Bit_SET);						//M1  1        
        GPIO_WriteBit(GUA_DRV8834_M0, GUA_DRV8834_M0_PIN, Bit_SET);						//M0  1       
      }
/*
      //1/32步(M1=1, M0=Z)
      if(nDRV8834_control_vaule == DRV8834_CONTROL_MICROSTEP_1_32)
      {
        GPIO_WriteBit(GUA_DRV8834_M1, GUA_DRV8834_M1_PIN, Bit_SET);						//M1  1        
        GPIO_WriteBit(GUA_DRV8834_M0, GUA_DRV8834_M0_PIN, GPIO_MODE_OUT_OD_HIZ_FAST);        // M0  Z       
      }  
*/      
      break;          
    }

    //方向选择
    case DRV8834_CONTROL_DIR: 
    {                  
      //正向
      if(nDRV8834_control_vaule == DRV8834_CONTROL_DIR_POSITIVE)
      {
        GPIO_WriteBit(GUA_DRV8834_DIR, GUA_DRV8834_DIR_PIN, Bit_RESET);					//DIR 0                
      }
      
      //反向
      if(nDRV8834_control_vaule == DRV8834_CONTROL_DIR_NEGATIVE)
      {
        GPIO_WriteBit(GUA_DRV8834_DIR, GUA_DRV8834_DIR_PIN, Bit_SET);						//DIR 1    
      }
      
      break;          
    }

    //脉冲脚电平选择
    case DRV8834_CONTROL_STEP: 
    {     
      //初始化时,拉低电平做好准备
      if(nDRV8834_control_vaule == DRV8834_CONTROL_STEP_INIT)
      {
        GPIO_WriteBit(GUA_DRV8834_STEP, GUA_DRV8834_STEP_PIN, Bit_RESET);				//STEP 0                
      }

      //拉低STEP
      if(nDRV8834_control_vaule == DRV8834_CONTROL_STEP_LOW)
      {
        GPIO_WriteBit(GUA_DRV8834_STEP, GUA_DRV8834_STEP_PIN, Bit_RESET);				//STEP 0               
      }

      //拉高STEP
      if(nDRV8834_control_vaule == DRV8834_CONTROL_STEP_HIGH)
      {
        GPIO_WriteBit(GUA_DRV8834_STEP, GUA_DRV8834_STEP_PIN, Bit_SET);					//STEP 1               
      }      
      
      break;          
    }    

    //其他
    default: 
    {
      break;          
    }                     
  }   
}

//******************************************************************************        
//name:             DRV8834_Set_Direction        
//introduce:        DRV8834的电机设置方向    
//parameter:        nDirection:1为正向,0为反向       
//return:           none      
//author:           甜甜的大香瓜                 
//email:            [email protected]     
//QQ group          香瓜单片机之STM8/STM32(164311667)                  
//changetime:       2016.10.18                     
//****************************************************************************** 
static void DRV8834_Set_Direction(int nDirection)
{
  //方向
  switch(nDirection)
  {
    //电机转轴朝上,逆时针,反向
    case MOTOR_CONFIG_DIRECTION_NEGATIVE:
    {
      DRV8834_Control(DRV8834_CONTROL_DIR, DRV8834_CONTROL_DIR_NEGATIVE);        
      break;      
    }  
 
    //电机转轴朝上,顺时针,正向    
    case MOTOR_CONFIG_DIRECTION_POSITIVE:
    {
      DRV8834_Control(DRV8834_CONTROL_DIR, DRV8834_CONTROL_DIR_POSITIVE);        
      break;      
    } 
 
    //其他
    default: 
    {
      break;          
    } 
  }
}

//******************************************************************************        
//name:             DRV8834_Set_Size        
//introduce:        DRV8834的电机设置步长    
//parameter:        nSize:0为整步,1为半步       
//return:           none      
//author:           甜甜的大香瓜                 
//email:            [email protected]     
//QQ group          香瓜单片机之STM8/STM32(164311667)                  
//changetime:       2016.10.18                     
//******************************************************************************
static void DRV8834_Set_Size(U8 nSize)
{
  //步长大小
  switch(nSize)
  {
    //整步
    case MOTOR_CONFIG_SIZE_FULL:
    {
      DRV8834_Control(DRV8834_CONTROL_MICROSTEP, DRV8834_CONTROL_MICROSTEP_FULL);         
      break;      
    } 
  
    //半步
    case MOTOR_CONFIG_SIZE_1_2:
    {
      DRV8834_Control(DRV8834_CONTROL_MICROSTEP, DRV8834_CONTROL_MICROSTEP_1_2);         
      break;      
    } 
    
    //其他
    default: 
    {
      break;          
    } 
  } 
}

//******************************************************************************        
//name:             DRV8834_Step_Move        
//introduce:        DRV8834的电机控制     
//parameter:        pMotor_Config:电机核心参数结构体数据       
//return:           运行时间      
//author:           甜甜的大香瓜                 
//email:            [email protected]     
//QQ group          香瓜单片机之STM8/STM32(164311667)                  
//changetime:       2016.10.18                     
//******************************************************************************
U32 DRV8834_Step_Move(MOTOR_CONFIG *pMotor_Config)
{
  int32 nSteps = pMotor_Config->DirectionSteps;                         //保存步数                                                    
  int32 nDirection = (nSteps >= 0)?1:-1;                                //计算方向
  U8    nSize = pMotor_Config->Size;                                    //保存步长  
  U32   nPulse_duration = (500000L/pMotor_Config->PulsePerSecond);    	//计算延时时间:1000000uS/每秒步数=需要几S,再/2为一个周期均分两段
	
  //唤醒
  DRV8834_Control(DRV8834_CONTROL_SLEEP, DRV8834_CONTROL_SLEEP_OFF); 
  
  //获取步数
  nSteps = nSteps * nDirection;                                         //获取步数
    
  //设置方向
  DRV8834_Set_Direction(nDirection);

  //设置步长
  DRV8834_Set_Size(nSize);

  //清除步数计算值
  pMotor_Config->StepsCount = 0;

  
  //电机转动
  while(nSteps && (pMotor_Config->Status == MOTOR_CONFIG_STATUS_ACTIVE))
  {
    //计算
    nSteps--;                                                           //计算剩余步数
    pMotor_Config->DirectionPosition += nDirection*1;                   //每走1步,计算一次位移
    pMotor_Config->StepsCount++;                                        //计算走过的步数
      
    //STEP低
    DRV8834_Control(DRV8834_CONTROL_STEP, DRV8834_CONTROL_STEP_LOW);
    
    //延时
    GUA_Delay_us(nPulse_duration);
    
    //STEP高
    DRV8834_Control(DRV8834_CONTROL_STEP, DRV8834_CONTROL_STEP_HIGH);
    
    //延时
    GUA_Delay_us(nPulse_duration);
  }
  
  //清除状态
  pMotor_Config->DirectionSteps = 0;
  pMotor_Config->Status = MOTOR_CONFIG_STATUS_IDLE; 
  
  //睡眠
  DRV8834_Control(DRV8834_CONTROL_SLEEP, DRV8834_CONTROL_SLEEP_ON);   

  //计算实际位移
  pMotor_Config->DirectionPosition %= DRV8834_STEP_PER_CIRCLE;                 //每DRV8834_STEP_PER_CIRCLE次为1圈,重新计数  
  
  //换算所用时间为ms为单位,实际走的步数*每步所花的ms数
  return(pMotor_Config->StepsCount*2*nPulse_duration/10);       
}

//******************************************************************************        
//name:             DRV8834_Init        
//introduce:        DRV8834的初始化      
//parameter:        none       
//return:           none      
//author:           甜甜的大香瓜                 
//email:            [email protected]     
//QQ group          香瓜单片机之STM8/STM32(164311667)                  
//changetime:       2016.10.18                     
//******************************************************************************
void DRV8834_Init(void)
{
  //IO初始化
  DRV8834_IO_Init();	
	
  //睡眠
  DRV8834_Control(DRV8834_CONTROL_SLEEP, DRV8834_CONTROL_SLEEP_ON); 

  //nENBL使能
  DRV8834_Control(DRV8834_CONTROL_OUTPUTS, DRV8834_CONTROL_OUTPUTS_ENABLE); 
  
  //STEP低
  DRV8834_Control(DRV8834_CONTROL_STEP, DRV8834_CONTROL_STEP_INIT); 
}

2) 编写驱动头文件 DRV8834.h(存放在“ …… \HARDWARE ”)

//******************************************************************************            
//name:             DRV8834.h           
//introduce:        DRV8834驱动头文件     
//author:           甜甜的大香瓜                   
//email:            [email protected]       
//QQ group          香瓜单片机之STM8/STM32(164311667)                    
//changetime:       2016.10.18     
//******************************************************************************   
#ifndef _DRV8834_H_
#define _DRV8834_H_


/*********************宏定义************************/   
//睡眠模式选择
#define DRV8834_CONTROL_SLEEP                   0
#define DRV8834_CONTROL_SLEEP_ON                0
#define DRV8834_CONTROL_SLEEP_OFF               1


//步数选择
#define DRV8834_CONTROL_MICROSTEP               1
#define DRV8834_CONTROL_MICROSTEP_FULL          0
#define DRV8834_CONTROL_MICROSTEP_1_2           1  
#define DRV8834_CONTROL_MICROSTEP_1_4           2  
#define DRV8834_CONTROL_MICROSTEP_1_8           3  
#define DRV8834_CONTROL_MICROSTEP_1_16          4  
#define DRV8834_CONTROL_MICROSTEP_1_32          5  


//方向选择
#define DRV8834_CONTROL_DIR                     2
#define DRV8834_CONTROL_DIR_POSITIVE            0
#define DRV8834_CONTROL_DIR_NEGATIVE            1


//输出选择
#define DRV8834_CONTROL_OUTPUTS                 3
#define DRV8834_CONTROL_OUTPUTS_ENABLE          0
#define DRV8834_CONTROL_OUTPUTS_DISABLE         1


//脉冲脚电平选择
#define DRV8834_CONTROL_STEP                    4
#define DRV8834_CONTROL_STEP_INIT               0
#define DRV8834_CONTROL_STEP_LOW                1
#define DRV8834_CONTROL_STEP_HIGH               2


//电机参数的宏
#define MOTOR_CONFIG_DIRECTION_NEGATIVE         -1
#define MOTOR_CONFIG_DIRECTION_POSITIVE         1

#define MOTOR_CONFIG_SIZE_FULL                  0
#define MOTOR_CONFIG_SIZE_1_2                   1

#define MOTOR_CONFIG_STATUS_IDLE                0
#define MOTOR_CONFIG_STATUS_ACTIVE              1

/*********************外部变量************************/ 
typedef struct   
{  
  signed long           DirectionSteps;                                           //含方向的步数  
  unsigned short        PulsePerSecond;                                           //每秒给的脉冲数 
  unsigned char         Size;                                                     //步长
  unsigned long         StepsCount;                                               //电机走过的步数  
  unsigned char         Status;                                                   //电机转动状态 
  signed long           DirectionPosition;                                        //含方向的位置
}MOTOR_CONFIG; 

extern MOTOR_CONFIG stMotor_Config;


/*********************函数声明************************/ 
void DRV8834_Control(unsigned char nDRV8834_control, unsigned char nDRV8834_control_vaule);
unsigned long DRV8834_Step_Move(MOTOR_CONFIG *pMotor_Config);
void DRV8834_Init(void);


#endif

3) 工程中添加DRV8834.c

【STM32】STM32之DRV8834电机驱动(IO方式)_第1张图片


4)在MDK设置中添加驱动源文件路径

【STM32】STM32之DRV8834电机驱动(IO方式)_第2张图片


2、在应用层中调用

1)添加头文件(main.c中)

#include "DRV8834.h"

2) 添加驱动初始化代码(main.c的main函数中)

  //DRV8834初始化  
  DRV8834_Init();

3) 添加测试代码(main.c中)

①添加一个电机转一圈的测试代码(main.c中)

//******************************************************************************            
//name:             GUA_Test           
//introduce:        测试代码         
//parameter:        none                 
//return:           none         
//author:           甜甜的大香瓜                 
//email:            [email protected]     
//QQ group          香瓜单片机之STM8/STM32(164311667)                  
//changetime:       2016.10.18                     
//******************************************************************************
#define DRV8834_STEP_PER_CIRCLE                  (int32)(15331)   //电机转动一圈的步数
static void GUA_Test(void)
{   
  while(1)
  {
    //X +360°
    stMotor_Config.DirectionSteps = DRV8834_STEP_PER_CIRCLE;                          //X步数,4字节 
    stMotor_Config.PulsePerSecond = 700;                                              //X速度,2字节 
    stMotor_Config.Size = 0x00;                                                       //X步长,1字节
    stMotor_Config.Status = MOTOR_CONFIG_STATUS_ACTIVE;                               //电机X启动,1字节 
    
    DRV8834_Step_Move(&stMotor_Config); 
	}
}	

由于我使用的电机除了电机自带的减速,还有外壳上的减速,因此一圈为15331步。


添加测试代码的调用(main.c的main函数中)

	//测试代码
	GUA_Test();
测试代码要放在初始化之后。


七、注意事项
暂无。

八、实验结果

仿真并设置断点在测试代码处,可发现电机转动至停止一共约22S,这是因为一圈为15331步,速度设置为700步每秒,计算可得约为21.9S。

因此实验成功。


你可能感兴趣的:(STM32)