void checkbusy() //检查忙,若忙则必须等待
{
EN=1;
RW=1;
RS=0;
LCD=0XFF;
if(BUSY);
}
void writecode(unsigned char dat) //写命令
{
checkbusy();
EN=1;
RW=0;
RS=0;
LCD=dat;
EN=1;
EN=0;
}
void writedata(unsigned char dat) //写数据
{
checkbusy();
EN=1;
RW=0;
RS=1;
LCD=dat;
EN=1;
EN=0;
}
void LCD_set(unsigned char page,unsigned char column) //设定起始行 页 列
{
column=column&0x3f; //12864最大为64列
writecode(page+0xb8); //+184
writecode(column+0x40); //+64
}
void LCD_clear() //清屏
{
unsigned char i,j;
CS2=0;
CS1=0;
for(i=0;i<8;i++)
{
for(j=0;j<64;j++)
{
LCD_set(i,j);
writedata(0);
}
}
}
void LCD_write_char(unsigned char screen,unsigned char page,unsigned char line,unsigned char *hz)
{
unsigned char i,j;
if(screen==0)
{
CS1=1;
CS2=0; //left
LCD_set(page,line);
for(i=0;i<8;i++)
writedata(hz[i]);
LCD_set(page+1,line);
for(j=0;j<8;j++)
writedata(hz[j+8]);
}
if(screen==1)
{
CS1=0; //right
CS2=1;
LCD_set(page,line);
for(i=0;i<8;i++)
writedata(hz[i]);
LCD_set(page+1,line);
for(j=0;j<8;j++)
writedata(hz[j+8]);
}
}
void LCD_write_var(unsigned char screen,unsigned char page,unsigned char line,int num) // 显示单个数字
{
unsigned char i;
if(screen==0)
{
CS1=1;
CS2=0; //left
LCD_set(page,line);
for(i=0;i<6;i++)
writedata(number[num][i]);
}
if(screen==1)
{
CS1=0; //right
CS2=1;
LCD_set(page,line);
for(i=0;i<6;i++)
writedata(number[num][i]);
}
}
void LCD_write_num(unsigned char screen,unsigned char page,unsigned char line,int dat) //显示三位数
{
unsigned char i,tab[3]={0};
tab[0]=dat/100;
tab[1]=dat%100/10;
tab[2]=dat%100%10;
for(i=0;i<3;i++)
LCD_write_var(screen,page,line+i*6,tab[i]);
}
void LCD_write_chinese(unsigned char screen,unsigned char page,unsigned char line,unsigned char *hz) //显示汉字 屏区 页 列 字库
{
unsigned char i,j;
if(screen==0)
{
CS1=1;
CS2=0; //left
LCD_set(page,line);
for(i=0;i<12;i++)
writedata(hz[i]);
LCD_set(page+1,line);
for(j=0;j<12;j++)
writedata(hz[j+12]);
}
if(screen==1)
{
CS1=0; //right
CS2=1;
LCD_set(page,line);
for(i=0;i<12;i++)
writedata(hz[i]);
LCD_set(page+1,line);
for(j=0;j<12;j++)
writedata(hz[j+12]);
}
}
void Display1(void)
{
int i;
for(i=0;i<10;i++)
delay(50);
}
void Display2(void) //汉子、字符的显示位置
{
LCD_write_chinese(0,0,0,ge);delay(10);
LCD_write_chinese(0,0,16,can);delay(10);
LCD_write_chinese(0,0,32,shu);delay(10);
LCD_write_chinese(0,0,48,xian);delay(10);
LCD_write_chinese(1,0,0,shi);delay(10);
LCD_write_chinese(1,0,16,ru);delay(10);
LCD_write_chinese(1,0,32,xia);delay(10);
LCD_write_chinese(0,2,0,she);delay(10);
LCD_write_chinese(0,2,14,ding);delay(10);
LCD_write_var(0,2,26,10);delay(10);
LCD_write_chinese(0,4,0,dang);delay(10);
LCD_write_chinese(0,4,14,qian);delay(10);
LCD_write_var(0,4,26,10);delay(10);
LCD_write_char(0,6,14,Kkp);delay(10);
LCD_write_var(0,6,26,10);delay(10);
LCD_write_char(1,2,20,Kki);delay(10);
LCD_write_var(1,2,30,10);delay(10);
LCD_write_char(1,4,20,Kkd);delay(10);
LCD_write_var(1,4,30,10);delay(10);
LCD_write_chinese(1,6,16,xu);delay(10);
LCD_write_chinese(1,6,32,ming);delay(10);
LCD_write_chinese(1,6,48,kang);delay(10);
}
void LCD_init()
{
writecode(0X3f);//显示开关关
writecode(0XC0);//修改显示起始行
writecode(0XB8);//修改页地址,x地址
writecode(0X40);//修改列地址,y地址
}
void delay(unsigned int a)
{
unsigned int i,j;
for(i=0;i
for(j=0;j<200;j++);
}
void Scankey(void) //控制器P1口对键盘扫描
{
int i,t;
P1=P1&0xf0; // 行扫描
t=P1&0xf0; //
if(t!=0xf0) //
{
KeyH=t&0xf0; //
P1=0xff; //
delay(1); //
P1&=0x0f; // 列扫描
t=P1&0x0f; //
if(t!=0x0f) //
{
KeyL=t;
Key=KeyH|KeyL;
for(i=0;i<16;i++)
{
if(table[i]==Key)
Key=i;
}
}
}
P1=0xff;
}
void delay1s(void)
{
unsigned char a,b,c;
for(c=100;c>0;c--)
for(b=150;b>0;b--)
for(a=16;a>0;a--);
}
void Keychuli(void) //按键处理
{
unsigned int t=30000;
int n1=1000;
int n2=1000;
LED0=0;
LED1=0;
LED2=0;
LED3=0; //
Key_flag=1;
Scankey();
if(Key==10) // 单击10(/)按键 设定速度
{
LED0=1; // D1灯亮,进入设置
while(!(n1==0))
{
Scankey();
if(Key==15) // 单击15(+)按键,增大设定值
{
delay1s();
while(!(n2==0))
{
Scankey();
delay(150);
if(Key==14) {n2=0;n1=0;Key=0;} // 单击14(=)按键, 确定参数
else if(Key==13) {setspeed=0;Key=0;} // 单击13(ON)按键, 参数清零
else if(Key>9) Key=0; // 加大的系数范围0-9
setspeed=setspeed+Key; //设定的速度+增加的系数
Key=0;
if(setspeed<0) setspeed=0;
if(setspeed>999) setspeed=999;
LCD_write_num(0,2,34,setspeed); //设定速度的显示位置
}
}
else if(Key==12&&setspeed!=0) // 单击12(-)按键,减小设定值
{
delay1s();
while(n2--)
{
Scankey();
delay(150);
if(Key==14) {n2=0;n1=0;Key=0;} // 单击14(=)按键, 确定参数
else if(Key==13) {setspeed=0;Key=0;} // 单击13(ON)按键, 参数清零
else if(Key>9) Key=0; // 减小的系数范围0-9
setspeed=setspeed-Key; //设定的速度-增加的系数
Key=0;
if(setspeed<0) setspeed=0;
if(setspeed>999) setspeed=999;
LCD_write_num(0,2,34,setspeed); //设定速度的显示位置
}
}
LCD_write_num(0,2,34,setspeed); //设定速度的显示位置
}
}
else if(Key==11) //单击11(*)按键,设置PID
{
delay(200); //延时
LED1=1;
while(t--) { Scankey();}
LED1=0;
delay(200);
if(Key!=11) //单击11(*)按键,设置P
{
LED1=1; //D2灯亮,进入P设置
while(!(n1==0))
{
Scankey();
if(Key==15) // 单击15(+)按键,增大设定值
{
delay1s();
while(!(n2==0))
{
Scankey();
delay(150);
if(Key==14) {n2=0;n1=0;Key=0;} // 单击14(=)按键, 确定参数
else if(Key==13) {KP=0;Key=0;} // 单击13(ON)按键, 参数清零
else if(Key>9) Key=0;
KP=KP+Key;
Key=0;
if(KP<0) KP=0;
if(KP>999) KP=999;
LCD_write_num(0,6,34,KP);
}
}
else if(Key==12&&KP!=0) // -
{
delay1s();
while(n2--)
{
Scankey();
delay(150);
if(Key==14) {n2=0;n1=0;Key=0;}
else if(Key==13) {KP=0;Key=0;} //参数清零
else if(Key>9) Key=0;
KP=KP-Key;
Key=0;
if(KP<0) KP=0;
if(KP>999) KP=999;
LCD_write_num(0,6,34,KP);
}
}
LCD_write_num(0,6,34,KP);
}
}
else if(Key==11)
{
delay(200);
LED2=1;
while(t--) { Scankey();}
LED2=0;
Scankey();
delay(200);
if(Key!=11) //单击11(*)按键,设置I
{
LED2=1; //D3灯亮时,进入I设置
while(!(n1==0))
{
Scankey();
if(Key==15) // +
{
delay1s();
while(!(n2==0))
{
Scankey();
delay(150);
if(Key==14) {n2=0;n1=0;Key=0;}
else if(Key==13) {KI=0;Key=0;} //参数清零
else if(Key>9) Key=0;
KI=KI+Key;
Key=0;
if(KI<0) KI=0;
if(KI>999) KI=999;
LCD_write_num(1,2,38,KI);
}
}
else if(Key==12&&KI!=0) // -
{
delay1s();
while(n2--)
{
Scankey();
delay(150);
if(Key==14) {n2=0;n1=0;Key=0;}
else if(Key==13) {KI=0;Key=0;} //参数清零
else if(Key>9) Key=0;
KI=KI-Key;
Key=0;
if(KI<0) KI=0;
if(KI>999) KI=999;
LCD_write_num(1,2,38,KI);
}
}
LCD_write_num(1,2,38,KI);
}
}
else if(Key==11) //单击11(*)按键,设置D
{
LED3=1; //D4灯亮时,进入D设置
while(!(n1==0))
{
Scankey();
if(Key==15) // +
{
delay1s();
while(!(n2==0))
{
Scankey();
delay(150);
if(Key==14) {n2=0;n1=0;Key=0;}
else if(Key==13) {KD=0;Key=0;} //参数清零
else if(Key>9) Key=0;
KD=KD+Key;
Key=0;
if(KD<0) KD=0;
if(KD>999) KD=999;
LCD_write_num(1,4,38,KD);
}
}
else if(Key==12&&KD!=0) // -
{
delay1s();
while(n2--)
{
Scankey();
delay(150);
if(Key==14) {n2=0;n1=0;Key=0;}
else if(Key==13) {KD=0;Key=0;} //参数清零
else if(Key>9) Key=0;
KD=KD-Key;
Key=0;
if(KD<0) KD=0;
if(KD>999) KD=999;
LCD_write_num(1,4,38,KD);
}
}
LCD_write_num(1,4,38,KD); //D的显示位置
}
}
}
}
}
void PWMset(int pwm) //PWM设置
{
if(pwm>=0){DIR=0;PWML=pwm;}
if(pwm<0){DIR=1;PWML=10000+pwm;}
}
/********电机PID控制**********/
void Motor_control(void)
{
int PID=0;
int P=0;
int I=0;
int D=0;
int out=0;
Now_speed[2] = Now_speed[1];
Now_speed[1] = Now_speed[0];
Now_speed[0] = setspeed-speed;
P = KP*(Now_speed[0]-Now_speed[1]); //PID计算
I = KI* Now_speed[0];
D = KD*(Now_speed[0]-2*Now_speed[1]+Now_speed[2]);
PID = P+I+D;
out=last_out+PID;
if(out>out_max) out=out_max; //输出值限幅
if(out
PWMset(out);
last_out=out; //输出给寄存器,改变PWM占空比
}
/**********计数器0初始化**********/
void timer0_init(void)
{
highh=(unsigned char)((16384-high)/256+192);
highl=(unsigned char)((16384-high)%256);
lowh=(unsigned char)(high/256+200);
lowl=(unsigned char)(high%256);
TMOD=0x01;
TH0=highh;
TL0=highl;
IT0=1;
EX0=1;
TR0=1;
ET0=1;
EA=1;
}
void Getspeed(void) interrupt 0 //外部中断脉冲计数
{
num++;
IE0=0;
}
void Timer(void) interrupt 1
{
if(flag==0)
{
TH0=(unsigned char)((16384-PWML)/256+192);;
TL0=(unsigned char)((16384-PWML)%256);;
PWM=1;
flag=1; //
}
else
{
TH0=(unsigned char)(PWML/256+200);
TL0=(unsigned char)(PWML%256);;
PWM=0;
flag=0; //
}
if(j==20)
{
speed=num;
if(Key_flag==0)
Motor_control();
num=0;
j=0;
}
j++;
TF0=0;
}
void main(void)
{
int t=1;
LCD_init();
timer0_init();
LCD_clear();
Display1();
delay(200);
PWM=1;
DIR=0;
LCD_clear();
while(1)
{
if(t==1)
{
Display2();
t=0;
}
Keychuli();
Key_flag=0;
/*****及时更新数据显示***/
LCD_write_num(0,2,34,setspeed);
LCD_write_num(0,4,34,speed);
LCD_write_num(0,6,34,KP);
LCD_write_num(1,2,38,KI);
LCD_write_num(1,4,38,KD);
}
}