STM32驱动步进电机28BYJ
 2015.04.01    |      STM32    |     AilsonJack    |     暂无评论    |     2007 views
By: Ailson Jack
Date: 2015-04-01
个人博客: http://www.only2fire.com/
<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;">&nbsp;&nbsp;这里是我的驱动28BYJ步进电机的完整的Keil工程,有需要的可以下载看看。文件:<a class="btn btn-success" href="https://pan.baidu.com/share/init?surl=sjr2qap" target="_blank">点此下载</a>&nbsp; 密码:<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(&#39;/uploads/AilsonJack/2018.08.18/1534571111212290.png&#39;)"/></p><p style="text-indent: 2em;">下图是四相八拍逆时针方向的一个相序图:</p><p style="text-indent: 2em;"><img src="/uploads/AilsonJack/2018.08.18/1534571113449661.jpg" onclick="preview_image(&#39;/uploads/AilsonJack/2018.08.18/1534571113449661.jpg&#39;)"/></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 – &gt; 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&nbsp;MOTOR_H #define&nbsp;MOTOR_H #include&nbsp;&quot;stm32f10x.h&quot; #include&nbsp;&quot;delay.h&quot; void&nbsp;Motor_Init(void);//步进电机初始化 void&nbsp;Motor_TurnPosi(u8&nbsp;ms);//步进电机正转 void&nbsp;Motor_TurnNeg(u8&nbsp;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&nbsp;&quot;motor.h&quot; #define&nbsp;PluseNum&nbsp;8&nbsp;&nbsp;&nbsp;&nbsp;//步进电机拍数 u8&nbsp;cw[8]={0X09,0X01,0X03,0X02,0X06,0X04,0X0C,0X08};//双相八拍正转(顺时针) u8&nbsp;ccw[8]={0X08,0X0C,0X04,0X06,0X02,0X03,0X01,0X09};//双相八拍反转(逆时针) /* ************************************************************************* *函数:void&nbsp;Motor_Init(void) *说明:初始化步进电机的相关引脚 *参数:无 *返回值:无 *注:&nbsp;&nbsp;橙:PB3&nbsp;&nbsp;&nbsp;&nbsp;黄:PB2&nbsp;&nbsp;&nbsp;&nbsp;褐:PB1&nbsp;&nbsp;&nbsp;&nbsp;蓝:PB0 *By:Ailson&nbsp;Jack *Date:2015.04.01 ************************************************************************* */ void&nbsp;Motor_Init(void) { &nbsp;&nbsp;&nbsp;&nbsp;GPIO_InitTypeDef&nbsp;Motor_Pin;//声明引脚初始化结构体 &nbsp;&nbsp;&nbsp;&nbsp;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);//使能PB口时钟 &nbsp;&nbsp;&nbsp;&nbsp;Motor_Pin.GPIO_Pin=GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3;//PB0&nbsp;PB1&nbsp;PB2&nbsp;PB3 &nbsp;&nbsp;&nbsp;&nbsp;Motor_Pin.GPIO_Mode=GPIO_Mode_Out_PP;//推挽输出模式 &nbsp;&nbsp;&nbsp;&nbsp;Motor_Pin.GPIO_Speed=GPIO_Speed_50MHz;//IO口速度50MHz &nbsp;&nbsp;&nbsp;&nbsp;GPIO_Init(GPIOB,&amp;Motor_Pin);//初始化PB0&nbsp;PB1&nbsp;PB2&nbsp;PB3 &nbsp;&nbsp;&nbsp;&nbsp;GPIO_Write(GPIOB,0XFF);//初始化输出高电平 } /* ************************************************************************* *函数:void&nbsp;Motor_TurnPosi(u8&nbsp;ms) *说明:让步进电机正转 *参数:ms:各个脉冲之间的时间间隔,单位:ms *注:&nbsp;&nbsp;如果发现步进电机的轴没有转动,但是有轻微的振动,那么可以通过适当的增大 *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;或减小ms的设定值,来使步进电机转动起来 *返回值:无 *By:Ailson&nbsp;Jack *Date:2015.04.01 ************************************************************************* */ void&nbsp;Motor_TurnPosi(u8&nbsp;ms) { &nbsp;&nbsp;&nbsp;&nbsp;u8&nbsp;i=0; &nbsp;&nbsp;&nbsp;&nbsp;for(i=0;i&lt;PluseNum;i++) &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;GPIO_Write(GPIOB,cw[i]); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;delay_ms(ms); &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;GPIO_Write(GPIOB,0XFF); } /* ************************************************************************* *函数:void&nbsp;Motor_TurnNeg(u8&nbsp;ms) *说明:让步进电机反转 *参数:ms:各个脉冲之间的时间间隔,单位:ms *返回值:无 *注:&nbsp;&nbsp;如果发现步进电机的轴没有转动,但是有轻微的振动,那么可以通过适当的增大 *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;或减小ms的设定值,来使步进电机转动起来 *By:Ailson&nbsp;Jack *Date:2015.04.01 ************************************************************************* */ void&nbsp;Motor_TurnNeg(u8&nbsp;ms) { &nbsp;&nbsp;&nbsp;&nbsp;u8&nbsp;i=0; &nbsp;&nbsp;&nbsp;&nbsp;for(i=0;i&lt;PluseNum;i++) &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;GPIO_Write(GPIOB,ccw[i]); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;delay_ms(ms); &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;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&nbsp;&quot;stm32f10x.h&quot; #include&nbsp;&quot;delay.h&quot; #include&nbsp;&quot;motor.h&quot; int&nbsp;main(void) { &nbsp;&nbsp;&nbsp;&nbsp;int&nbsp;i=0; &nbsp;&nbsp;&nbsp;&nbsp;GPIO_InitTypeDef&nbsp;Motor_Pin;//声明引脚初始化结构体 &nbsp;&nbsp;&nbsp;&nbsp;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);//使能PA口时钟 &nbsp;&nbsp;&nbsp;&nbsp;Motor_Pin.GPIO_Pin=GPIO_Pin_11|GPIO_Pin_15;//按键输入口,用来切换电机转向 &nbsp;&nbsp;&nbsp;&nbsp;Motor_Pin.GPIO_Mode=GPIO_Mode_IPU;//上拉输入 &nbsp;&nbsp;&nbsp;&nbsp;GPIO_Init(GPIOA,&amp;Motor_Pin);//初始化 &nbsp;&nbsp;&nbsp;&nbsp;Motor_Init();//初始化步进电机 &nbsp;&nbsp;&nbsp;&nbsp;while(1) &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_11)&nbsp;==&nbsp;0) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for(i=0;i&lt;512;i++)//循环512次,即转子转过360度 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Motor_TurnPosi(9); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_15)&nbsp;==&nbsp;0) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for(i=0;i&lt;512;i++)//循环512次,即转子转过360度 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Motor_TurnNeg(9); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;delay_ms(100); &nbsp;&nbsp;&nbsp;&nbsp;} }</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>
欢迎关注博主的公众号呀,精彩内容随时掌握:
热情邀请仔细浏览下博客中的广告,万一有对自己有用或感兴趣的呢。◕ᴗ◕。。
如果这篇文章对你有帮助,记得点赞和关注博主就行了^_^,当然了能够赞赏博主,那就非常感谢啦!
注: 转载请注明出处,谢谢!^_^
转载请注明来源: 本文链接:  By: AilsonJack
STM32驱动步进电机28BYJ  |  说好一起走
暂无评论,要不要来个沙发
发表评论

 
Copyright © 2015~2023  说好一起走   保留所有权利   |  百度统计  蜀ICP备15004292号