51单片机控制电机正反转用LCD显示电机运行方向和速度
时间:10-02
整理:3721RD
点击:
我是一个纯新手,根据网上的LCD程序和正反转程序,自己稍微弄了个程序,但是仿真时候LCD是亮了,却没有显示数据;而电机根本没有运转。求高手解答,我是一个新手,真新手。
/*直流电机的PWM速度控制程序*/
/*晶振采用11.0592M,产生pwm的频率约为91hz*/
/*LCD程序*/
#include<reg51.h>
#include <intrins.h> //内部包含延时函数 _nop_();
#include<math.h>
#define uchar unsigned char
#define uint unsigned int
#define delayNOP(); {_nop_();_nop_();_nop_();_nop_();};
uchar code FFW[8]={0xf1,0xf3,0xf2,0xf6,0xf4,0xfc,0xf8,0xf9}; //正转相序编码
uchar code REV[8]={0xf9,0xf8,0xfc,0xf4,0xf6,0xf2,0xf3,0xf1};
sbit K1 = P3^0; //运行与停止
sbit K3 = P3^2; //方向转换
sbit LCD_RS = P2^0;
sbit LCD_RW = P2^1;
sbit LCD_EN = P2^2;
bit on_off=0,on_off1=0; //运行与停止标志
bit direction=1; //方向标志
bit rate_dr=1; //速率标志
uchar code cdis1[ ] = {" STEPPING MOTOR "};
uchar code cdis2[ ] = {"CONTROL PROCESS"};
uchar code cdis3[ ] = {" STOP "};
uchar code cdis4[ ] = {"NO: RATE: TEXT: "};
uchar code cdis5[ ] = {" RUNNING "};
uchar m,v=0,q=0,q1;
uchar data_temp,data_temp1,data_temp2;
sbit en1=P2^7; /*L298 Enable A*/
sbit en2=P3^0; /*L298 Enable B*/
sbit s1=P2^3; /*L298 input 1*/
sbit s2=P2^4; /*l298 input 2*/
sbit s3=P2^5; /*L298 Input 3*/
sbit s4=P2^6; /*L298 Inout 4*/
uchar t=0; /*中断计数器*/
uchar m1=0; /*电机1速度值*/
uchar m2=0; /*电机2速度值*/
uchar tmp1,tmp2; /*电机当前速度值*/
/*电机控制函数index-电机号(1,2);speed-电机速度(-100-100)*/
void motor_1(uchar index,char speed)
{
if(speed>=-100&&speed<=100)
{
if(index==1); /*电机1的处理*/
{
m1=abs(speed); /*取速度值的绝对值*/
if(speed<0) /*速度值为负则反转*/
{
s1=0;
s2=1;
}
else /*不为负数则正转*/
{
s1=1;
s2=0;
}
}
}
}
void motor_2(uchar index,char speed)
{
if(speed>=-100&&speed<=100)
{
if(index==2) /*电机2的处理*/
{
m2=abs(speed); /*电机2的速度控制*/
if(speed<0) /*电机2的方向控制*/
{
s3=0;
s4=1;
}
else
{
s3=1;
s4=0;
}
}
}
}
void motor_12(uchar index,char speed)
{
if(speed>=-100&&speed<=100)
{
if(index==1); /*电机1的处理*/
{
m1=abs(speed); /*取速度值的绝对值*/
if(speed<0) /*速度值为负则反转*/
{
s1=0;
s2=1;
}
else /*不为负数则正转*/
{
s1=1;
s2=0;
}
}
if(index==2) /*电机2的处理*/
{
m2=abs(speed); /*电机2的速度控制*/
if(speed<0) /*电机2的方向控制*/
{
s3=0;
s4=1;
}
else
{
s3=1;
s4=0;
}
}
}
}
void delayA(uint j)/*简易延时函数*/
{
for(j;j>0;j--);
}
/********************************************************/
/*
/* 延时t毫秒
/* 11.0592MHz时钟,延时约1ms
/*
/********************************************************/
void delay(uint t) //tms
{
uchar k;
while(t--)
{
for(k=0; k<125; k++)
{ }
}
}
/********************************************************/
void delayB(uchar x) //x*0.14MS
{
uchar i;
while(x--)
{
for (i=0; i<13; i++)
{ }
}
}
/********************************************************/
/********************************************************/
/*
/*检查LCD忙状态
/*lcd_busy为1时,忙,等待。为0时,闲,可写指令与数据。
/*
/********************************************************/
bit lcd_busy()
{
bit result;
LCD_RS = 0;
LCD_RW = 1;
LCD_EN = 1;
delayNOP();
result = (bit)(P0&0x80);
LCD_EN = 0;
return(result);
}
/********************************************************/
/*
/*写指令数据到LCD
/*RS=L,RW=L,E=高脉冲,D0-D7=指令码。
/*
/********************************************************/
void lcd_wcmd(uchar cmd)
{
while(lcd_busy());
LCD_RS = 0;
LCD_RW = 0;
LCD_EN = 0;
_nop_();
_nop_();
P0 = cmd;
delayNOP();
LCD_EN = 1;
delayNOP();
LCD_EN = 0;
}
/********************************************************/
/*
/*写显示数据到LCD
/*RS=H,RW=L,E=高脉冲,D0-D7=数据。
/*
/********************************************************/
void lcd_wdat(uchar dat)
{
while(lcd_busy());
LCD_RS = 1;
LCD_RW = 0;
LCD_EN = 0;
P0 = dat;
delayNOP();
LCD_EN = 1;
delayNOP();
LCD_EN = 0;
}
/********************************************************/
/*
/* LCD初始化设定
/*
/********************************************************/
void lcd_init()
{
delay(30);
lcd_wcmd(0x38); //16*2显示,5*7点阵,8位数据
delay(5);
lcd_wcmd(0x38);
delay(5);
lcd_wcmd(0x38);
delay(5);
lcd_wcmd(0x0c); //显示开,关光标
delay(5);
lcd_wcmd(0x06); //写入新数据后光标右移
delay(5);
lcd_wcmd(0x01); //清除LCD的显示内容
delay(5);
}
/********************************************************/
/*
/* 设定显示位置
/*
/********************************************************/
void lcd_pos(uchar pos)
{
lcd_wcmd(pos | 0x80); //数据指针=80+地址变量
}
/********************************************************/
/*
/* LCD1602初始显示子程序
/*
/********************************************************/
void LCD_init_DIS()
{
delay(10); //延时
lcd_init(); //初始化LCD
lcd_pos(0); //设置显示位置为第一行的第1个字符
m = 0;
while(cdis1[m] != '\0')
{ //显示字符
lcd_wdat(cdis1[m]);
m++;
}
lcd_pos(0x40); //设置显示位置为第二行第1个字符
m = 0;
while(cdis2[m] != '\0')
{
lcd_wdat(cdis2[m]); //显示字符
m++;
}
delay(3000); //延时
lcd_pos(0); //设置显示位置为第一行的第1个字符
m = 0;
while(cdis3[m] != '\0')
{ //显示字符
lcd_wdat(cdis3[m]);
m++;
}
lcd_pos(0x40); //设置显示位置为第二行第1个字符
m = 0;
while(cdis4[m] != '\0')
{
lcd_wdat(cdis4[m]); //显示字符
m++;
}
for(m=0;m<2;m++)
{
lcd_pos(0x0c+m); //显示方向符号
lcd_wdat(0x3e);
}
}
/********************************************************/
/*
/*数据转换子程序
/*
/********************************************************/
void data_conv()
{
data_temp1=data_temp/10; //高位
if(data_temp1==0)
{data_temp1=0x20;} //高位为0不显示
else
{data_temp1=data_temp1+0x30;}
data_temp2=data_temp%10; //低位
data_temp2=data_temp2+0x30;
}
/********************************************************/
/*
/*数据显示子程序
/*
/********************************************************/
void data_dis()
{
data_temp = tmp1; //显示速率
data_conv();
lcd_pos(0x4d);
lcd_wdat(data_temp1);
lcd_pos(0x4e);
lcd_wdat(data_temp2);
}
/********************************************************
/*
/* 显示运行方向符号
/*
/********************************************************/
void motor_DR()
{
if(direction==1) //正转方向标志
{ for(m=0;m<2;m++)
{
lcd_pos(0x0c+m); //显示方向符号
lcd_wdat(0x3e);
}
}
else
{ for(m=0;m<2;m++) //反转方向标志
{
lcd_pos(0x0c+m); //显示方向符号
lcd_wdat(0x3c);
}
}
}
/********************************************************
/*
/* 显示运行状态
/*
/********************************************************/
void motor_RUN()
{
if(on_off==1)
{ TR0=1;
lcd_pos(0); //设置显示位置为第一行的第1个字符
m = 0;
while(cdis5[m] != '\0')
{ lcd_wdat(cdis5[m]); //RUNNING
m++; }
motor_DR(); //
}
else
{ TR0=0; P1 =0x0f;
lcd_pos(0); //设置显示位置为第一行的第1个字符
m = 0;
while(cdis3[m] != '\0')
{ lcd_wdat(cdis3[m]); //STOP
m++; }
motor_DR(); //
}
}
void main()
{
char i;
LCD_init_DIS();
TMOD=0x02; /*设定T0的工作模式为2*/
TH0=0x9B; /*装入定时器的初值*/
TL0=0x9B;
EA=1; /*开中断*/
ET0=1; /*定时器0允许中断*/
TR0=1; /*启动定时器0*/
P1=0x0f;
while(1)
{
if(K1==0)
{
delay(20);
if(K1==0)
{
while(K1==0); //等待键释放
on_off=~on_off;
motor_RUN();
}
} //K1 end
/********************************************************/
if(K3==0)
{
delay(20);
if(K3==0)
{
direction=~direction;
motor_DR();
}
delay(100);
}//K3 end
}
while(1) /*电机实际控制演示*/
{
for(i=0;i<=100;i++)/*正转加速*/
{
motor_12(1,i);
motor_12(2,i);
delayA(5000);
}
for(i=100;i>0;i--)/*正转减速*/
{
motor_12(1,i);
motor_12(2,i);
delayA(5000);
}
for(i=0;i<=100;i++)/*反转加速*/
{
motor_12(1,-i);
motor_12(2,-i);
delayA(5000);
}
for(i=100;i>0;i--)/*反转减速*/
{
motor_12(1,-i);
motor_12(2,-i);
delayA(5000);
}
}
}
void timer0() interrupt 1/*T0中断服务程序*/
{
if(t==0) /*1个PWM周期完成后才回接受新数值*/
{
tmp1=m1;
tmp2=m2;
}
if(t<tmp1) en1=1;else en1=0; /*产生电机1的PWM信号*/
if(t<tmp2) en2=1;else en2=0; /*产生电机2的PWM信号*/
t++;
if(t>=100) t=0; /*1个PWM信号由100此中断产生*/
}
/*直流电机的PWM速度控制程序*/
/*晶振采用11.0592M,产生pwm的频率约为91hz*/
/*LCD程序*/
#include<reg51.h>
#include <intrins.h> //内部包含延时函数 _nop_();
#include<math.h>
#define uchar unsigned char
#define uint unsigned int
#define delayNOP(); {_nop_();_nop_();_nop_();_nop_();};
uchar code FFW[8]={0xf1,0xf3,0xf2,0xf6,0xf4,0xfc,0xf8,0xf9}; //正转相序编码
uchar code REV[8]={0xf9,0xf8,0xfc,0xf4,0xf6,0xf2,0xf3,0xf1};
sbit K1 = P3^0; //运行与停止
sbit K3 = P3^2; //方向转换
sbit LCD_RS = P2^0;
sbit LCD_RW = P2^1;
sbit LCD_EN = P2^2;
bit on_off=0,on_off1=0; //运行与停止标志
bit direction=1; //方向标志
bit rate_dr=1; //速率标志
uchar code cdis1[ ] = {" STEPPING MOTOR "};
uchar code cdis2[ ] = {"CONTROL PROCESS"};
uchar code cdis3[ ] = {" STOP "};
uchar code cdis4[ ] = {"NO: RATE: TEXT: "};
uchar code cdis5[ ] = {" RUNNING "};
uchar m,v=0,q=0,q1;
uchar data_temp,data_temp1,data_temp2;
sbit en1=P2^7; /*L298 Enable A*/
sbit en2=P3^0; /*L298 Enable B*/
sbit s1=P2^3; /*L298 input 1*/
sbit s2=P2^4; /*l298 input 2*/
sbit s3=P2^5; /*L298 Input 3*/
sbit s4=P2^6; /*L298 Inout 4*/
uchar t=0; /*中断计数器*/
uchar m1=0; /*电机1速度值*/
uchar m2=0; /*电机2速度值*/
uchar tmp1,tmp2; /*电机当前速度值*/
/*电机控制函数index-电机号(1,2);speed-电机速度(-100-100)*/
void motor_1(uchar index,char speed)
{
if(speed>=-100&&speed<=100)
{
if(index==1); /*电机1的处理*/
{
m1=abs(speed); /*取速度值的绝对值*/
if(speed<0) /*速度值为负则反转*/
{
s1=0;
s2=1;
}
else /*不为负数则正转*/
{
s1=1;
s2=0;
}
}
}
}
void motor_2(uchar index,char speed)
{
if(speed>=-100&&speed<=100)
{
if(index==2) /*电机2的处理*/
{
m2=abs(speed); /*电机2的速度控制*/
if(speed<0) /*电机2的方向控制*/
{
s3=0;
s4=1;
}
else
{
s3=1;
s4=0;
}
}
}
}
void motor_12(uchar index,char speed)
{
if(speed>=-100&&speed<=100)
{
if(index==1); /*电机1的处理*/
{
m1=abs(speed); /*取速度值的绝对值*/
if(speed<0) /*速度值为负则反转*/
{
s1=0;
s2=1;
}
else /*不为负数则正转*/
{
s1=1;
s2=0;
}
}
if(index==2) /*电机2的处理*/
{
m2=abs(speed); /*电机2的速度控制*/
if(speed<0) /*电机2的方向控制*/
{
s3=0;
s4=1;
}
else
{
s3=1;
s4=0;
}
}
}
}
void delayA(uint j)/*简易延时函数*/
{
for(j;j>0;j--);
}
/********************************************************/
/*
/* 延时t毫秒
/* 11.0592MHz时钟,延时约1ms
/*
/********************************************************/
void delay(uint t) //tms
{
uchar k;
while(t--)
{
for(k=0; k<125; k++)
{ }
}
}
/********************************************************/
void delayB(uchar x) //x*0.14MS
{
uchar i;
while(x--)
{
for (i=0; i<13; i++)
{ }
}
}
/********************************************************/
/********************************************************/
/*
/*检查LCD忙状态
/*lcd_busy为1时,忙,等待。为0时,闲,可写指令与数据。
/*
/********************************************************/
bit lcd_busy()
{
bit result;
LCD_RS = 0;
LCD_RW = 1;
LCD_EN = 1;
delayNOP();
result = (bit)(P0&0x80);
LCD_EN = 0;
return(result);
}
/********************************************************/
/*
/*写指令数据到LCD
/*RS=L,RW=L,E=高脉冲,D0-D7=指令码。
/*
/********************************************************/
void lcd_wcmd(uchar cmd)
{
while(lcd_busy());
LCD_RS = 0;
LCD_RW = 0;
LCD_EN = 0;
_nop_();
_nop_();
P0 = cmd;
delayNOP();
LCD_EN = 1;
delayNOP();
LCD_EN = 0;
}
/********************************************************/
/*
/*写显示数据到LCD
/*RS=H,RW=L,E=高脉冲,D0-D7=数据。
/*
/********************************************************/
void lcd_wdat(uchar dat)
{
while(lcd_busy());
LCD_RS = 1;
LCD_RW = 0;
LCD_EN = 0;
P0 = dat;
delayNOP();
LCD_EN = 1;
delayNOP();
LCD_EN = 0;
}
/********************************************************/
/*
/* LCD初始化设定
/*
/********************************************************/
void lcd_init()
{
delay(30);
lcd_wcmd(0x38); //16*2显示,5*7点阵,8位数据
delay(5);
lcd_wcmd(0x38);
delay(5);
lcd_wcmd(0x38);
delay(5);
lcd_wcmd(0x0c); //显示开,关光标
delay(5);
lcd_wcmd(0x06); //写入新数据后光标右移
delay(5);
lcd_wcmd(0x01); //清除LCD的显示内容
delay(5);
}
/********************************************************/
/*
/* 设定显示位置
/*
/********************************************************/
void lcd_pos(uchar pos)
{
lcd_wcmd(pos | 0x80); //数据指针=80+地址变量
}
/********************************************************/
/*
/* LCD1602初始显示子程序
/*
/********************************************************/
void LCD_init_DIS()
{
delay(10); //延时
lcd_init(); //初始化LCD
lcd_pos(0); //设置显示位置为第一行的第1个字符
m = 0;
while(cdis1[m] != '\0')
{ //显示字符
lcd_wdat(cdis1[m]);
m++;
}
lcd_pos(0x40); //设置显示位置为第二行第1个字符
m = 0;
while(cdis2[m] != '\0')
{
lcd_wdat(cdis2[m]); //显示字符
m++;
}
delay(3000); //延时
lcd_pos(0); //设置显示位置为第一行的第1个字符
m = 0;
while(cdis3[m] != '\0')
{ //显示字符
lcd_wdat(cdis3[m]);
m++;
}
lcd_pos(0x40); //设置显示位置为第二行第1个字符
m = 0;
while(cdis4[m] != '\0')
{
lcd_wdat(cdis4[m]); //显示字符
m++;
}
for(m=0;m<2;m++)
{
lcd_pos(0x0c+m); //显示方向符号
lcd_wdat(0x3e);
}
}
/********************************************************/
/*
/*数据转换子程序
/*
/********************************************************/
void data_conv()
{
data_temp1=data_temp/10; //高位
if(data_temp1==0)
{data_temp1=0x20;} //高位为0不显示
else
{data_temp1=data_temp1+0x30;}
data_temp2=data_temp%10; //低位
data_temp2=data_temp2+0x30;
}
/********************************************************/
/*
/*数据显示子程序
/*
/********************************************************/
void data_dis()
{
data_temp = tmp1; //显示速率
data_conv();
lcd_pos(0x4d);
lcd_wdat(data_temp1);
lcd_pos(0x4e);
lcd_wdat(data_temp2);
}
/********************************************************
/*
/* 显示运行方向符号
/*
/********************************************************/
void motor_DR()
{
if(direction==1) //正转方向标志
{ for(m=0;m<2;m++)
{
lcd_pos(0x0c+m); //显示方向符号
lcd_wdat(0x3e);
}
}
else
{ for(m=0;m<2;m++) //反转方向标志
{
lcd_pos(0x0c+m); //显示方向符号
lcd_wdat(0x3c);
}
}
}
/********************************************************
/*
/* 显示运行状态
/*
/********************************************************/
void motor_RUN()
{
if(on_off==1)
{ TR0=1;
lcd_pos(0); //设置显示位置为第一行的第1个字符
m = 0;
while(cdis5[m] != '\0')
{ lcd_wdat(cdis5[m]); //RUNNING
m++; }
motor_DR(); //
}
else
{ TR0=0; P1 =0x0f;
lcd_pos(0); //设置显示位置为第一行的第1个字符
m = 0;
while(cdis3[m] != '\0')
{ lcd_wdat(cdis3[m]); //STOP
m++; }
motor_DR(); //
}
}
void main()
{
char i;
LCD_init_DIS();
TMOD=0x02; /*设定T0的工作模式为2*/
TH0=0x9B; /*装入定时器的初值*/
TL0=0x9B;
EA=1; /*开中断*/
ET0=1; /*定时器0允许中断*/
TR0=1; /*启动定时器0*/
P1=0x0f;
while(1)
{
if(K1==0)
{
delay(20);
if(K1==0)
{
while(K1==0); //等待键释放
on_off=~on_off;
motor_RUN();
}
} //K1 end
/********************************************************/
if(K3==0)
{
delay(20);
if(K3==0)
{
direction=~direction;
motor_DR();
}
delay(100);
}//K3 end
}
while(1) /*电机实际控制演示*/
{
for(i=0;i<=100;i++)/*正转加速*/
{
motor_12(1,i);
motor_12(2,i);
delayA(5000);
}
for(i=100;i>0;i--)/*正转减速*/
{
motor_12(1,i);
motor_12(2,i);
delayA(5000);
}
for(i=0;i<=100;i++)/*反转加速*/
{
motor_12(1,-i);
motor_12(2,-i);
delayA(5000);
}
for(i=100;i>0;i--)/*反转减速*/
{
motor_12(1,-i);
motor_12(2,-i);
delayA(5000);
}
}
}
void timer0() interrupt 1/*T0中断服务程序*/
{
if(t==0) /*1个PWM周期完成后才回接受新数值*/
{
tmp1=m1;
tmp2=m2;
}
if(t<tmp1) en1=1;else en1=0; /*产生电机1的PWM信号*/
if(t<tmp2) en2=1;else en2=0; /*产生电机2的PWM信号*/
t++;
if(t>=100) t=0; /*1个PWM信号由100此中断产生*/
}
已退回5积分