基于51单片机的步进电机控制系统(串口、上位机监控、人机交互)原理图、流程图、物料清单、仿真图、源代码
基于51单片机的步进电机(串口)
步进电机控制系统
功能要求:
1、通过小键盘给定,实现步进电机启动/停止、正转/反转、加速/减速设置与控制,数码管(或液晶)显示当前步进电机状态及相关参数,简单故障诊断与报警。
2、上位机监控功能要求:通过串口或USB口实现上/下位机通信,能够显示步进电机当前状态及运行参数(数据显示或动画显示),能够从上位机控制下位机之步进电机工作。

#include "reg51.h"
#define uchar unsigned char
#define uint unsigned int
sbit rs=P2^0; //1602数据/命令选择引脚 H:数据 L:命令
sbit rw=P2^1; //1602读写引脚 H:数据寄存器 L:指令寄存器
sbit e =P2^2; //1602使能引脚 下降沿触发
sbit k1=P1^0;//按钮
sbit k2=P1^1;
sbit k3=P1^2;
sbit k4=P1^3;
sbit k5=P1^4;
sbit k6=P1^5;
sbit k7=P1^6;
sbit beep=P3^7;//蜂鸣器
sbit AA=P2^3;//步进电机
sbit BB=P2^4;
sbit CC=P2^5;
sbit DD=P2^6;
uchar hang[]="speed:00";//速度
uchar speed=45;//速度
uchar time=0,flag=0,fang=0,start=0;//电机控制
uchar sec=0;//显示定时
void delay_uint(uint i)
{
while(i--);
}
/********************************************************************
* 名称 : write_com(uchar com)
* 功能 : 1602命令函数
* 输入 : 输入的命令值
* 输出 : 无
***********************************************************************/
void write_com(uchar com)
{
e=0;
rs=0;
rw=0;
P0=com;
delay_uint(20);
e=1;
delay_uint(20);
e=0;
}
/********************************************************************
* 名称 : write_data(uchar dat)
* 功能 : 1602写数据函数
* 输入 : 需要写入1602的数据
* 输出 : 无
***********************************************************************/
void write_data(uchar dat)
{
e=0;
rs=1;
rw=0;
P0=dat;
delay_uint(20);
e=1;
delay_uint(20);
e=0;
}
/********************************************************************
* 名称 : write_string(uchar hang,uchar add,uchar *p)
* 功能 : 改变液晶中某位的值,如果要让第一行,第五个字符开始显示"ab cd ef" ,调用该函数如下
write_string(1,5,"ab cd ef;")
* 输入 : 行,列,需要输入1602的数据
* 输出 : 无
***********************************************************************/
void write_string(uchar hang,uchar add,uchar *p)
{
if(hang==1)
write_com(0x80+add);
else
write_com(0x80+0x40+add);
while(1)
{
if(*p == '\0') break;
write_data(*p);
p++;
}
}
/********************************************************************
* 名称 : init_1602()
* 功能 : 初始化1602液晶
* 输入 : 无
* 输出 : 无
***********************************************************************/
void init_1602()
{
write_com(0x38); //数据总线为8位,显示2行,5x7点阵
write_com(0x0e); //开显示,有光标,光标闪烁
write_com(0x06); //光标自动右移
delay_uint(1000); //等待设置完成
}
void com_fa(uchar *p)//发送
{
ES=0;
while(*p!='\0')
{
SBUF=*p;
while(!TI);
TI=0;
p++;
}
RI=0;
ES=1;
}
void main()
{
init_1602();
SCON=0X50; //设置为工作方式1
TMOD=0X21; //设置计数器工作方式2
TH1=0XFD; //9600
TL1=0XFD;
ES=1; //打开接收中断
EA=1; //打开总中断
TR1=1; //打开计数器
TH0=0XD8;
TL0=0XF0;
ET0=1;//打开定时器0中断允许
EA=1;//打开总中断
TR0=1;//打开定时器
while(1)
{
beep=k7;//简单故障检测
if(!k1)//启动
{
start=1;
while(!k1);
}
if(!k2)//停止
{
start=0;
while(!k2);
}
if(!k3)//正转
{
fang=1;
while(!k3);
}
if(!k4)//反转
{
fang=0;
while(!k4);
}
if(!k5)//加速
{
if(speed<49)
speed++;
hang[6]=(speed-30)/10+0x30; //速度
hang[7]=(speed-30)%10+0x30;
while(!k5);
}
if(!k6)//减速
{
if(speed>0)
speed--;
hang[6]=(speed-30)/10+0x30; //速度
hang[7]=(speed-30)%10+0x30;
while(!k6);
}
}
}
//定时器0中断
void Timer0() interrupt 1
{
if(start) //启动
{
if(time<50-speed)//速度控制
time++;
else
{
time=0;
if(fang)//反转
{
switch(flag)
{
case 0:DD=1;break;
case 1:AA=0;break;
case 2:CC=1;break;
case 3:DD=0;break;
case 4:BB=1;break;
case 5:CC=0;break;
case 6:AA=1;break;
case 7:BB=0;
}
}
else //正转
{
switch(flag)
{
case 0:BB=1;break;
case 1:AA=0;break;
case 2:CC=1;break;
case 3:BB=0;break;
case 4:DD=1;break;
case 5:CC=0;break;
case 6:AA=1;break;
case 7:DD=0;
}
}
if(flag<7)
flag++;
else
flag=0;
}
}
//显示
if(sec<100)//1s
sec++;
else
{
sec=0;
hang[6]=(speed-30)/10+0x30; //速度
hang[7]=(speed-30)%10+0x30;
write_string(1,0,hang);
com_fa(hang);//发送速度
com_fa(" \r");
if(start)
{
write_string(2,0,"run ");//启停
com_fa("run\r");
}
else
{
write_string(2,0,"stop");
com_fa("stop\r");
}
if(fang)
{
write_string(2,8,"right");//方向
com_fa("right\r");
}
else
{
write_string(2,8,"left ");
com_fa("left\r");
}
}
TH0=0XD8;
TL0=0XF0;
}
//串口
void Usart() interrupt 4
{
uchar i;
i=SBUF;//接收到的数据
RI = 0;//清除接收中断标志位
if(i=='Q')//启动
{
start=1;
}
if(i=='A')//停止
{
start=0;
}
if(i=='W')//正转
{
fang=1;
}
if(i=='S')//反转
{
fang=0;
}
if(i=='E')//加速
{
if(speed<49)
speed++;
}
if(i=='D')//减速
{
if(speed>0)
speed--;
}
}