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  驱动步进电机 编辑:什么鱼 引用地址:STM32驱动步进电机

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

推荐阅读最新更新时间:2023-08-08 15:04

玩转STM32(6)初识编译环境
前面已经介绍了怎么样找到项目的工程文件,只要双击那个文件就可以打开整个项目工程,进入代码开发调试环境。在很多年以前,开发软件还是很困难的事情,因为那时候编译环境非常不友好,不是图形界面,而是基于文本的界面,并且还不是集成开发环境,是分离的。当你在编辑器里写了代码之后,然后再保存成文件,然后退出编辑器,再来到命令行的环境下面,输入调用编译器的命令,才可以编译源码。如果编译有问题,要先把出错的行号和列号记住,再进入编辑器进行代码修改,就这样来来回回,反反复复地进行着,可想而之,那时的开发效率是多么的低下,需要人的记性超级好,耐心也要经得起考验,才可以成为开发人员。到今天这个时代,已经大为改观,整个开发环境已经是集成开发环境了,非常便捷
[单片机]
玩转<font color='red'>STM32</font>(6)初识编译环境
STM32串口双缓冲乒乓数据传输方式
对于没玩过DMA 的朋友,这里简单说一下DMA,用自己的语言说吧,那就是,从某个位置 传输数据到某个位置,如果不用DMA,那要CPU参与操作,一个字节一个字节地搬,效率高 点的,就一个字一个字地搬.但当你用了DMA 后,那就是只需要设置:A.从哪里开始搬; B, 搬到哪里去;C以字节方式搬还是半字还是字;D:一共搬多少个.之后,启动DMA.CPU内部 就会开始搬数据了,整个搬数据的过程都不需要指令的参与,唯一要做的,就是检测什么时 候搬完.你可以扫描寄存器,也可以用中断.这里,我使用了中断. 具体设置功能看注释就可以明白了.注意一点就是,有一个设置: DMA_InitStructure.DMA_PeripheralInc = DM
[单片机]
<font color='red'>STM32</font>串口双缓冲乒乓数据传输方式
STM32串口USART
USART作为一种标准接口在应用中十分常见。 1、STM32固件库使用外围设备的主要思路 在STM32中,外围设备的配置思路比较固定。 首先是使能相关的时钟,一方面是设备本身的时钟,如果设备是通过IO口输入输出则还需要使能对应IO口的时钟。 其次是配置对应外设的各项相关参数,如果设备是通过IO口输入输出则还需要配置相关的GPIO。 最后是使能对应外设。 如果相关设备需要使用中断功能,则还需要配置对应外设中断通道的中断优先级,然后使能相应设备的中断,最后还要填写相应的中断服务程 序,在服务程序中进行相应的操作。 2、UART的配置步骤 2.1、打开时钟 由于UART1的TX和RX和AFIO都挂在APB2桥上,因此采用固件库函数R
[单片机]
<font color='red'>STM32</font>串口USART
单片机串口处理获得的经验(stm32
最近搞了一个stm32串口数据帧批处理代码,遇到了很多问题,作为刚工作的我,经验太缺乏,实在是需要总结一番,以避免以后再出现同样的错误。 大致情况罗列如下: 1、串口接收中断处理 在学校的时候根本没有接触过什么循环处理的方法,到现在我也讲不上来这个方法的名字是什么,反正自己会运用了。大致的情况是环形数组处理,代码如下: //====================== 接收数据中断 if( USART_GetITStatus( COM_USARTx, USART_IT_RXNE ) != RESET ) { if( COM_Rx_Sign ==
[单片机]
stm32之滴答定时器(1):滴答定时器在内核的位置
之所以要讲这个滴答定时器,是因为它很特殊,stm32的定时器有内部也有外部的,而滴答定时器是在cortex内核里面的,明白滴答定时器,就可以根据这个思路去对stm32有更深的了解,可以说起到一个举一反三的作用吧。 滴答定时器在stm32手册中可以说是一笔带过,只是讲解了寄存器怎么用,很多童鞋可能对这个滴答定时器还是一头雾水,这第一篇先参考cortex-m3的内核手册讲一下滴答定时器在内核的位置。 在内核文件core_cm3.h(内核文件哦(⊙o⊙))中可以看到systick的地址 #define SysTick_BASE (SCS_BASE + 0x0010) 也就是说SysTick的基址是在SCS的基址
[单片机]
<font color='red'>stm32</font>之滴答定时器(1):滴答定时器在内核的位置
基于STM32的DS1302时钟芯片驱动
/************************************************************************************************************************* * 函数 : DS1302.H * 功能 : DS1302头文件 * 参数 : 无 * 返回 : 无 * 依赖 : 底层读写函数 * 最后修改时间 : * 说明 : DS1302采用GPIO模拟SPI的方式DS1302 LSB格式,上升沿写 下降沿读 BCD码存储 * 参考 : ********************************************************
[单片机]
STM32串口3使用代码
  STM32的串口是相当丰富的,功能也很强劲。最多可提供5路串口(MiniSTM32使用的是STM32F103RBT6,具有3个串口),有分数波特率发生器、支持单线光通信和半双工单线通讯、支持LIN、智能卡协议和IrDASIR ENDEC规范(仅串口3支持)、具有DMA等。   串口最基本的设置,就是波特率的设置。STM32的串口使用起来还是蛮简单的,只要你开启了串口时钟,并设置相应IO口的模式,然后配置一下波特率,数据位长度,奇偶校验位等信息,就可以使用了。   串口能给我们编程调试带来很大帮助,STM32的串口使用起来也很简单,参考官方代码,然后对照STM32手册,就能找到相关寄存器设置,以及设置的先后顺序。   
[单片机]
<font color='red'>STM32</font>串口3使用代码
基于STM32、FreeRTOS 实现硬件看门狗+软件看门狗监测多任务的方法
我们都知道硬件看门狗的目的:是用来监测系统,防止系统死机,并在死机的情况下使系统复位重启。 在RTOS操作系统中,如果任务(线程)较多,出现高优先级任务长时间占用CPU资源,低优先级任务长时间得不到执行这种想象,那么我们的系统就是具有Bug的系统。 如上描述,假如我们的线程没有死机,只是长时间得不到执行。在这种异常情况下,我们又不希望系统复位,只希望执行特定代码,那我们该如何来避免这种问题呢? Ⅰ关于看门狗 硬件看门狗:利用一个定时器计数电路,其定时输出连接到电路的复位端,程序在一定时间范围内对定时“喂狗”。 因此程序正常工作时,定时器总不能溢出,也就不能产生复位信号。如果程序出现故障,不在定时周期内喂狗,就使得看门
[单片机]
基于<font color='red'>STM32</font>、FreeRTOS 实现硬件看门狗+软件看门狗监测多任务的方法
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

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

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