STM32驱动步进电机28BYJ
<p style="text-indent: 2em;">步进电机是一种将电脉冲信号转化为角位移的执行机构。在非超载的情况下,电机的转速、停止的位置只取决于脉冲信号的频率和脉冲数,而不受负载变化的影响,即给电机加一个脉冲信号,电机则转过一个步距角。这一线性关系的存在,加上步进电机只有周期性的误差而无累积误差等特点。使得在速度、位置等控制领域用进电机来控制变的非常的简单。</p><p style="text-indent: 2em;">步进电机的特点:步进电机必须加驱动才可以运转,驱动信号必须为脉冲信号,没有脉冲的时候,步进电机静止,如果加入适当的脉冲信号,就会以一定的角度(称为角)转动。转动的速度和脉冲的频率成正比。如果想改变步进电机的转动方向,只需要改变给定步进电机的脉冲顺序即可。</p><p style="text-indent: 2em;">上面是关于步进电机的一些基础知识,今天我要给大家讲讲如何利用STM32来驱动步进电机28BYJ。虽然网上有许多的关于28BYJ的驱动程序,不过大多是用51实现的,我现在正好要用到28BYJ,而且驱动也写好了,因此在这里就分享出来用STM32驱动28BYJ的完整程序,方便大家学习使用。</p><p style="text-indent: 2em;">在开始讲解之前,先说明一下,我使用的是STM32的库函数,开发工具是Keil,大家如果还不清楚如何在Keil下搭建STM32的库函数工程,那么可以参考我的博文:<a href="http://www.only2fire.com/archives/3.html" target="_blank"><span style="color: rgb(255, 0, 0);">Keil下建立STM32库函数工程</span></a>。</p><p style="text-indent: 0em;"> 这里是我的驱动28BYJ步进电机的完整的Keil工程,有需要的可以下载看看。文件:<a class="btn btn-success" href="https://pan.baidu.com/share/init?surl=sjr2qap" target="_blank">点此下载</a> 密码:<span style="color: rgb(255, 0, 0);">i2gg</span>。</p><p style="text-indent: 2em;">这里对于28BYJ的一些细节的东西,我就不讲太多,有想了解更详细信息的,可以参看28BYJ的手册。我在这儿只说一些大家关心的问题。</p><p style="text-indent: 2em;"><span style="color: rgb(255, 0, 0);">我驱动28BYJ采用的是双相八拍(A-AB-B-BC-C-CD-D-DA),一个循环使转子转动5.625/8度,那么要想使转子转过一圈,就要让这个循环512次。</span><br/></p><p style="text-indent: 2em;">由于STM32的IO口输出信号不足以驱动28BYJ,因此我使用了ULN2003对IO口信号进行放大,然后再连接到步进电机的相应接口上。这里是我使用的引脚定义:<span style="color: rgb(0, 112, 192);">IN1</span>:<span style="color: rgb(255, 0, 0);">PB3</span> <span style="color: rgb(0, 112, 192);">IN2</span>:<span style="color: rgb(255, 0, 0);">PB2</span> <span style="color: rgb(0, 112, 192);">IN3</span>:<span style="color: rgb(255, 0, 0);">PB1</span> <span style="color: rgb(0, 112, 192);">IN4</span>:<span style="color: rgb(255, 0, 0);">PB0</span>,下面是连接的电路图:</p><p style="text-align:center"><img src="/uploads/AilsonJack/2018.08.18/1534571111212290.png" onclick="preview_image('/uploads/AilsonJack/2018.08.18/1534571111212290.png')"/></p><p style="text-indent: 2em;">下图是四相八拍逆时针方向的一个相序图:</p><p style="text-indent: 2em;"><img src="/uploads/AilsonJack/2018.08.18/1534571113449661.jpg" onclick="preview_image('/uploads/AilsonJack/2018.08.18/1534571113449661.jpg')"/></p><p style="text-indent: 2em;">我在程序中定义的正反转脉冲数组:<br/><span style="color: rgb(0, 112, 192);">u8 cw[8]={0X09,0X01,0X03,0X02,0X06,0X04,0X0C,0X08};//双相八拍正转(顺时针)<br/>u8 ccw[8]={0X08,0X0C,0X04,0X06,0X02,0X03,0X01,0X09};//双相八拍反转(逆时针)</span></p><p style="text-indent: 2em;">这个数组最终体现在<span style="color: rgb(255, 0, 0);">PB</span>口的<span style="color: rgb(255, 0, 0);">低4位</span>,从上述数组中挑一个值讲讲,其余的类似。<span style="color: rgb(255, 0, 0);">ccw[0]=0X08</span>,即二进制的<span style="color: rgb(255, 0, 0);">0000 1000</span>,也即<span style="color: rgb(255, 0, 0);">PB3 PB2 PB1 PB0 – > 1000</span>,对应的是<span style="color: rgb(0, 112, 192);">PB3:橙 PB2:黄 PB1:粉 PB0:蓝</span>,对应结果和上图的第二列(序号1)一致,其余的列依此类推。要想步进电机转动的方向反向,那么就让其脉冲反向即可,这也就是<span style="color: rgb(255, 0, 0);">ccw</span>与<span style="color: rgb(255, 0, 0);">cw</span>的关系啦。理解了这个之后,剩下的大家看看我的程序就明白了。我的程序如下:</p><p style="text-indent: 2em;"><span style="color: rgb(255, 0, 0);">motor.h:</span></p><pre class="brush:cpp;toolbar:false PrismJs">#ifndef MOTOR_H
#define MOTOR_H
#include "stm32f10x.h"
#include "delay.h"
void Motor_Init(void);//步进电机初始化
void Motor_TurnPosi(u8 ms);//步进电机正转
void Motor_TurnNeg(u8 ms);//步进电机反转
#endif</pre><p style="text-indent: 2em;"><span style="color: rgb(255, 0, 0);">motor.c:</span></p><pre class="brush:cpp;toolbar:false PrismJs">#include "motor.h"
#define PluseNum 8 //步进电机拍数
u8 cw[8]={0X09,0X01,0X03,0X02,0X06,0X04,0X0C,0X08};//双相八拍正转(顺时针)
u8 ccw[8]={0X08,0X0C,0X04,0X06,0X02,0X03,0X01,0X09};//双相八拍反转(逆时针)
/*
*************************************************************************
*函数:void Motor_Init(void)
*说明:初始化步进电机的相关引脚
*参数:无
*返回值:无
*注: 橙:PB3 黄:PB2 褐:PB1 蓝:PB0
*By:Ailson Jack
*Date:2015.04.01
*************************************************************************
*/
void Motor_Init(void)
{
GPIO_InitTypeDef Motor_Pin;//声明引脚初始化结构体
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);//使能PB口时钟
Motor_Pin.GPIO_Pin=GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3;//PB0 PB1 PB2 PB3
Motor_Pin.GPIO_Mode=GPIO_Mode_Out_PP;//推挽输出模式
Motor_Pin.GPIO_Speed=GPIO_Speed_50MHz;//IO口速度50MHz
GPIO_Init(GPIOB,&Motor_Pin);//初始化PB0 PB1 PB2 PB3
GPIO_Write(GPIOB,0XFF);//初始化输出高电平
}
/*
*************************************************************************
*函数:void Motor_TurnPosi(u8 ms)
*说明:让步进电机正转
*参数:ms:各个脉冲之间的时间间隔,单位:ms
*注: 如果发现步进电机的轴没有转动,但是有轻微的振动,那么可以通过适当的增大
* 或减小ms的设定值,来使步进电机转动起来
*返回值:无
*By:Ailson Jack
*Date:2015.04.01
*************************************************************************
*/
void Motor_TurnPosi(u8 ms)
{
u8 i=0;
for(i=0;i<PluseNum;i++)
{
GPIO_Write(GPIOB,cw[i]);
delay_ms(ms);
}
GPIO_Write(GPIOB,0XFF);
}
/*
*************************************************************************
*函数:void Motor_TurnNeg(u8 ms)
*说明:让步进电机反转
*参数:ms:各个脉冲之间的时间间隔,单位:ms
*返回值:无
*注: 如果发现步进电机的轴没有转动,但是有轻微的振动,那么可以通过适当的增大
* 或减小ms的设定值,来使步进电机转动起来
*By:Ailson Jack
*Date:2015.04.01
*************************************************************************
*/
void Motor_TurnNeg(u8 ms)
{
u8 i=0;
for(i=0;i<PluseNum;i++)
{
GPIO_Write(GPIOB,ccw[i]);
delay_ms(ms);
}
GPIO_Write(GPIOB,0XFF);
}</pre><p style="text-indent: 2em;"><span style="color: rgb(255, 0, 0);">main.c:</span></p><pre class="brush:cpp;toolbar:false PrismJs">#include "stm32f10x.h"
#include "delay.h"
#include "motor.h"
int main(void)
{
int i=0;
GPIO_InitTypeDef Motor_Pin;//声明引脚初始化结构体
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);//使能PA口时钟
Motor_Pin.GPIO_Pin=GPIO_Pin_11|GPIO_Pin_15;//按键输入口,用来切换电机转向
Motor_Pin.GPIO_Mode=GPIO_Mode_IPU;//上拉输入
GPIO_Init(GPIOA,&Motor_Pin);//初始化
Motor_Init();//初始化步进电机
while(1)
{
if(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_11) == 0)
{
for(i=0;i<512;i++)//循环512次,即转子转过360度
{
Motor_TurnPosi(9);
}
}
if(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_15) == 0)
{
for(i=0;i<512;i++)//循环512次,即转子转过360度
{
Motor_TurnNeg(9);
}
}
delay_ms(100);
}
}</pre><p style="text-indent: 2em;">将程序下载到板子上,接好步进电机与STM32的引脚连接,用两个按键或者直接将按键输入口接一下地,是不是看到步进电机动起来了<img src="/UEditor/dialogs/emotion/images/face/i_f07.gif"/>。</p><p style="text-indent: 2em;"><span style="color: rgb(255, 0, 0);">注:</span>我这个驱动在我自己做的STM32小系统上能跑起来,但是在我买的开发板上貌似有点问题,而且总感觉STM32驱动步进电机的力不大,应该是IO口输出能力的问题,但是想想自己加了个驱动板,按理说,应该不会出现驱动力不足这个现象,有知道怎么回事的朋友可以交流一下。只想说,知识的世界真的很大,怎么学都有学的<img src="/UEditor/dialogs/emotion/images/face/i_f01.gif"/>。</p>
暂无评论,要不要来个沙发
发表评论
JLink V9掉固件修复(灯不亮) 3Zephyr笔记2 - 在STM32F429上运行HelloWorld 2计算NandFlash要传入的行地址和列地址 1Linux MMC子系统 - 6.eMMC 5.1工作模式-设备识别模式 0Linux MMC子系统 - 5.eMMC 5.1工作模式-引导模式 0Linux MMC子系统 - 4.eMMC 5.1常用命令说明(2) 0
标签云
Linux嵌入式实用技巧ARM内核学习问题集合CC++编程语言阅读笔记汇编Linux内核完全注释Windows驱动开发计算机基础ARM11ARMv7-ASTM32IDESublimeLinux内核学习eMMCMMC子系统Ubuntu操作系统OfficeVMWareAPUEgccRTOS中断漫游世界随笔感悟开发工具软件应用编程VsCodearmccarmclang编译器ZephyrSPIJLink网卡驱动安装各种芯片库函数NFSμCOS内核sambaFlashUnix命令与脚本输入法Linux内核设计与实现gitRIFFWAVJATGFTPar8161安装centos有线上网μCGUI字库工程建立右键菜单网络文件系统Firefox百度NTFS文件系统CodeBlocksCentOS数据结构算法PhotoShop51KeilQTUltraEditscanfglibc宏定义UIDGID优先级娱乐天地SourceInsight磁盘扇区总线I2CPDFBComparePythonI2SFPUMakefileSWDCPUARP软件推荐FileZilla