C8T6 A4988步进驱动与42步进电机的2相4线源码详解

  • 项目要求
  • 所需要的元器件
  • A4988步进驱动 与2相4线 42步进电机接线
    1. (第一种方法)不用定时器驱动42步进电机
    2. (第二种方法)用定时器驱动42步进电机
    3. 通过外部中断对电机进行停止
    4. 上位机控制电机开启关闭
    5. 上位机发送命令效果
    6. 示波器波形展示

    项目要求

    本项目通过stm32f1为核心的最小系统板控制42步进电机,可以通过按键的开关对电机进行实时的控制,也可以通过上位机发送的串口命令对电机进行控制,本项目用到了定时器、外部中断、串口收发等。

    所需要的元器件

    1、STM32F103C8T6最小系统核心板

    2、A4988步进驱动

    3、2相4线 42步进电机

    4、2个微动开关(分别负责控制电机开始和停止)


    5、12V的电源

    6、检测电机输出波形的示波器

    A4988步进驱动 与2相4线 42步进电机接线

    A4988步进驱动 2相4线 42步进电机

    A4988步进驱动接线定义:
    A4988
    开发板GND –GND DIR– PB9方向
    开发板3.3V –VDD STEP– PB5脉冲信号
    A –1B SLEEP– VCC3.3V
    C –1A RESET– VCC3.3V
    D –2A MS3– PB12
    B –2B MS2– PB11
    外接电源GND –GND MS1– PB10
    外接电源VCC –VMOT ENABLE– PB13控制抱死

    (第一种方法)不用定时器驱动42步进电机

    下面展示一些 内联代码片

    // A code block
    var foo = 'bar';
    
    // An highlighted block
    //参数
    dir:FALSE正转TRUE反转
    //period 周期
    //step   脉冲
    void Step_Control(u8 dir,u16 period,u32 steps)
    {
    	u32 i;
    	for(i=0; i <= steps;i++)
    	{
    		DIR = dir;
    		STEP = 1;
    		delay_us(1);
    		STEP = 0;
    		delay_us(period);
    	}
    }
    
    

    第一种方法,我们利用for循环发出脉冲信号,通过控制period和steps参数控制,电机运转的时长,这种方式简单,但是会出现问题,就是当我们控制电机运转时,无法通过串口发送”CLOSE“停止命令。因为程序在执行for循环无法打断。

    (第二种方法)用定时器驱动42步进电机

    下面展示一些 内联代码片

    // A code block
    var foo = 'bar';
    
    // An highlighted block
    #include "timer.h"
    #include "usart.h"
    
    //V1.1 20120904
    //1,增加TIM3_PWM_Init函数。
    //2,增加LED0_PWM_VAL宏定义,控制TIM3_CH2脉宽									  
    //  
       	  
    //通用定时器3中断初始化
    //这里时钟选择为APB1的2倍,而APB1为36M
    //arr:自动重装值。
    //psc:时钟预分频数
    //这里使用的是定时器3!
    void TIM3_Int_Init(u16 arr,u16 psc)
    {
      TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
    	NVIC_InitTypeDef NVIC_InitStructure;
    
    	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //时钟使能
    
    	TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值	 计数到5000为500ms
    	TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值  10Khz的计数频率  
    	TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置时钟分割:TDTS = Tck_tim
    	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //TIM向上计数模式
    	TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位
     
    	TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE ); //使能指定的TIM3中断,允许更新中断
    
    	NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;  //TIM3中断
    	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;  //先占优先级0级
    	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;  //从优先级3级
    	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能
    	NVIC_Init(&NVIC_InitStructure);  //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器
    
    	TIM_Cmd(TIM3, ENABLE);  //使能TIMx外设
    							 
    }
    //定时器3中断服务程序
    void TIM3_IRQHandler(void)   //TIM3中断
    {
    	if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET) //检查指定的TIM中断发生与否:TIM 中断源 
    		{
    		TIM_ClearITPendingBit(TIM3, TIM_IT_Update  );  //清除TIMx的中断待处理位:TIM 中断源 
    	
    		}
    }
    
    
    
    
    //TIM3 PWM部分初始化 
    //PWM输出初始化
    //arr:自动重装值
    //psc:时钟预分频数
    void TIM3_PWM_Init(u16 arr,u16 psc)
    {  
    	GPIO_InitTypeDef GPIO_InitStructure;
    	TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
    	TIM_OCInitTypeDef  TIM_OCInitStructure;
    	
    
    	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);	//使能定时器3时钟
     	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB  | RCC_APB2Periph_AFIO, ENABLE);  //使能GPIO外设和AFIO复用功能模块时钟
    	
    	GPIO_PinRemapConfig(GPIO_PartialRemap_TIM3, ENABLE); //Timer3部分重映射  TIM3_CH2->PB8    
     
       //设置该引脚为复用输出功能,输出TIM3 CH2的PWM脉冲波形	GPIOB.8
    	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; //TIM_CH2
    	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  //复用推挽输出
    	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    	GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化GPIO
     
       //初始化TIM3
    	TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值
    	TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值 
    	TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置时钟分割:TDTS = Tck_tim
    	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //TIM向上计数模式
    	TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位
    	
    	//初始化TIM3 Channel2 PWM模式	 
    	TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; //选择定时器模式:TIM脉冲宽度调制模式2
     	TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能
    	TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //输出极性:TIM输出比较极性高
    	TIM_OC2Init(TIM3, &TIM_OCInitStructure);  //根据T指定的参数初始化外设TIM3 OC2
    
    	TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Enable);  //使能TIM3在CCR2上的预装载寄存器
     
    	//TIM_Cmd(TIM3, ENABLE);  //使能TIM3
    	TIM_Cmd(TIM3, DISABLE);  //不使能TIM3
    	
    
    }
    
    

    在这里我们通过定时器3,对PB5输出大小为50Mhz的方波,对steps引脚进行驱动,这种方式的好处就是,即使电机在运转,也可以通过上位机发送命令。

    上位机控制电机开启关闭

    下面展示一些 内联代码片

    // A code block
    var foo = 'bar';
    
    // An highlighted block
    void Send_data_control()
    {
    	
    	if(USART_RX_STA&0x8000)
    	{
    		len=USART_RX_STA&0x3fff;//得到接收到的数据长度
    		printf("\r\n您发送的消息为:\r\n\r\n");
    		for(t=0;t<len;t++)
    		{
    			USART_SendData(USART1,USART_RX_BUF[t]);//向串口1发送数据
    			while(USART_GetFlagStatus(USART1,USART_FLAG_TC)!=SET);
    		}
    		printf("\r\n\r\n");
    		
    		USART_RX_STA=0;
    		
    		if(!(strcmp((char*)USART_RX_BUF,"OPEN")))
    		{
    			
    			TIM_Cmd(TIM3, ENABLE);  //使能TIM3
    		}
    		
    		if(!(strcmp((char*)USART_RX_BUF,"CLOSE")))
    		{
    			
    			NVIC_SystemReset(); // 执行软复位,重新启动处理器
    			
    		}
    
    		
    }
    	
    
    
    }
    
    
    

    直接通过使能定时器3,来开启电机运转

    通过外部中断对电机进行停止

    下面展示一些 内联代码片

    // A code block
    var foo = 'bar';
    
    // An highlighted block
    // 外部中断处理函数
    void EXTI4_IRQHandler(void)
    {
        if (EXTI_GetITStatus(EXTI_Line4) != RESET)
        {
            // 处理外部中断事件
            // ...
    			
    				
            EXTI_ClearITPendingBit(EXTI_Line4);  // 清除中断标志位
    				
    			 NVIC_SystemReset(); // 执行软复位,重新启动处理器
        }
    }
    
    
    

    上位机发送命令效果

    示波器波形展示


    本项目开源,有需要借鉴的可以评论,发链接。

    物联沃分享整理
    物联沃-IOTWORD物联网 » C8T6 A4988步进驱动与42步进电机的2相4线源码详解

    发表评论