实验的仿真题图
步进电机是那个宝买的28BYJ-48 驱动模块的ULN2003a也那个宝买的
接线图如下
也可以按照自己的代码来接线,我是按自己代码的串口设置接的线。
话不多说先上代码:
首先电机转动的代码
uchar phasecw[8] ={0x08,0x0c,0x04,0x06,0x02,0x03,0x01,0x09};//正转 电机导通相序 D-C-B-A
uchar phaseccw[8]={0x01,0x03,0x02,0x06,0x04,0x0c,0x08,0x09};//反转 电机导通相序 A-B-C-D
//顺时针转动
- void MotorCW(void)
- {
- uchar i;
- for(i=0;i<8;i++)
- {
- MotorData=phasecw[i];
- Delay_ms(speed);//转速调节
- }
- i=0;
- }
- //逆时针转动
- void MotorCCW(void)
- {
- uchar i;
- for(i=0;i<8;i++)
- {
- MotorData=phaseccw[i];
- Delay_ms(speed);//转速调节
- }
- }
复制代码 根据步进电机的原理:依次给4相高电平就可以驱动步进电机转动而A,B,C,D四相 分别对应P1.0,P1.1,P1.2,P1.3口所以只有让P1口依次为0x01,0x02,0x04,0x08就行了,如果要反转就把它倒过来依次为0x08,0x04,0x02,0x01.一圈4步,所以叫四相四拍。但是我不推荐使用这种,它的一步角度较大电机会有较大抖动。所以采用了四相八拍0x01,0x03,0x02,0x06,0x04,0x0c,0x08,0x09这样电机转动也相对平稳不易出事。
为了实现电机的不停顿转动我将转动函数放在了死循环里,但是在死循环里我们无法控制电机了怎么办了就在死循环里加入一个按键函数这样死循环不停扫描按键我们就可以在k1 里面通过sem控制电机的正反转了。
死循环:while(sem&&sam)
{
MotorCW();
Delay_ms(speed);//转速调节
keypros();
}
while(!sem&&sam)
{
MotorCCW();
Delay_ms(speed);//转速调节
按键控制:
if(k1==0) //检测按键K1是否按下
{
Delay_ms(10); //消除抖动 一般大约10ms
if(k1==0) //再次判断按键是否按下
{
sam=1;
sem=!sem;
}
while(!k1); //检测按键是否松开
}
为什么要用一个键控制正反转了?不仅仅是因为按键不够,更重要的是能消除键位冲突,键位冲突是指同时按下不同的键产生的冲突。消除键位冲突也是每次实验应该考虑的事情。但是这样也产生了新的问题就是当我们用两个键控制正反转时,单片机上电后电机不会转动。而用上述方法的话上电电机就进入死循环开始转动,所以引入sam控制电机的开始于停止。当sam为0与上sem可以使sem失去控制能力,也就是电机不转了。这样也就解决此问题还能控制电机停止
if(k2==0) //检测按键K1是否按下
{
Delay_ms(10); //消除抖动 一般大约10ms
if(k2==0) //再次判断按键是否按下
{
sam=0;
}
while(!k2); //检测按键是否松开
}
我们由步进电机原理可知电机是一步一步的走的,如果我们控制了它每一步的间隔时间就可以达到控制电机的速度的目的。但是对于我买的步进电机来说速度变换的一定程度就不明显了所以我设置了限位这样就减少代码的bug,所以写出按键控制速度代码如下
if(k3==0) //检测按键K1是否按下
{
Delay_ms(10); //消除抖动 一般大约10ms
if(k3==0) //再次判断按键是否按下
{
speed++;
if(speed>6)
{
speed=6;
}
}
while(!k3); //检测按键是否松开
}
if(k4==0) //检测按键K1是否按下
{
Delay_ms(10); //消除抖动 一般大约10ms
if(k4==0) //再次判断按键是否按下
{
speed--;
if(speed<1)
{
speed=1;
}
}
while(!k3); //检测按键是否松开
}
}
理解了这些代码的原理就可以写出总代码了
- #include<reg52.h>
- #define uchar unsigned char
- #define uint unsigned int
- #define MotorData P1 //步进电机控制接口定义
- uchar phasecw[8] ={0x08,0x0c,0x04,0x06,0x02,0x03,0x01,0x09};//正转 电机导通相序 D-C-B-A
- uchar phaseccw[8]={0x01,0x03,0x02,0x06,0x04,0x0c,0x08,0x09};//反转 电机导通相序 A-B-C-D
- uint sem=0,sam=0,speed=3;//信号量,sem控制正反转,sam设置电机是否转动,1转动,0不转动
- sbit k1=P3^1;
- sbit k2=P3^0;
- sbit k3=P3^2;
- sbit k4=P3^3;
- //ms延时函数
- void Delay_ms(uint x)
- {
- uint i,j;
- for(i=0;i<x;i++)
- for(j=0;j<112;j++);
- }
- //顺时针转动
- void MotorCW(void)
- {
- uchar i;
- for(i=0;i<8;i++)
- {
- MotorData=phasecw[i];
- Delay_ms(speed);//转速调节
- }
- i=0;
- }
- //逆时针转动
- void MotorCCW(void)
- {
- uchar i;
- for(i=0;i<8;i++)
- {
- MotorData=phaseccw[i];
- Delay_ms(speed);//转速调节
- }
- }
- //按键函数
- void keypros()
- {
- if(k1==0) //检测按键K1是否按下
- {
- Delay_ms(10); //消除抖动 一般大约10ms
- if(k1==0) //再次判断按键是否按下
- {
- sam=1;
- sem=!sem;
- }
- while(!k1); //检测按键是否松开
- }
- if(k2==0) //检测按键K1是否按下
- {
- Delay_ms(10); //消除抖动 一般大约10ms
- if(k2==0) //再次判断按键是否按下
- {
- sam=0;
- }
- while(!k2); //检测按键是否松开
- }
- if(k3==0) //检测按键K1是否按下
- {
- Delay_ms(10); //消除抖动 一般大约10ms
- if(k3==0) //再次判断按键是否按下
- {
- speed++;
- if(speed>6)
- {
- speed=6;
- }
-
- }
- while(!k3); //检测按键是否松开
- }
- if(k4==0) //检测按键K1是否按下
- {
- Delay_ms(10); //消除抖动 一般大约10ms
- if(k4==0) //再次判断按键是否按下
- {
- speed--;
- if(speed<1)
- {
- speed=1;
- }
-
- }
- while(!k3); //检测按键是否松开
- }
- }
- //主函数
- void main(void)
- {
- while(1)
- {
- MotorData=0x00; //设初值
- keypros();
- while(sem&&sam)
- {
- MotorCW();
- Delay_ms(speed);//转速调节
- keypros();
- }
- while(!sem&&sam)
- {
- MotorCCW();
- Delay_ms(speed);//转速调节
- keypros();
- }
- }
- }
复制代码 本文大体就是这样,如果有什么疑问可以在评论区留言,我会尽量回答。
最后附上代码包:
步进电机实验.zip
(20.67 KB, 下载次数: 559)
|