资源描述
//MCU:AT89S51
//晶振:12M
#include "regX52.H"
#include "math.h"
#include "intrins.h"
#define LCDIO P0 //定义P0口与LCD1602旳数据口相接
#define ON 1
#define OFF 0
sbit LCD_RS=P2^6;
sbit LCD_RW=P2^5;
sbit LCD_EN=P2^4;
sbit LCD_BUSY=LCDIO^7;
sbit SW4=P2^0; // 速度设置加
sbit SW3=P2^1; // 速度设置减
sbit SW2=P2^2; // 停
sbit SW1=P2^3; // 反转
sbit IN2=P3^4; // 红色旳线
sbit PWM=P3^5; // 黄色旳线
sbit IN1=P3^6; // 紫色旳线
int display;
int flag;
int time;
int a;
int s=25;
unsigned long int p;
unsigned long int xiao;
unsigned long int h;
unsigned long int v;
unsigned char dispbuff[4]; //寄存各位数据
/*******1ms延时子程序***********/
void delay_nms(unsigned int n)
{
unsigned int i;
unsigned char j;
for(i=0;i<n;i++)
for(j=0;j<120;j++)
; //空操作
}
/*******1ms延时子程序***********/
/*******0.1ms延时子程序***********/
void control_speed(unsigned int n)
{
unsigned char j;
for(j=0;j<n;j++)
; //空操作
}
/*******0.1ms延时子程序***********/
#define uchar unsigned char
#define uint unsigned int
//LCD驱动
void LCD_check_busy(void) //检测LCD状态,看它是不是还在忙呢
{
do
{
LCD_EN=0;
LCD_RS=0;
LCD_RW=1;
LCDIO=0xff;
LCD_EN=1;
}
while(LCD_BUSY==1);
LCD_EN=0;
}
/************LCD1602写命令*******************************/
void LCD_send_command(uchar command,busy1)
{
if(busy1)
LCD_check_busy();
LCD_RS=0;
LCD_RW=0;
LCD_EN=1;
LCDIO=command;
LCD_EN=0;
}
/*****************LCD1602写数据**************************/
void LCD_send_data(uchar dat)
{
LCD_check_busy();
LCD_RS=1;
LCD_RW=0;
LCD_EN=1;
LCDIO=dat;
LCD_EN=0;
}
void LCD_write_char(uchar x,uchar y,uchar dat)
{
unsigned char address;
if (x==0)
address=0x80+y;
else
address=0xc0+y;
LCD_send_command(address,0);
LCD_send_data(dat);
}
/******************LCD1602显示字符串*********************/
void LCD_disp_string(uchar x,uchar y,uchar *Data)
{
if(x==0)
{
if(y<16)
{
LCD_send_command(0x80+y,0);
for(;y<16&&*Data!='\0';y++)
{
LCD_send_data(*(Data));
Data++;
}
if(*Data!='\0')
{
y=0;
x=1;
}
}
}
if(x==1)
{
LCD_send_command(0xc0+y,0);
for(;y<16&&*Data!='\0';y++)
{
LCD_send_data(*(Data));
Data++;
}
}
}
void LCD_init(void)
{
delay_nms(15);
LCD_send_command(0x38,0);
delay_nms(5);
LCD_send_command(0x38,0);
delay_nms(5);
LCD_send_command(0x38,0);
delay_nms(5);
LCD_send_command(0x38,1);//设置lcd1602为每个字符5×7显示
LCD_send_command(0x0f,1); //开显示,光标显示并闪烁
LCD_send_command(0x06,1);//光标移动设置,每写一种数,光标自动加一
LCD_send_command(0x01,1); //清屏
}
/**************LCD1602旳初始化完毕***************************/
/***********************初始化函数*********************/
void init()
{
IT1=1; //脉冲触发方式
EA=1; //中断总容许
EX1=1; //容许外部中断1
TMOD=0x91;
TH0=0x3c;
TL0=0xb0; //给定期器赋初值
ET0=1; //容许定期中断
TR0=1; //启动定期器
}
/******定期器,外部中断初始化******/
void main()
{
int mode;
int vs=50; //速度设置参数
int Y= 2;
int
k=0;
init();
LCD_init();
LCD_disp_string(0,0x00,"set speed:");
LCD_disp_string(1,0x00,"V=");
LCD_disp_string(1,0x05,"Hz");
while(1)
{
/***********************按键模式某些控制*********************/
if(SW4==0) //设定速度加
{ xiao++;
if(xiao>100)
{ xiao=0;
vs++;
if(vs>100)
{ vs=100; }
}
}
if(SW3==0) //设定速度减
{ xiao++;
if(xiao>100)
{ xiao=0;
vs--;
if(vs<8)
{ vs=8; }
}
}
if(SW2==0) //开关键
{ delay_nms(100);
{
if(SW2==0)
{
if(mode!=0)
mode=0;
else
mode=1;
}
}
delay_nms(150);
}
if(SW1==0) //正反转
{ delay_nms(100);
{
if(SW1==0)
{
if(mode==2)
{ mode=1; }
else
{ mode=2; }
}
}
delay_nms(150);
}
/***********************按键模式某些控制*********************/
/***********************电机运行模式选择*********************/
switch(mode)
{
case 0x00: //关闭电机
PWM = OFF;
break;
case 0x01: //正转
IN1 = 0; //p36 紫线
IN2 = 1; //p34 红线
PWM = 1; //p35 黄线 (控制速度)
control_speed(s);
PWM = 0; //p35 黄线
control_speed(100-s);
break;
case 0x02: //反转
IN1 = 1; //p36 紫线
IN2 = 0; //p34 红线
PWM = 1; //p35 黄线
control_speed(s);
PWM = 0; //p35 黄线
control_speed(100-s);
break;
default:break;
}
/***********************电机运行模式选择*********************/
/***********************速度计算显示*********************/
if(display==1)
{
display=0; //一秒钟显示一次
dispbuff[3]=(v/100);
dispbuff[2]=(v/10%10); //
dispbuff[1]=(v%10); //
LCD_write_char(1,0x02,(dispbuff[3])+48); //
LCD_write_char(1,0x03,(dispbuff[2])+48);
LCD_write_char(1,0x04,(dispbuff[1])+48);
LCD_write_char(0,0x0a,(vs/100)+48);
LCD_write_char(0,0x0b,(vs/10)%10+48);
LCD_write_char(0,0x0c,(vs%10)+48);
switch(mode)
{
case 0x00: //关闭电机
LCD_disp_string(1,0x07,"----stop");
break;
case 0x01: //正转
LCD_disp_string(1,0x07,"--->work");
break;
case 0x02: //反转
LCD_disp_string(1,0x07,"<---work");
break;
default:break;
}
/***********************速度计算显示*********************/
/***********************速度自动调整(每一秒调整一次)*********************/
if(v>(vs+Y*2)) //速度过大,迅速调整
{
s=s-3;
if(s<8)
{ s=8;}
}
if((v-Y)>=vs>=(v-Y*2)) //速度过大, 慢速调整。
{
s=s-1; // delay_nms(1);
if(s<8)
{ s=8;}
}
if(vs>(v+Y*2)) //速度过大,迅速调整
{
s=s+3;
if(s>95)
{ s=95;}
}
if((vs-Y)>=v>=(vs-Y*2)) //速度过大, 慢速调整。
{
s=s+1; // delay_nms(1);
if(s>95)
{ s=95;}
}
else
s=s;
/***********************速度自动调整(每一秒调整一次)*********************/
}
}
}
/***********************频率进入端口*********************/
void inter1() interrupt 2
{
p++;
}
void timer0() interrupt 1 //定期中断入口
{
TH0=0x3c;
TL0=0xb0; // 50ms //定期器赋值
time++;
if(time>=20) //一秒
{
time=0;
v=p/2;
p=0;
xiao=0;
display=1;
}
}
展开阅读全文