可实现功能:1 可控制左右旋转2 可控制停止转动3 有测速功能,即时显示在液晶上4 有速度档位选择,分五个档次,但不能精确控速5 档位显示在液晶上用到的知识:1 用外部中断检测电机送来的下降沿,在一定时间里统计脉冲个数,进行算出转速。
2 通过改变占空比可改变电机速度,占空比的改变可以通过改变定时器的重装初值来实现。
3 要想精确控制速度,还需要用自动控制理论里的PID算法,但参数难以选定,故在此设计中没有涉及!#include<reg52.h>#define uchar unsigned char#define uint unsigned intsbit PW1=P1^0 ;sbit PW2=P1^1 ; //控制电机的两个输入sbit accelerate=P0^2 ; //调速按键sbit stop=P0^3 ; //停止按键sbit left=P0^4 ; //左转按键sbit right=P0^5 ; //右转按键sbit detect=P3^2; //检测脉冲sbit lcdrs=P0^0;sbit lcden=P0^1;#define Da P2uint temp; //保存检测到的电平数据以便比较uint count; //用于计数uint aa,bb; //用于计数uint speed; //用来计算转速uint a=25000;uint t0=25000,t1=25000; //初始时占空比为50%uchar flag=1; //此标志用于选择不同的装载初值uchar dflag; //左右转标志uchar sflag=1; //用来标志速度档位#define right_turn PW1=0;PW2=1 //顺时针转动#define left_turn PW1=1;PW2=0 //逆向转动#define end_turn PW1=1;PW2=1 //停转void keyscan(); //键盘扫描void delay(uchar z);void time_init(); //定时器的初始化void write_(uchar ); //液晶写指令void write_data(uchar date); //液晶写数据void lcd_init(); //液晶初始化void display(uint rate); //显赫速度void int0_init(); //定时器0初始化void keyscan(); //键盘扫描程序void judge_derection();void main(){time_init(); //定时器的初始化lcd_init(); //液晶初始化int0_init(); //定时器0初始化while(1){}}void time_init(){TMOD=0x11; //两个定时器都设定为工作方式1 十六位定时计数器 EA=1; //开启总中断TH0=(65536-50000)/256;TL0=(65536-50000)%256;ET0=1;TR0=1;TH1=(65536-a)/256;TL1=(65536-a)%256;ET1=1;TR1=0;}void int0_init(){EX0=1;//外部中断源可以申请中断IT0=1;//外部中断源下降沿触发}void timer0() interrupt 1 using 0{TH0=(65536-50000)/256;TL0=(65536-50000)%256; //装载初值keyscan(); //键盘扫描程序aa++;if(aa==5){aa=0;temp=count*0.5*60*2*2*100/24; //计算转速,每分转多少圈count=0; //重新开始计数脉冲数display(temp); //把计算得的结果显示出来}}void timer1() interrupt 3 using 0{if(flag){flag=0;end_turn;a=t0; //t0的大小决定着低电平延续时间TH1=(65536-a)/256;TL1=(65536-a)%256; //重装载初值}else{flag=1; //这个标志起到交替输出高低电平的作用if(dflag==0){right_turn; //右转}else{left_turn; //左转}a=t1; //t1的大小决定着高电平延续时间TH1=(65536-a)/256;TL1=(65536-a)%256; //重装载初值}}/*******外部中断*******************/void service_int0() interrupt 0{count++; //来一个下降沿沿就计一个脉冲数}/*******显示函数***********/void display(uint rate){uchar wan,qian, bai,shi,ge;wan=rate/10000;qian=rate/1000%10;bai=rate/100%10;shi=rate/10%10;ge=rate%10;write_(0x80);write_data('0'+wan);write_data('0'+qian);write_data('0'+bai);write_data('.');write_data('0'+shi);write_data('0'+ge);}/******延时函数********/void delay(uint z){uint x,y;for(x=z;x>0;x--)for(y=110;y>0;y--) ;}/************写指令************/void write_(uchar ){lcdrs=0;Da=;delay(1);lcden=1;delay(1);lcden=0;}/************写数据**********/void write_data(uchar date){lcdrs=1;Da=date;delay(1);lcden=1;delay(1);lcden=0;}/************液晶初始化**********/void lcd_init(){lcden=0;write_(0x38) ; //初始化write_(0x0c) ; //打开光标 0x0c不显示光标 0x0e光标不闪,0x0f光标闪write_(0x01) ; //清显示write_(0x80+0x40);write_data('0');write_data(' ');write_data('G');write_data('e');write_data('a');write_data('r');}/***********键盘扫描程序**********/void keyscan(){if(stop==0){TR1=0; //关闭定时器0 即可停止转动end_turn; // 停止供电write_(0x80+0x40);write_data('0');}if(left==0){TR1=1;dflag=1; //转向标志置位则左转write_(0x80+0x40);write_data('0'+sflag);}if(right==0){TR1=1;dflag=0; //转向标志复位则右转write_(0x80+0x40);write_data('0'+sflag);}if(accelerate==0){delay(10) ; //延时消抖if(accelerate==0){while(accelerate==0) ; //等待松手sflag++;if(sflag==2){t0=20000;t1=30000; //占空比为百分之60write_(0x80+0x40);write_data('2');}if(sflag==3){t0=15000;t1=35000; //占空比为百分之70 write_(0x80+0x40);write_data('3');}if(sflag==4){t0=10000;t1=40000; //占空比为百分之80 write_(0x80+0x40);write_data('4');}if(sflag==5){t0=5000;t1=45000; //占空比为百分之90 write_(0x80+0x40);write_data('5');}if(sflag>=6){sflag=0;t0=25000;t1=25000;write_(0x80+0x40);write_data('1');}}} }。