STM32驱动步进电机

最新更新时间:2019-03-18来源: eefocus关键字:STM32  驱动步进电机 手机看文章 扫描二维码
随时随地手机看文章

步进电机是将电脉冲信号转变为角位移或线位移,可以通过控制脉冲来控制,因此比一般的电机更精准。这篇文章将会讲述我对四线两项步进电机的调试经验。


1.步进电机以及THB7128的接线

THB7128步进电机驱动有两个接线口,J4口与stm32的IO口相接,J2口与步进电机和电源相接。


J2口有6个端子,从两个端口旁的接口定义可以看出,接口分别为B-,B+,A-,A+,V-,V+。其中V+与9~32V的电源相接,V-接电源地,其余的接口B+,B-一组,A+,A-一组与步进电机的两组同相线相接(注:想要判断步进电机哪两根线同相,只需用万用表测量,短接的即为同相)。


J4口同样可以从端口定义看出,分别有CP+,CP-,DIR+,DIR-,EN+,EN-6个端子。CP为脉冲信号输入端,DIR为电机正反转控制端,EN为电机脱机控制端。在J4端口有共阳极和共阴极两种接线方法。 


共阳极接法:分别将CP+,DIR+,EN+连接到STM32板子的输出电压上,脉冲输入信号通过CP-接入;此时,DIR,EN-在低电平有效。 


共阴极接法:分别将CP-,DIR-,EN-连接到控制系统的地端(与电源地隔离);此时脉冲输入信号通过CP+加入,U/D+,EN+在高电平有效。 


(注:我采用的是共阴极接法,所以之后只介绍共阴极的程序) 


J4端口共阴极接线


2. THB7128设置

TBH7128有6个拨盘开关(S1~S6),前3个开关控制细分设置,即控制电机每一步转动多少度,步距角=电机固有步距角/细分数。后三个S3~S6设置电流大小,设置的电流不要超过电机的额定电流。具体如何设置根据自己实际情况参考驱动芯片背后的说明表进行调节。说明表所示: 


Microstep-Set 
Current-Set


3.程序设计

(1)使步进电机稳定转动 

驱动接收到一个脉冲步进电机就动一步,所以我们可以用定时器中断将脉冲按一定的频率从STM32的IO口输入到驱动中,这样就可以使步进电机稳定转动起来 

(2)步进电机的开启、截止以及变向 

当THB7128使能端EN+接收到高电平时步进电机停止运转,接收到低电平时正常运转。因此改变与EN+相接的IO口的电平高低就可以控制电机的开启与截止。 

当正反控制端DIR+接收到高电平时步进电机改变转动方向,改变相应的IO口电平即可让步进电机变向。 

(3)步进电机变速 

我用的定时器中断来驱动电机转动,所以只要想办法改变定时器中断的参数就可以让电机改变速度


具体程序如下:


①定时器设置及IO口初始化


#include "dianji.h"

#include "led.h"


void TIM3_Int_Init(u16 arr,u16 psc)

{

  TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;

    NVIC_InitTypeDef NVIC_InitStructure;


    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //时钟使能


    //定时器TIM3初始化

    TIM_TimeBaseStructure.TIM_Period = arr;//自动重装载寄存器周期的值

    TIM_TimeBaseStructure.TIM_Prescaler = psc;//预分频值

    TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;//设置时钟分割

    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;//向上计数模式

    TIM_TimeBaseInit(TIM3,&TIM_TimeBaseStructure);


    TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE); //使能指定的TIM3中断,允许更新中断


    //中断优先级NVIC设置

    NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;//TIM3中断

    NVIC_InitStructure.NVIC_IRQChannelCmd =ENABLE; 

    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //抢占优先级

    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;//响应优先级

    NVIC_Init(&NVIC_InitStructure);


    TIM_Cmd(TIM3,ENABLE);//使能TIMx

}


void TIM3_IRQHandler(void)//TIM3中断函数

{

    if(TIM_GetITStatus(TIM3,TIM_IT_Update) != RESET)//检查TIM3更新中断发生与否

    {

        TIM_ClearITPendingBit(TIM3,TIM_IT_Update);//清除TIMx更新中断标志

        LED0=!LED0;

    }

}



void DJ_Init(void)

{

    GPIO_InitTypeDef GPIO_InitStruct;


    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);//使能GPIOB

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOG,ENABLE);//使能GPIOG


    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;//推挽输出 

    GPIO_InitStruct.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_4;

    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;

    GPIO_Init(GPIOB,&GPIO_InitStruct);

    GPIO_SetBits(GPIOB,GPIO_Pin_6);


    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;//推挽输出 

    GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9;

    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;

    GPIO_Init(GPIOG,&GPIO_InitStruct);

    GPIO_SetBits(GPIOG,GPIO_Pin_9); 

}


②主函数(具体操作控制)


#include "stm32f10x.h"

#include "usart.h"

#include "led.h"

#include "delay.h"

#include "sys.h"

#include "timer.h"

#include "key.h"

#include "dianji.h"


#define up 1 

#define down 0



int main(void)

{

    vu8 key = 0;

    vu8 key1 = 0;

    vu8 num0 = 0;

    vu8 num1 = 0;

    vu8 num2 = 0;

    vu8 speed = 1;

    vu16 arrLowest = 189;

    vu16  arrMax= 409;

    vu16 arr =299;

    vu16 psc = 359;

    LED_Init();

    delay_init();

    KEY_Init();

    DJ_Init();

    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);

    uart_init(115200);   //串口初始化为115200


    TIM3_Int_Init(arr,psc);//10Khz的计数频率,计数到100为10ms (arr+1)*(psc+1)/72  

    while(1)

    {   

        key = KEY_Scan(0);

        if(key == KEY0_PRES)

        {

            if(num0 == 0)

            {

                num0 = 1;

                LED1=0;

                GPIO_ResetBits(GPIOB,GPIO_Pin_6);

            }

            else

            {

                num0 = 0;

                LED1=1;

                GPIO_SetBits(GPIOB,GPIO_Pin_6);

            }

        }           

        if(key == KEY1_PRES)

        {

            if(num2 == 0)

            {

                GPIO_SetBits(GPIOG,GPIO_Pin_9);

                num2 = 1;

            }

            else

            {

                GPIO_ResetBits(GPIOG,GPIO_Pin_9);

                num2 = 0;

            }

        }

        while(key == WKUP_PRES)

        {                       

            if(speed == down)

            {               

                arr+=2;

                TIM3_Int_Init(arr,psc);                 

                delay_ms(50);

                key1 = KEY_Scan(0);

                if(arr > arrMax)

                {

                    speed = up;

                }

                if(key1 == WKUP_PRES)//关闭变速

                {

                    LED1 = 0;

                    key = 0;

                }

            }

            if(speed == up)

            {                   

                arr-=2;             

                TIM3_Int_Init(arr,psc);                 

                delay_ms(50);

                if(arr < arrLowest)

                {   

                    speed = down;

                }

                key1 = KEY_Scan(0);

                if(key1 == WKUP_PRES)

                {

                    LED1 = 0;

                    key = 0;

                }   

            }

        }       

    }

}


4.总结

通过以上过程的调试,我实现了用按键控制步进电机的启动、截止、变向以及加减速这些功能。 

可能我的电机驱动和大家的不一样, 希望能让读者起到参考作用。

关键字:STM32  驱动步进电机 编辑:什么鱼 引用地址:http://news.eeworld.com.cn/mcu/2019/ic-news031843529.html

上一篇:STM32之SystemInit()函数的探讨
下一篇:CanFestival移植到STM32F103

推荐阅读

STM32 SPI硬件模式
反复试验,发现SPI_NSS引脚的自动硬件控制与想象的不同,无论是否外加上拉,只要一使能SPI,SPI_Cmd(SPI1, ENABLE); SPI_NSS引脚就一直处于低电平,直到SPI_Cmd(SPI1, DISABLE);这个需要用程序来控制。  而用过其他芯片则是发送完成自动会拉高,这点是要注意的我说的就是做主机的时候SPI_SSOutputCmd(SPIx,ENABLE) 在soft模式时这句话有必要吗?我的理解是当hard模式,需要multimaster的时候,才应该要开启这个output功能,这点从我的截图上可以看出。我觉得,这里只要把SPI_InitStructure
发表于 2022-02-21
<font color='red'>STM32</font> SPI硬件模式
STM32 timer input filter
STM32的定时器输入通道都有一个滤波单元,分别位于每个输入通路上(下图中的黄色框)和外部触发输入通路上(下图中的兰色框),它们的作用是滤除输入信号上的高频干扰。具体操作原理如下:在TIMx_CR1中的CKD[1:0]可以由用户设置对输入信号的采样频率基准,有三种选择:1)采样频率基准fDTS=定时器输入频率fCK_INT2)采样频率基准fDTS=定时器输入频率fCK_INT/23)采样频率基准fDTS=定时器输入频率fCK_INT/4然后使用上述频率作为基准对输入信号进行采样,当连续采样到N次个有效电平时,认为一次有效的输入电平。实际的采样频率和采样次数可以由用户程序根据需要选择;外部触发输入通道的滤波参数在从模式控制寄存器(TI
发表于 2022-02-21
<font color='red'>STM32</font> timer input filter
关于STM32影子寄存器和预装载寄存器和TIM_ARRPreloadConfig
本文的说明依据STM32参考手册(RM0008)第10版:英文:http://www.st.com/stonline/products/literature/rm/13902.pdf中译文:http://www.stmicroelectronics.com.cn/stonline/mcu/images/STM32_RM_CH_V10_1.pdf在STM32参考手册的第13、14章中,都有一张定时器的框图,下面是第14章中定时器框图的局部,图中黄色框所示的是auto-reload register,在下面的第14.3.2节"Counter Modes"就解释了auto-reload register的用法。在图中可
发表于 2022-02-21
关于<font color='red'>STM32</font>影子寄存器和预装载寄存器和TIM_ARRPreloadConfig
stm32 Fdts
发表于 2022-02-21
<font color='red'>stm32</font> Fdts
STM32定时器输出比较模式
OCx与OCxREF和CCxP之间的关系初学STM32,我这个地方卡了很久,现在终于有些明白了,现在把我的理解写下与大家共享,如果有不对的地方,还请指出。-----------------------------------------------------------------------------------------------------------------------TIM_OCMode选择定时器模式。该参数取值见下表:TIM_OCInitStructure.TIM_Pulse = CCR1_Val; //设置跳变值,当计数器计数到这个值时,电平发生跳变TIM_OC2PreloadConfig(TIM3, TI
发表于 2022-02-18
<font color='red'>STM32</font>定时器输出比较模式
stm32库函数学习篇
两天学习了一下stm32通用定时器的输入捕获功能。在网上看到很多网友说触发中断程序进不了,于是自己也测试了个小程序,还好能够进入中断。呵呵~ 实现功能:PA8随意延时驱动led灯闪烁,并且将PA8用杜邦线连接到PA7口,PA7是通用定时器TIM3的2通道,在TIM3_CH2触发中断程序中取反连接到PD2口的led灯,指示中断程序运行,并且每次进入中断后改变触发捕获的极性。实现两个led灯会交替闪烁。 先有必要了解stm32定时器的输入触发模块,如下图:需要注意的是,一眼望去一个定时器似乎有8个通道,左边四个,右边四个,但其实左边和右边是共用相同的IO引脚,所以名称标注是一模一样。也就是说,每个通用定时器都只有四个
发表于 2022-02-18
<font color='red'>stm32</font>库函数学习篇
小广播
实战 培训 开发板 精华推荐

何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2022 EEWORLD.com.cn, Inc. All rights reserved