A4988驱动步进电机
在我电动车跷跷板的程序中有这部分代码,我看有不少人在发,也就单独列出来。
我用的是两相四线步进电机,通过对A4988发送脉冲来驱动步进电机。
程序是使用门控模式输出脉冲。门控模式,我也是刚刚接触,理解的比较简单,就是用一个定时器的高低电平来决定另一个定时器是否触发,可以用一个定时器来控制另一个定时器。
/*MOTOR.h*/
#include "sys.h"
#define DIR1 PBout(10)
#define DIR2 PEout(15)
#define MS1 PCout(7)
#define MS2 PCout(8)
#define MS3 PCout(6)
#define MOTOR_MODE_FULL_STEP 0x00 //全速
#define MOTOR_MODE_HALF_STEP 0x04 //二分之一
#define MOTOR_MODE_QUARTER_STEP 0x02 //四分之一
#define MOTOR_MODE_EIGHTH_STEP 0x06 //八分之一
#define MOTOR_MODE_SIXTEENTH_STEP 0x07 //十六分之一
typedef struct
{
char DIRL;
char DIRR;
char MODE;
}MOTOR_InitTypeDef;
void TIM3_PWM(u16 Cycle, u16 Pulse_Num);
void dir_init(void);
void TIM3_init(void);
void MOTOR_MODE(MOTOR_InitTypeDef* MOTOR_InitStruct);
void TIM4_Config(void);
void NVIC_Configa(void);
/*MOTOR.c*/
#include "motor.h"
#include "stm32f10x.h"
#include "inv_mpu.h"
#include "inv_mpu_dmp_motion_driver.h"
/*****ÉèÖÃPWMµÄÊä³ö£¬¾«È·Êä³ö¶àÉÙƵÂʶàÉÙ¸öÊýµÄÂö³å************/
/*****Cycle:ÖÜÆÚ£¬µ¥Î»(us)
******Pulse_Num:Âö³å¸öÊý(×î´ó3200)
****¸Ä±äTIM3µÄ £¨ ÖØ×°ÔØÖµ £© ¸Ä±äÂö³åƵÂÊ£¬¹Ì¶¨Õ¼¿Õ±ÈΪ50%
****¸Ä±äTIM2µÄ £¨ Ô¤·ÖƵÆ÷+ÖØ×°ÔØÖµ £© ¸Ä±äÂö³å¸öÊý */
void TIM3_PWM(u16 Cycle, u16 Pulse_Num)
{
u16 TIM3per = 0;
u32 Time = 0;
Time = Cycle * (Pulse_Num+10);
Time /= 100; //Ô¤·ÖƵΪ7200,100us ¼¼ÊõÒ»´Î
TIM3per = Cycle/10; //Ô¤·ÖƵΪ720 ,10us ¼¼ÊõÒ»´Î
TIM_SetAutoreload(TIM2, Time-1); //ÉèÖÃTIM2µÄÖØ×°ÔØÖµ
TIM_SetAutoreload(TIM3, TIM3per-1); //ÉèÖÃTIM3µÄÖØ×°ÔØÖµ
TIM_SetCompare1(TIM3,TIM3per/2); //ÉèÖÃTIM3Õ¼¿Õ±ÈΪ50%
TIM_SetAutoreload(TIM4, TIM3per-1); //ÉèÖÃTIM3µÄÖØ×°ÔØÖµ
TIM_SetCompare1(TIM4,TIM3per/2); //ÉèÖÃTIM3Õ¼¿Õ±ÈΪ50%
TIM_Cmd(TIM2,ENABLE);
}
void TIM3_init(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
TIM_OCInitTypeDef TIM_OCInitStruct;
GPIO_InitTypeDef GPIO_InitStruct;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2|RCC_APB1Periph_TIM3,ENABLE); // RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_AFIO,ENABLE); // RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP; //TIM2_ch1_ETR£ºA0 £¬ TIM3_ch1 £ºA6
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_1|GPIO_Pin_7|GPIO_Pin_6;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_InitStruct);
/**************TIM2¹¤×÷ÔÚµ¥Âö³åģʽÏÂ********************/
TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInitStruct.TIM_Prescaler = 7199; //Ô¤·ÖÅäÖµ£¬Ã¿100u¼ÆÊýÒ»´Î
TIM_TimeBaseInitStruct.TIM_Period = 400; //ÖØÔØÖµ
TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStruct);
TIM_SelectOnePulseMode(TIM2,TIM_OPMode_Single);//ÉèÖÃTIM2ÔÚµ¥Âö³åģʽÏ £¬ µ¥´Î´¥·¢
TIM_OC2PreloadConfig(TIM2,TIM_OCPreload_Enable);// ʹÄÜTIM2µÄͨµÀ2ԤװÔؼĴæÆ÷
TIM_SelectOutputTrigger(TIM2,TIM_TRGOSource_OC2Ref); //Âö³åÊä³öͨµÀ2
TIM_OCInitStruct.TIM_OCMode = TIM_OCMode_PWM2;//
TIM_OCInitStruct.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStruct.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OCInitStruct.TIM_Pulse = 200;//±È½Ï²¶»ñ1µÄԤװÔØÖµ Õ¼¿Õ±È50%
TIM_OC2Init(TIM2,&TIM_OCInitStruct);
TIM_Cmd(TIM2,DISABLE);//ÏȲ»Ê¹ÄÜTIM2
/****************TIM3ÔÙ´ÓģʽµÄÃÅ¿ØģʽϵÄPWMÊä³öģʽ**************/
TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Down;
TIM_TimeBaseInitStruct.TIM_Prescaler = 719;//Ô¤·ÖƵֵ£¬10us¼¼ÊõÒ»´Î
TIM_TimeBaseInitStruct.TIM_Period = 200;//ÖØÔØÖµ
TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitStruct);
TIM_SelectSlaveMode(TIM3, TIM_SlaveMode_Gated);//TIM3ΪÃÅ¿Øģʽ
TIM_SelectMasterSlaveMode(TIM3,TIM_MasterSlaveMode_Enable);
TIM_SelectInputTrigger(TIM3,TIM_TS_ITR1);//ÄÚ²¿´ÓTIM2´¥·¢
TIM_OCInitStruct.TIM_OCMode = TIM_OCMode_PWM2;
TIM_OCInitStruct.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStruct.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OCInitStruct.TIM_Pulse = 100; //±È½Ï²¶»ñ1µÄԤװÔØÖµ Õ¼¿Õ±È50%
TIM_OC2Init(TIM3,&TIM_OCInitStruct);
TIM_OC1Init(TIM3,&TIM_OCInitStruct);
TIM_Cmd(TIM3,ENABLE);
}
void dir_init(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);//ʹÄÜGPIOBµÄʱÖÓ
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE,ENABLE);//ʹÄÜGPIOEµÄʱÖÓ
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);//ʹÄÜGPIOCµÄʱÖÓ
GPIO_InitStruct.GPIO_Mode=GPIO_Mode_Out_PP; //ÍÆÍìÊä³ö
GPIO_InitStruct.GPIO_Pin=GPIO_Pin_10; //PB10¶Ë¿ÚÅäÖÃ
GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;//ËÙ¶È50MHz
GPIO_Init(GPIOB,&GPIO_InitStruct); //³õʼ»¯GPIOB.10
GPIO_SetBits(GPIOB,GPIO_Pin_10); //ÉèÖÃPB10Êä³ö¸ß
GPIO_InitStruct.GPIO_Mode=GPIO_Mode_Out_PP; //ÍÆÍìÊä³ö
GPIO_InitStruct.GPIO_Pin=GPIO_Pin_15; //PE15¶Ë¿ÚÅäÖÃ
GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;//ËÙ¶È50MHz
GPIO_Init(GPIOE,&GPIO_InitStruct); //³õʼ»¯GPIOE.15
GPIO_SetBits(GPIOE,GPIO_Pin_15); //ÉèÖÃPE15Êä³ö¸ß
GPIO_InitStruct.GPIO_Mode=GPIO_Mode_Out_PP; //ÍÆÍìÊä³ö
GPIO_InitStruct.GPIO_Pin=GPIO_Pin_6|GPIO_Pin_7|GPIO_Pin_8; //PC678¶Ë¿ÚÅäÖÃ
GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;//ËÙ¶È50MHz
GPIO_Init(GPIOC,&GPIO_InitStruct); //³õʼ»¯GPIOC.678
GPIO_SetBits(GPIOB,GPIO_Pin_6|GPIO_Pin_7|GPIO_Pin_8); //ÉèÖÃPC678Êä³ö¸ß
}
void MOTOR_MODE(MOTOR_InitTypeDef* MOTOR_InitStruct)
{
DIR1 =MOTOR_InitStruct ->DIRL ;
DIR2 =MOTOR_InitStruct ->DIRR ;
MS1 =MOTOR_InitStruct ->MODE >> 2;
MS2 =MOTOR_InitStruct ->MODE >> 1 & 0x01;
MS3 =MOTOR_InitStruct ->MODE & 0x01;
}
/*Ò»Ã붨ʱ*/
void TIM4_Config(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4,ENABLE);
TIM_ClearITPendingBit(TIM4,TIM_IT_Update);
TIM_TimeBaseStructure.TIM_Period = 1999;
TIM_TimeBaseStructure.TIM_Prescaler = 35999;
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM4,&TIM_TimeBaseStructure);
TIM_ITConfig(TIM4,TIM_IT_Update,ENABLE);
TIM_Cmd(TIM4,ENABLE);
}
void NVIC_Configa(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
NVIC_InitStructure.NVIC_IRQChannel = TIM4_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
/*main.c*/
MOTOR_InitTypeDef MOTOR_InitStruct;
dir_init();
delay_init();
TIM3_init();
void main()
{
MOTOR_InitStruct.DIRL =0;
MOTOR_InitStruct.DIRR =1;
MOTOR_InitStruct.MODE = MOTOR_MODE_EIGHTH_STEP ;
MOTOR_MODE(&MOTOR_InitStruct);
TIM3_PWM(2000, 120);
delay_ms(100);
}
注释懒得改了,复制到KEIL5里面就正常了。
输出脉冲可以稳定的确定周期与数量(逻辑分析仪实测),TIM3_PWM(2000, 120);第一个参数为周期,第二个参数为脉冲数量。