栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 系统运维 > 运维 > Linux

SYK-0806-A2S1 工业自动化控制之【08-步进电机启动和停止】

Linux 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

SYK-0806-A2S1 工业自动化控制之【08-步进电机启动和停止】

大家好,我是『芯知识学堂』的SingleYork,前一篇文章给大家介绍了“SYK-0806-A2S1 工业自动化控制之【07-定时器产生特定频率脉冲】”,这一篇中,笔者要给大家介绍如何定时器产生特定频率来控制步进电机。

在工业自动化控制中,相信大家对步进电机并不会陌生,工业上用的步进电机一般还会配一个专门的驱动器,下图中就是其中的一款带驱动器的57型步进电机套件:

那么,我们先来看一下步进电机的控制原理:


根据上图中的步进电机的控制原理我们可以知道,通过控制器产生脉冲信号,再经过步进电机驱动器将脉冲信号转化为步进电机的角位移,便可以让步进电机动起来了!接下来我们看下步进电驱动器的接线方法。步进电机驱动器有三种接线方式,即:共阳极接法、共阴极接法和差分方式接法,分别如下图所示:




步进电机一般有四线、六线和八线三种,三种电机的接线方式如下图所示:

一般买电机的时候,厂家会给出具体的接线图,本例中,笔者就是用的8线步进电机并行高速接法。驱动器采用的是共阳极接法。线路连接好了,接下来我们就要来分析代码部分了。

首先,我们还是来说一下本例要实现的功能,本例中笔者是分两种方式来实现步进电机的启动与停止:

  1. 通过控制定时器0的启动与停止来实现电机0脉冲的输出与关闭

  2. 定时器2一直开启,通过一个变量来控制电机2的脉冲输出与关闭

具体控制逻辑如下:

  • 当X00信号由低电平变成高电平时,电机0启动;
  • 当X01信号由低电平变成高电平时,电机0停止;
  • 当X02信号由低电平变成高电平时,电机2启动;
  • 当X03信号由低电平变成高电平时,电机2停止;

控制逻辑弄清楚了,现在就可以来看代码部分了,首先,还是两个定时器的配置,本例中笔者还是将两个定时器单独来配置:

#include	"bsp_timer.h"


void	Timer0_config(u32 TIM0_Fre)
{
	TIM_InitTypeDef		TIM_InitStructure;						//结构定义
    
	TIM_InitStructure.TIM_Mode      = TIM_16BitAutoReload;	    //指定工作模式,   TIM_16BitAutoReload,TIM_16Bit,TIM_8BitAutoReload,TIM_16BitAutoReloadNoMask
	TIM_InitStructure.TIM_Polity    = PolityLow;			    //指定中断优先级(低到高) Polity_0,Polity_1,Polity_2,Polity_3
	TIM_InitStructure.TIM_Interrupt = ENABLE;					//中断是否允许,   ENABLE或DISABLE
	TIM_InitStructure.TIM_ClkSource = TIM_CLOCK_1T;		        //指定时钟源,     TIM_CLOCK_1T,TIM_CLOCK_12T,TIM_CLOCK_Ext
	TIM_InitStructure.TIM_ClkOut    = DISABLE;				    //是否输出高速脉冲, ENABLE或DISABLE
	TIM_InitStructure.TIM_Value     = 65536UL - (MAIN_Fosc / TIM0_Fre/2);		//初值,
	TIM_InitStructure.TIM_Run       = ENABLE;					//是否初始化后启动定时器, ENABLE或DISABLE
	Timer_Inilize(Timer0,&TIM_InitStructure);					//初始化Timer0	  Timer0,Timer1,Timer2,Timer3,Timer4
}

void	Timer2_config(u32 TIM2_Fre)
{
	TIM_InitTypeDef		TIM_InitStructure;						//结构定义

	TIM_InitStructure.TIM_Mode      = TIM_16BitAutoReload;	    //指定工作模式,   TIM_16BitAutoReload,TIM_16Bit,TIM_8BitAutoReload
	TIM_InitStructure.TIM_Polity    = PolityLow;			    //指定中断优先级, PolityHigh,PolityLow
	TIM_InitStructure.TIM_Interrupt = ENABLE;				    //中断是否允许,   ENABLE或DISABLE
	TIM_InitStructure.TIM_ClkSource = TIM_CLOCK_1T;			    //指定时钟源, TIM_CLOCK_1T,TIM_CLOCK_12T,TIM_CLOCK_Ext
	TIM_InitStructure.TIM_ClkOut    = DISABLE;				    //是否输出高速脉冲, ENABLE或DISABLE
	TIM_InitStructure.TIM_Value     = 65536UL - (MAIN_Fosc / TIM2_Fre/2);		//初值,
	TIM_InitStructure.TIM_Run       = ENABLE;				    //是否初始化后启动定时器, ENABLE或DISABLE
	Timer_Inilize(Timer2,&TIM_InitStructure);				    //初始化Timer1	  Timer0,Timer1,Timer2,Timer3,Timer4
}

然后,在app.c文件中的app_int()函数中调用Timer0_config()、Timer2_config()这两个函数对定时器0和定时器2分别进行初始化,同时因为电机0是直接通过控制定时器0的启动和停止来控制电机启停的,所以这里还需先将定时器0关闭,即“TR0= 0;”:

void app_init(void)
{
	GPIO_Config();      //GPIO配置
    
    Timer0_config(Timer0_Fre);     //定时器0配置
    Timer2_config(Timer2_Fre);     //定时器2配置
    
    TR0= 0;             //定时器0停止运行
    EA = 1;			    //开启总中断
}

这里设定的定时器0和定时器2的输出时钟频率依然为1000Hz:

u32 Timer0_Fre = 1000UL;//timer0频率初值
u32 Timer2_Fre = 1000UL;//timer2频率初值

接下来,我们为了后面程序的可读性更强,笔者这里用了一些宏定义来配置电机0和电机2的对应的控制信号:

#define M0_PUL   Y00    //定义电机0脉冲对应的GPIO
#define M2_PUL   Y01    //定义电机2脉冲对应的GPIO

#define M0_Start X00    //定义电机0启动信号对应的GPIO
#define M0_Stop  X01    //定义电机0停止信号对应的GPIO

#define M2_Start X02    //定义电机2启动信号对应的GPIO
#define M2_Stop  X03    //定义电机2停止信号对应的GPIO

同时,还定义了一个变量用作电机2的脉冲输出使能控制:

bit F_Motor2_EN= 0;     //电机2脉冲输出使能标志位

接下来,就是两个电机的控制逻辑部分了,还是跟之前一样,这部分的代码均放在了app_run()函数中,首先我们先定义4个标志位,用于X00-X03的状态的判断:

    static bit F_M0_Start = 0;
    static bit F_M0_Stop  = 0;

    static bit F_M2_Start = 0;
    static bit F_M2_Stop  = 0;

这里可能大家注意到了,每个变量前面都加了结果static关键字,相信有一定基础的小伙伴们都应该能明白此处加这个关键字的作用,试想一下,如果此处没有static这个关键字的话,那么F_M0_Start 、F_M0_Stop 、F_M2_Start 、F_M2_Stop这四个变量的值是不是在每次进入app_run()这个函数的时候,都会被初始化一遍(即赋值0)?这种情况肯定不是我们本例中想要的,因此,此处加static这个关键字是很有必要的。

废话不多说,附上app.c的完整代码吧,注释也比较全,相信大家一看就能理解了:

#include	"app.h"

#define M0_PUL   Y00    //定义电机0脉冲对应的GPIO
#define M2_PUL   Y01    //定义电机2脉冲对应的GPIO

#define M0_Start X00    //定义电机0启动信号对应的GPIO
#define M0_Stop  X01    //定义电机0停止信号对应的GPIO

#define M2_Start X02    //定义电机2启动信号对应的GPIO
#define M2_Stop  X03    //定义电机2停止信号对应的GPIO

bit F_Motor2_EN= 0;     //电机2脉冲输出使能标志位

u32 Timer0_Fre = 1000UL;//timer0频率初值
u32 Timer2_Fre = 1000UL;//timer2频率初值


void app_init(void)
{
	GPIO_Config();      //GPIO配置
    
    Timer0_config(Timer0_Fre);     //定时器0配置
    Timer2_config(Timer2_Fre);     //定时器2配置
    
    TR0= 0;             //定时器0停止运行
    EA = 1;			    //开启总中断
}


void app_run(void)
{
    static bit F_M0_Start = 0;
    static bit F_M0_Stop  = 0;

    static bit F_M2_Start = 0;
    static bit F_M2_Stop  = 0;
    
    
    
    if(!F_M0_Start)
    {
        if(!M0_Start)          //X00低电平
        {
            delay_ms(10);      //10ms消抖
            if(!M0_Start)
            {
                F_M0_Start = 1;//X00低电平标志置“1”
            }
        }
    }
    else
    {
        if(M0_Start)          //X00高电平
        {
            delay_ms(10);     //10ms消抖
            if(M0_Start)
            {
                F_M0_Start = 0;//X00低电平标志清“0”
                TR0        = 1;//定时器0开始运行
            }
        }
    }
    
    if(!F_M0_Stop)
    {
        if(!M0_Stop)           //X01低电平
        {
            delay_ms(10);      //10ms消抖
            if(!M0_Stop)
            {
                F_M0_Stop  = 1;//X01低电平标志置“1”
            }
        }
    }
    else
    {
        if(M0_Stop)            //X01高电平
        {
            delay_ms(10);      //10ms消抖
            if(M0_Stop)
            {
                F_M0_Stop  = 0;             //X01低电平标志清“0”
                TR0        = 0;             //定时器0停止运行
                M0_PUL     = OutputT_OFF;   //Y00保持高电平
            }
        }
    }
    
    
    
    
    
    if(!F_M2_Start)
    {
        if(!M2_Start)          //X02低电平
        {
            delay_ms(10);      //10ms消抖
            if(!M2_Start)
            {
                F_M2_Start = 1;//X02低电平标志置“1”
            }
        }
    }
    else
    {
        if(M2_Start)           //X02高电平
        {
            delay_ms(10);      //10ms消抖
            if(M2_Start)
            {
                F_M2_Start = 0;//X02低电平标志清“0”
                F_Motor2_EN= 1;//电机2脉冲输出使能
            }
        }
    }
    
    if(!F_M2_Stop)
    {
        if(!M2_Stop)           //X03低电平
        {
            delay_ms(10);      //10ms消抖
            if(!M2_Stop)
            {
                F_M2_Stop  = 1;//X03低电平标志置“1” 
            }
        }
    }
    else
    {
        if(M2_Stop)            //X03高电平
        {
            delay_ms(10);      //10ms消抖
            if(M2_Stop)
            {
                F_M2_Stop  = 0;//X03低电平标志清“0”
                F_Motor2_EN= 0;//电机2脉冲输出失能
            }
        }
    }
}


void timer0_int (void) interrupt TIMER0_VECTOR //频率可变
{
    M0_PUL = !M0_PUL;           //Y00状态翻转
}


void timer2_int (void) interrupt TIMER2_VECTOR //频率可变
{
    if(F_Motor2_EN)             //电机2脉冲输出使能
        M2_PUL = !M2_PUL;       //Y01状态翻转
    else
        M2_PUL = OutputT_OFF;   //Y01保持高电平
}

最后,笔者给大家看一下程序运行的效果吧:

好了,关于使用本节内容笔者就介绍到这里了,有疑问的小伙伴们可以给笔者留言或者直接参与评论,下一节笔者将给大家介绍“如何让步进电机正反转运行”,详见“SYK-0806-A2S1 工业自动化控制之【09-步进电机正反转】”,感谢大家的支持!

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/679920.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号