大家好,我是『芯知识学堂』的SingleYork,前一篇文章给大家介绍了“SYK-0806-A2S1 工业自动化控制之【07-定时器产生特定频率脉冲】”,
这一篇中,笔者要给大家介绍如何定时器产生特定频率来控制步进电机。
在工业自动化控制中,相信大家对步进电机并不会陌生,工业上用的步进电机一般还会配一个专门的驱动器,
下图中就是其中的一款带驱动器的57型步进电机套件:
那么,我们先来看一下步进电机的控制原理:
根据上图中的步进电机的控制原理我们可以知道,通过控制器产生脉冲信号,
再经过步进电机驱动器将脉冲信号转化为步进电机的角位移,便可以让步进电机动起来了!
接下来我们看下步进电驱动器的接线方法。步进电机驱动器有三种接线方式,
即:共阳极接法、共阴极接法和差分方式接法,分别如下图所示:
步进电机一般有四线、六线和八线三种,三种电机的接线方式如下图所示:
一般买电机的时候,厂家会给出具体的接线图,本例中,笔者就是用的8线步进电机并行高速接法。驱动器采用的是共阳极接法。
线路连接好了,接下来我们就要来分析代码部分了。
首先,我们还是来说一下本例要实现的功能,本例中笔者是分两种方式来实现步进电机的启动与停止:
通过控制定时器0的启动与停止来实现电机0脉冲的输出与关闭
定时器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的完整代码吧,注释也比较全,相信大家一看就能理解了:
复制代码
最后,笔者给大家看一下程序运行的效果吧:
好了,关于使用本节内容笔者就介绍到这里了,有疑问的小伙伴们可以给笔者留言或者直接参与评论,
下一节笔者将给大家介绍“如何让步进电机正反转运行”,详见“SYK-0806-A2S1 工业自动化控制之【09-步进电机正反转】”,感谢大家的支持!
本章附件:
【STC15系列】SYK-0806-A2S1- 08-步进电机启动和停止.rar
(67.31 KB, 下载次数: 2)
|