单片机怎么控制步进电机(用单片机控制步进电机与直流电机其原理是否一样)
我们平时都用到电机,它是一种把电能转换为机械能的装置,下面我们用实例来说说步进电机和直流电机在控制方式上有什么不同。今天我们用两个实例来给刚学单片机的小伙伴们说明,两种电机控制方式的不同。
一、步进电机的控制
步进电机是以脉冲信号电流来驱动,例如步进电机每转一周需要200个脉冲信号来激励,就可以计算出每个励磁信号能使步进电机前进1.8度,其旋转角度与脉冲的个数成正比,而步进电机的正反转有励磁脉冲产生的顺序来控制。通过以上的原理,我们就可以用程序来控制步进电机了,
1)连接:
(一)将P2.0、P2.1、P2.2、P2.3口分别接到P30(在步进电机模块的左侧)的A、B、C、D上。
(二)将M3(步进电机驱动模块输出)的A、B、C、D分别接到步进电机的A、B、C、D四相上,步进电机的COM端接到VCC(M3接口标志的VCC)上。
2)电源:将P35(步进电机驱动模块的左下角)接口用短接冒短接,电源 5V
3)按键命名:与P1低位到高位依次连接的按键一下命名为按键KEY1~KEY8
步进电机控制原理图
步进电机仿真图
#include<reg51.h>
#define uchar unsigned char
#define uint unsigned int
#define T0_COUNT 50 //定时器0的计数值
#define KEY P1 //按键控制
#define MOTOR P2 //步进电机接口
sbit LED = P3^3; //LED指示灯
uint count; //节拍计数值
uint count_time; //计时时间
uchar count_beat; //步进电机驱动数组中的数值计数/*A AB B BC C CD D DA*/
uchar forward[8]={0x01,0x03,0x02,0x06,0x04,0x0c,0x08,0x09}; //四相八拍 正转
/* A AD D DC C CB B BA*/
uchar reverse[8]={0x01,0x09,0x08,0x0c,0x04,0x06,0x02,0x03}; //四相八拍 反转
bit forward_flag; //电机正反转标志, 1:电机正转 0:电机反转
bit stop_flag; //电机停止/运行标志 1:停止 0;运行
bit suspend_flag; //电机暂停/继续标志 1:暂停 0:继续
函数名称:delay_ms软件延时,延时的单位时间在1ms左右
void delay_ms(uint n)
{
uint i;
uchar j;
for(i=0;i<n;i )
for(j=0;j<120;j );
}
函数名称:key_scan功 能:按键扫描返 回 值:扫描的结果,"0"为无按键按下、非"0"为按键值
uchar key_scan()
{
uchar temp = 0;
KEY = 0xff;
if(KEY!=0xff)
{
delay_ms(10); //按键消抖
KEY = 0xff;
if(KEY!=0xff)
{
temp = KEY;
while(KEY!=0xff) //等待按键释放
KEY = 0xff;
}
}
return temp;
}
函数名称:key_behav形 参:uchar key_val:按键值功 能:实现按键功能
void key_behav(uchar key_val)
{
switch(key_val)
{
case 0xfe: //步进电机加速
if((0==stop_flag)&&(0==suspend_flag))
{
count_time -= 10; //减少节拍之间的时间
if(count_time<40)
count_time = 40;
}
break;
case 0xfd: //步进电机减速
if((0==stop_flag)&&(0==suspend_flag))
{
if(count_time<150)
count_time = 10; //增加节拍之间的时间
}
break;
case 0xfb: //步进电机正或反转选择
if((0==stop_flag)&&(0==suspend_flag))
{
forward_flag = ~forward_flag; //切换电机旋转模式
count_beat = 0; //步进电机驱动数组中的数值计数
}
break;
case 0xf7: //步进电机 暂停/继续
if(stop_flag==0)
{
suspend_flag = ~suspend_flag;
if(suspend_flag)
TR0 = 0; //暂停
else
TR0 = 1; //继续
}
break;
case 0xef: //步进电机停止/运行
stop_flag =~ stop_flag;
if(stop_flag)
{ //停止
TR0 = 0; //停止输出
LED = 1; //关闭LED指示灯
count_beat = 0;
count_time = 1000;
forward_flag = 1;
suspend_flag = 0;
}
else
{
LED = 0; //点亮LED指示灯
TR0 = 1; //允许输出
}
break;
default:break;
}
}
函数名称:interrupt_init功 能:中断寄存器初始化 返 回 值:无
void interrupt_init()
{
TMOD = 0x01; //定时器工作方式1
TH0 = (65536-T0_COUNT)/256; //赋值初值
TL0 = (65536-T0_COUNT)%6;
ET0 = 1; //打开定时器 1 中断
EA = 1; //打开总中断
}
函数名称:variable_init功 能:变量、标志初始化
void variable_init() //初始化
{
count_beat = 0; //赋占空比初值
count_time = 100;
forward_flag = 1; //步进电机正转
suspend_flag = 0; //电机继续
stop_flag = 1; //电机停止
}
void main()/*-------------主函数----------*/
{
uchar key_val; //定义变量
variable_init(); //变量初始化
interrupt_init(); //中断初始化
while(1)
{
key_val = key_scan(); //按键扫描,判断哪个按键按下
key_behav(key_val); //按键按下,判断实现的功能
}
}
函数名称:moto_run功 能:中断函数;产生控制电机的PWM波形返 回 值:无
void moto_run() interrupt 1
{
TH0 = (65536-T0_COUNT)/256; //定时器赋初值
TL0 = (65536-T0_COUNT)%6;
count ;
if((count>=count_time))
{
count = 0;
if(forward_flag) //步进电机正转
MOTOR = forward[count_beat];
else //步进电机反转
MOTOR = reverse[count_beat];
count_beat ;
}
if(count_beat>7)
count_beat=0;
}
用单片机仿真板发出脉冲信号由ULN2003驱动5伏步进电机
二、直流电机控制
用单片机控制直流电机,我们都知道由于单片机I/O的灌电流仅有10毫安左右,工作电压为5伏,要驱动额定电压为12伏,额定电流为几百毫安的直流电动机,必须增加驱动电路,才能提供大的驱动电流,我们常用的直流电动机驱动电路有继电器控制的驱动电路、有三极管组成的H桥驱动电路、电机驱动芯片、达林顿管驱动器等。我了达到电机正反转,我焊接了一个由三极管组成的驱动桥电路,来驱动电机的正反转。
微型直流电机驱动桥
1)连接:
(1)将P2.0、P2.1口接到P31(在直流电机模块的左侧)的DC_A、DC_B上。
(2)将B1(直流电机驱动模块输出)接到直流电机上。
(3)将P3.3口接到某一个LED接口上(P8或P17)。作为直流电机状态指示灯:亮,直 流电机运行;灭,直流电机停止
2)电源:将P36(直流电机驱动模块的左上角)接口用短接冒短接,电源 5V
3)按键命名:与P1低位到高位依次连接的按键一下命名为按键1~8
4)效果:启动程序,直流电机默认停止状态,运行指示灯熄灭
按键1:在直流电机运行的状态下,直流电机加速
按键2:在直流电机运行的状态下,直流电机减速
按键3:在直流电机运行的状态下,直流电机正反转切换
按键4:直流电机暂停/继续
按键5:直流电机停止/运行
直流电机控制原理图
直流电机仿真图
直流电机控制参考程序
#include<at89x52.h>
#define uchar unsigned char
#define uint unsigned int
#define T0_COUNT 100 //定时器0的计数值
#define KEY P1 //按键控制
#define PWM 100 //PWM计数值的上限值
#define INIT_VAL_PWM 20 //PWM占空比初始值
#define INCREMENT_PWM 10 //PWM控制时的增量大小
sbit DC_Moto_A = P2^0; //脉冲输入引脚
sbit DC_Moto_B = P2^1;
sbit LED = P3^3; //LED指示灯接口
uchar count_PWM; //PWM计数值
uchar val_PWM; //PWM占空比的值(加速可调)
bit forward_flag; //电机正反转标志, 1:电机正转 0:电机反转
bit stop_flag; //电机停止/运行标志 1:停止 0;运行
bit suspend_flag; //电机暂停/继续标志 1:暂停 0:继续
函数名称:delay_ms,形参:uint n:延时时间的长度,功能是软件延时,延时的单位时间在1ms左右
void delay_ms(uint n)
{
uint i;
uchar j;
for(i=0;i<n;i )
for(j=0;j<120;j );
}
函数名称:key_scan,功能:按键扫描,返 回 值:扫描的结果,"0"为无按键按下、非"0"为按键值
uchar key_scan() //按键检测
{
uchar temp = 0;
KEY = 0xff;
if(KEY!=0xff) //按键消抖
{
delay_ms(10);
KEY = 0xff;
if(KEY!=0xff)
{
temp = KEY;
while(KEY!=0xff) //等待按键释放
KEY = 0xff;
}
}
return temp;
}
函数名称:key_behav,形 参:uchar key_val:按键值,功能:实现按键功能
void key_behav(uchar key_val)
{
switch(key_val)
{
case 0xfe: //电机加速
if((0==stop_flag)&&(0==suspend_flag))
{
val_PWM = INCREMENT_PWM; //增加占空比
if(val_PWM>PWM) //PWM表示占空比的上限值
val_PWM = PWM;
}
break;
case 0xfd: //电机减速
if((0==stop_flag)&&(0==suspend_flag)) //他是如何加速的事通过什么来实现的呢
{
if(val_PWM>=INCREMENT_PWM)
val_PWM -= INCREMENT_PWM; //增加占空比
}
break;
case 0xfb: //电机正或反转选择
if((0==stop_flag)&&(0==suspend_flag))
forward_flag = ~forward_flag; //切换电机旋转模式
break;
case 0xf7: //电机暂停/继续
if(stop_flag==0)
{
suspend_flag = ~suspend_flag;
if(suspend_flag)
{
TR0 = 0; //暂停
DC_Moto_A = 0;
DC_Moto_B = 0;
}
else
TR0 = 1; //继续
}
break;
case 0xef: //电机停止/运行
stop_flag =~ stop_flag;
if(stop_flag)
{ //停止
TR0 = 0; //停止PWM输出
val_PWM = INIT_VAL_PWM; //初始化变量和标志
LED = 1; //关闭指示灯
forward_flag = 1;
suspend_flag = 0; //停止运行的时候初始化一下
DC_Moto_A = 0;
DC_Moto_B = 0;
}
else
{
LED = 0; //点亮指示灯
TR0 = 1; //允许输出PWM波形
}
break;
default:break;
}
}
函数名称:interrupt_init,功能:中断寄存器初始化
void interrupt_init() //初始化
{
TMOD = 0x01; //选择定时器/计数器工作方式1
TH0 = (65536-T0_COUNT)/256;
TL0 = (65536-T0_COUNT)%6;
ET0 = 1; //开定时器/计数器中断
TR0 = 1;
EA = 1; //开总中断
}
函数名称:variable_init,功能:变量、标志初始化
void variable_init() //变量初始化
{
val_PWM = INIT_VAL_PWM;
forward_flag = 1; //电机正反转标志
suspend_flag = 0; //电机暂停/继续标志
stop_flag = 1; //电机停止/运行标志
LED = 1; //关闭指示灯
DC_Moto_A = 0; //P2^0口输入
DC_Moto_B = 0; //P2^1口输入
}
void main() /*-------------主函数----------*/
{
uchar key_val;
variable_init(); //变量初始化
interrupt_init(); //中断函数初始化
while(1)
{
do
key_val = key_scan();
while(0==key_val);
key_behav(key_val);
}
}
函数名称:moto_run,功 能:中断函数;产生控制电机的PWM波形(定时器1中断)
void moto_run() interrupt 1 //选择正转还是反转跳入中断
{
TH0 = (65536-T0_COUNT)/256; //核心是在中断里面
TL0 = (65536-T0_COUNT)%6;
count_PWM ; //PWM计数值
if(forward_flag)
{ //电机正转
DC_Moto_B = 0;
if(count_PWM<val_PWM) //产生PWM
DC_Moto_A = 1;
else
DC_Moto_A = 0;
}
else
{ //电机反转
DC_Moto_A = 0;
if(count_PWM<val_PWM) //产生PWM
DC_Moto_B = 1;
else
DC_Moto_B = 0;
}
if(count_PWM>=PWM)
count_PWM = 0;
}
用单片机仿真板发出PWM波形去控制H桥来驱动直流小电机
以上程序我们是用PWM实现对电机的调速的,因为PWM信号只有两种状态,高电平和低电平,对于一个给定的周期来说,高电平所占的时间和周期之比我们称之为占空比,我们只要改变控制信号的占空比就可以改变电机的转速。
从以上两个实例可以看出,不同的电机,所用的控制方式是不一样的。希望通过这两个实例的推送对刚学单片机的朋友有所帮助,有问题欢迎留言讨论,共同进步。
,免责声明:本文仅代表文章作者的个人观点,与本站无关。其原创性、真实性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容文字的真实性、完整性和原创性本站不作任何保证或承诺,请读者仅作参考,并自行核实相关内容。文章投诉邮箱:anhduc.ph@yahoo.com