用AT89C52单片机作为控制器,设计简单实用的步进电机控制系统
1 引言
作为工业领域广泛应用的控制电机,步进电机具有出色的开环性能,易于实现数字化、智能化控制。步进电机组成的控制系统具有结构简单、性能稳定、造价便宜等特点,在工业控制领域中得到了广泛的应用。单片机对步进电机的控制成本低、操作灵活,在步进电机的控制中得到了广泛的应用。本文以AT89C52单片机作为控制器设计一种新型的两相混合式步进电机的控制系统。
2 系统结构设计
控制系统主要由单片机、键盘、显示、驱动、PC上位机等5个模块组成,其中PC上位机用于编写及烧录程序。控制器通过相应的IO接口,将控制指令发送至驱动电路,可以控制步进电机的运行,完成系统的伺服控制。
控制系统可实现以下功能:(1)控制步进电机的启动和停止、运行方向、运行速度。(2)显示步进电机的运行状态、方向、转速。(3)通过软件实现细分控制。图1为控制系统总体结构图。
图1 控制系统总体结构图
3 系统硬件设计
单片机模块主要由AT89C52单片机及外围滤波、电源管理、晶振和复位电路组成。AT89C52单片机具有8KB内存的可编程可擦除只读存储器,便于反复的进行程序的编写。电源管理电路提供的3.5V和5V电压分别给单片机、晶振、LED和控制电路供电。12MHZ的晶振给单片机提供时钟信号。单片机的串口用于和PC上位机的通信以及烧录软件程序。P1口控制驱动电路开关管的通断。P0和P2口控制LCD1602和LED组成的显示模块。P3口检测键盘信号及外部中断信号。
3.2 键盘及显示模块
控制系统设置了5位独立按键组成的键盘模块以及由LCD1602和5位LED组成的显示模块。通过键盘可以对步进电机进行正转、反转、加速、减速、停止功能的操作。步进电机运行时的状态信息可以通过显示模块直观的显示出来。图2为键盘及显示模块硬件原理图。
键盘模块的特点在于用单片机的两个外部中断来控制步进电机进行加、减速,即每引入一次外部中断,步进电机加/减速一次。正转、反转、停止按键分别由单片机的P3.0、P3.1、P3.4口引入。加速、减速按键分别由单片机的P3.2和P3.3口引入。
LCD1602的数据/命令选择端、读写选择端、使能信号分别接在单片机的P2.0、P2.1、P2.2口上,数据口接在单片机的P0口上。LCD1602可以显示步进电机的5种运行状态以及运行速度。5位LED通过74LS138接在单片机的P2.3—P2.5口上,5位LD分别用于表示步进电机的正转、反转、加速、减速、停止5种运行状态。
图2 键盘及显示模块硬件原理图
3.3 驱动模块
控制系统的电机驱动模块采用双极性驱动的方式。双极性驱动是指步进电机线圈中电流的流动方向不是单向的,即绕组中的电流有时沿某一方向流动,有时沿相反的方向流动。双极性驱动电路可以同时驱动四线式或六线式的两相混合式步进电机。
控制系统所选用的二相混合式步进电机工作时的额定电压为12V,绕组的阻值为1.5Ω,额定电流为8A。由于该步进电机工作时的电流较大,因此需要选择额定电流较大的功率开关管,否则步进电机工作时较大的工作电流产生的热效应极易烧毁开关管。功率开关管BUW49工作时的额定电压为80V,额定电流为30A,属于高电流型功率开关管,因此完全能够满足需要。
根据步进电机的工作原理,当控制电路给驱动电路发出相应的脉冲信号时,电机绕组的通电顺序为A+B+→A-B+→A-B-→A+B-,其4个状态按顺序进行循环,电机则正向转动。若相序变为A+B-→A-B-→A-B+→A+B+,电机则逆向转动。
因此,当单片机AT89C52的引脚P1.0至P1.7输出的脉冲时序依次为10011001→01101001→01100110→10010110时,控制各个开关管依次导通,产生相应的正向通电时序,从而驱动步进电机正向旋转。同样,当单片机的引脚输出的脉冲时序相反时,电机则反向旋转。图3为驱动电路硬件原理图。
图3 驱动电路硬件原理图
控制系统的硬件原理图由电子技术虚拟仿真软件Proteus 7.5进行仿真,仿真时两相混合式步进电机的参数按照控制系统所选用的步进电机实际参数设置。经过仿真得出该系统能够实现对步进电机的正/反转、停止、加/减速的控制,并且控制非常灵敏、工作可靠、不会出现误操作。
步进电机在运行时的运行状态、速度参数以及按键的操作状态能够以英文的形式非常直观的显示在LCD1602和5位LED上。通过分析仿真时虚拟示波器测出的A、B两相的绕组电压波形得知,步进电机在系统仿真运行的过程中具有良好的动态响应。图4为控制系统整体硬件原理图。
图4 控制系统整体硬件原理图
4 系统软件设计
4.1 步进电机工作方式
由于按双四拍方式工作时步进电机不容易失步,并且控制精度较高,因此步进电机采用双四拍的工作方式。这种工作方式每次都有两相绕组导通,两相绕组处在相同的电压之下,以A+B+→A-B+→A-B-→A+B-(或反向)方式导通。当A、B绕组完成一次通电循环以后,磁场旋转一周,转子则前进一个步距角。
4.2 运行方向控制
步进电机的运行方向由其内部绕组的通电顺序及通电方式决定。由于两相双四拍步进电机不容易失步,控制精度比较高,所以本文采用两相双四拍的工作方式对步进电机进行控制。
对于两相双四拍工作方式:
正向旋转:A+B+→A-B+→A-B-→A+B-反向旋转:A+B-→A-B-→A-B+→A+B+两相双四拍控制模型如表3.1所示。
表3.1 两相双四拍控制模型
4.3 运行速度控制
控制步进电机的运行速度,实际上是控制驱动脉冲的发出频率或换相周期。即在加速的过程中,使驱动脉冲的发出频率升高;在减速的过程中,使驱动脉冲的发出频率降低。对驱动脉冲频率的控制可以通过软件延时和硬件中断的方式来实现。
软件延时是指根据所需的延时时间常数编写一个延时子程序,当CPU执行延时子程序时,系统达到延时的目的。采用软件延时方式,CPU一直被占用,使得CPU的利用率降低。
可编程的硬件定时器可以对系统的时钟脉冲进行计数,计数值可以通过编程的方式设定。当计数到预定的脉冲数时,定时器产生中断信号,系统得到所需的延时时间。定时器延时可以提高CPU的利用率。
4.4 系统程序设计
系统程序设计的思想是:
(1)对单片机进行初始化:首先应该关中断,然后对用到的一些寄存器和功能模块进行初始化,最后再开中断,并且给定步进电机的速度初值和每次加速/减速时速度变化的幅值。(2)调入子程序:分块调入方向、速度、键盘、显示的子程序。速度控制程序写入外部中断程序中,这样可以在不改变运动方向的前提下改变速度的参数。(3)等待功能按键按下:采用查询方式编写按键程序,通过按键程序扫描等待功能按键的按下。(4)执行按键功能:当程序检测到有按键被按下后,执行相应的功能,并且显示步进电机对应的运行状态信息。图5为系统程序结构图。图5 系统程序结构图
5 实验验证
在实验中本系统选57HS56DF101TK-01混合式步进电机作为控制对象。该步进电机为两相四线步进电机,步距角为1.8°,额定电流为8A,静转矩为10Kg·cm。图6为控制系统实物图。
图6 控制系统实物图
实验时,测得电机绕组阻值Rs为1.5Ω,系统选择12V直流电源供电,符合步进电机的要求。图7为步进电机运行时A相的电压波形图。图8为步进电机的静态矩角特性曲线图。
图7 步进电机A相电压图
图8 步进电机矩角特性曲线图
实验结果说明,本控制系统在步进电机的运行过程中可以实现对步进电机的运行控制,改变步进电机的工作状态,控制精确,能够较好的满足工作要求。
6 结语
本文基于AT89C52单片机设计的两相混合式步进电机控制系统具有体积小、可靠性高、功能丰富、造价便宜等特点,适用范围广,具有很强的实用价值和经济价值。
(编自《电气技术》,原文标题为“基于AT89C52单片机的步进电机控制系统研究”,作者为何冲、王淑红 等。)
用单片机控制步进电机与直流电机其原理是否一样?
我们平时都用到电机,它是一种把电能转换为机械能的装置,下面我们用实例来说说步进电机和直流电机在控制方式上有什么不同。今天我们用两个实例来给刚学单片机的小伙伴们说明,两种电机控制方式的不同。
一、步进电机的控制
步进电机是以脉冲信号电流来驱动,例如步进电机每转一周需要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
4)效果:启动程序,步进电机默认停止状态
按键4:步进电机暂停/继续
按键5:步进电机停止/运行
步进电机控制原理图
步进电机仿真图
#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)%256;
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)%256;
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)%256;
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)%256;
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信号只有两种状态,高电平和低电平,对于一个给定的周期来说,高电平所占的时间和周期之比我们称之为占空比,我们只要改变控制信号的占空比就可以改变电机的转速。
从以上两个实例可以看出,不同的电机,所用的控制方式是不一样的。希望通过这两个实例的推送对刚学单片机的朋友有所帮助,有问题欢迎留言讨论,共同进步。
相关问答
步进电机 的 单片机控制 是什么 原理 ?单片机按步进电机工作原理来控制的,编程总是比较灵活,步进电机是按“节拍”工作的,比如两相电机,一般是四线制,A,/A,B,/B,可以依次送电,让其工作,也可...单片...
单片机控制步进电机 驱动器这个驱动器的功能是为了配合控制源来说的。驱动器的脉冲输入和方向信号的输入都是脉冲信号!1:单脉冲就是脉冲输入一直有,通过方向输入的高低电平来...
单片机控制步进电机 制动?从底层技术上来说,很简单,就是将下一相的通电时间和断电时间,均比前一相延后一点,每次一点,这样就制动了.步进电机在高速运行的时候也会受惯性的影响的,如果...
诸位朋友,求了解, 步进电机 驱动器 控制步进电机 的 原理 ?[回答]步进电机驱动器当然是用来驱动步进电机的,驱动板上有几个端口,只要你按着说明书接线对了,你只需通过DSP的PWM模块向驱动板输入一定频率的PWM波,之后...
51 单片机控制步进电机 ,用按键控制单片机的运转,按一下走一步停下来,再摁一下再走一步,如此循环?这个不难的。就一个电机处理程序,一个按键处理程序呗这个不难的。就一个电机处理程序,一个按键处理程序呗
Proteus的51 单片机控制步进电机 ,实现电机正反转?Proteus的51单片机控制步进电机,一般是控制其相序分配的顺逆从而控制正反转,一般而言,步进电机相序分配可以做成一个数组比如step[]={0x03,0x06,0x0c,0x09},这...
51 单片机控制步进电机 ?用单片机同时是不可能的,当然,时间间隔小到可以接受,跑几个任务,那也可以视为同时。要实现真正意义上的同时,用FPGA/CPLD是可以完成的。话说回来,也许你的...
步进电机 基本 控制 方法?可以用单片机+全集成步进电机驱动芯片来整全应用,这样比较简单,控制上很方便。用普通的51单片机像AT89C2051或STC12C1052+THB7128或THB6064这类芯片来组合...
如何用C语言 控制步进电机 ,正转后自动反转?首先要看你的电机是直流电机还是步进电机。直流电机就简单了,只有两根线,电机两端电压正负极改变就可以实现正转反转。不过要加电机驱动芯片,或者h桥电路,电...