1.设计目的
设计并制作一个测量模拟小车(如模拟自行车、摩托车等)的行驶速度及距离的装置,且能分别显示其行驶速度和行驶距离值。
2.方案简介
硬件:
主控:stc89c52rc最小系统板
测速模块:槽式光电测速传感器,20栅格编码盘
显示:LCD12864
输入:4*4键盘
电机:5v直流电机
电机驱动:L298N
报警模块:放大电路、蜂鸣器、发光二极管
电源:单片机、LCD、传感器供电由最小系统版供电;
电机驱动由3节3.7v锂电池供电(电机驱动要和单片机共地)
因为都是用的模块,除了信号放大电路,其他都是杜邦线连接单片机与各个模块。
软件:
大致思路是定时器T0输出PWM波改变电机转速,模拟小车转动。外部中断INT0记脉冲(下降沿)。测速方法为M法。有能力的可以尝试改为M/T法,
单片机的定时器TI已经特意留出来了,具体程序见附件。
单片机源程序如下:
- #include <reg52.h>
- #include <12864.c>
- #define T 500 //PWM波 周期50us
- typedef unsigned int u32;
- typedef unsigned short u16;
- typedef unsigned char u8 ;
- uchar key=0; //键值
- u8 speed_high=5; //最高速度设置
- u8 actual_speed=0; //实际速度
- u8 temp=0; //按键扫描中间值
- uchar key_flag=0;//按键标志
- unsigned int num_flag=0; // 按键次数标志
- unsigned char flag_h=0;
- unsigned char us500 = 0;//500us定时次数计数器
- unsigned char ms100_flag=0; //100ms定时到标志
- unsigned char s1_flag=0; //500ms标志
- unsigned char Time1L=0,Time1H=0,Time0L=0,Time0H=0;//PWM波定时器占空比高,低电平时间变量
- unsigned char maichong_count=0; //电机转数脉冲计数器
- char NextState=1; //定时器高,低电平转换标志
- double CurrentWaves = 0;
- double distance=0;
- u16 distant=0;
- u16 PWM_a=300;//占空比初值
- sbit IN1=P2^6;
- sbit IN2=P2^7;
- sbit PWM=P2^5; //PWM波输出端口
- sbit bee=P3^7;
- uchar code Code[]="123A456B789C*0#D"; //键值码
- uchar code Buff[]="0123456789"; //显示字形码
- uchar Buff1[4]={'0','0',' ','0'}; //第一行显示缓冲区
- uchar Buff2[4]={'0','0',' ','0'}; // 第二行显示缓冲区
- uchar Buff3[4]={'0','0',' ','0'}; // 第三行显示缓冲区
- uchar Buff4[4]={'0','0',' ','0'}; // 第四行显示缓冲区
- void keydown(void);
- void keyscan(void);
- void keyjudge(void);
- void disp(void);
- void a_count(void);
- void rnu(void);
- void stop(void);
- /**********************************************************/
- //延时一毫秒子程序
- void mDelay(uint Delay)
- { uint i;
- for(;Delay > 0;Delay--)
- for(i = 0;i < 110;i++);
- }
- /**********************************************************/
- //定时计数器0初始化
- void Init_T0()
- {
- TMOD=0x01; //定时器0模式设置
- Time1H=(65536-PWM_a)/256; //定时器0初值1
- Time1L=(65536-PWM_a)%256; // 定时器0初值1
- Time0H=(65536+PWM_a-T)/256; // 定时器0初值2
- Time0L=(65536+PWM_a-T)%256;// 定时器0初值2
- TH0=Time1H;
- TL0=Time1L;
- ET0=1;
- TR0=1;
- EX0=1; //外中断0允许
- IT0=1; //外部中断边沿触发方式
- NextState=1;
- PWM=1;
- }
- /**********************************************************/
- //电机启动
- void run(void)
- {
- IN1=1;
- IN2=0;
- EA=0;
- Init_T0();
- EA=1;
- IN1=1;
- IN2=0;
- }
- /**********************************************************/
- //电机停止
- void stop()
- {
- IN1=0;
- IN2=0;
- PWM=0;
- ET0=0;
- TR0=0;
- EA=0;
- }
- /*************************************************************/
- //判断键是否按下
- void keydown(void)
- {
- P1=0xF0;
- if(P1!=0xF0)
- {
- mDelay(20);
- keyscan();
- }
- }
- /**********************************************************/
- // 键扫描子程序
- void keyscan(void)
- {
- P1=0xF0; //行线为输入,列线为输出,并置列线输出全为0
- temp=P1; //读P1口
- temp=temp&0xF0;
- temp=~((temp>>4)|0xF0);
- if(temp==1)
- key=0;
- else if(temp==2)
- key=1;
- else if(temp==4)
- key=2;
- else if(temp==8)
- key=3;
- P1=0x0F; //列线为输入,行线为输出,并置行线输出全为0
- temp=P1; //读P1口
- temp=temp&0x0F;
- temp=~(temp|0xF0);
- if(temp==1)
- key=key+0;
- else if(temp==2)
- key=key+4;
- else if(temp==4)
- key=key+8;
- else if(temp==8)
- key=key+12;
- P1=0xF0;
- while(P1!=0XF0);
- {
- mDelay(5);
- }
- keyjudge(); //判断按键功能
- }
- /*************************************************************/
- //按键功能判断
- void keyjudge(void)
- {
- uchar a=Code[key];
- a=a-0x30;
- if(key==3)
- { Buff1[2]='>'; //按键指示A 显示
- Buff2[2]=' '; //按键指示B 取消显示
- Buff3[2]=' '; //按键指示C 取消显示
- key_flag='A';
- num_flag=0;
- }
- else if(key==7)
- {
- Buff3[2]=' '; //按键指示C 取消显示
- Buff1[2]=' '; //按键指示A取消显示
- Buff2[2]='>'; //按键指示B 显示
- key_flag='B';
- num_flag=0;
- }
- else if(key==11)
- {
-
- Buff1[2]=' '; //按键指示A 取消显示
- Buff2[2]=' '; //按键指示B 取消显示
- Buff3[2]='>'; //按键指示C 显示
- run();
- }
- else if(key==15)
- { Buff1[2]=' ';
- Buff2[2]=' ';
- Buff3[2]=' ';
- stop();
- actual_speed=0;
- CurrentWaves=0;
- disp();
- }
- else if(key==14) //#############
- {
- //PWM_a-=10;
- run();
- stop();
- distant=0;
- disp();
- }
- else if(key==12) //***********
- {
- //PWM_a+=10;
- run();
- stop();
- distance=0;
- distant=0;
- actual_speed=0;
- CurrentWaves=0;
- disp();
- }
- else
- {
- if (key_flag=='A') //输入设定转速
- {
- if(num_flag==1)
- {
- Buff1[1]=a+0x30;
- PWM_a=PWM_a+a;
- num_flag=0;
- }
- else if (num_flag==0)
- {
- Buff1[0]=a+0x30;
- PWM_a=a*10;
- num_flag++;
- }
- disp();
- }
- else if(key_flag=='B')
- {
- if(num_flag==1)
- {
- Buff2[1]=a+0x30;
- speed_high=speed_high+a;
- num_flag=0;
- }
- else if (num_flag==0)
- {
- Buff2[0]=a+0x30;
- speed_high=a*10;
- num_flag++;
- }
- disp();
- }
-
- else
- {
- num_flag=0;
- key_flag=0;
- }
- }
- }
- /*****************速度距离计算*************/
- void a_count(void)
- {
- actual_speed=CurrentWaves*3.6; //实际转速计算
-
- distant=distance/10;
- }
- /*******************显示***************************/
- void disp(void)
- {
- write_12864com(0x80+3); //12864LCD第一行显示 设置参数指示显示位置
- write_12864data(Buff1[2]);
- write_12864com(0x80+4); //12864LCD第一行显示
- write_12864data(Buff1[0]);
- write_12864com(0x80+5);
- write_12864data(Buff1[1]);
- Display_string(6,0,"per");
- write_12864com(0x90+3); //12864LCD第二行显示 设置参数指示显示位置
- write_12864data(Buff2[2]);
- write_12864com(0x90+4); //12864LCD第二行显示
- write_12864data(Buff2[0]);
- write_12864com(0x90+5);
- write_12864data(Buff2[1]);
- Display_string(6,1,"km/h");
- write_12864com(0x88+3); //12864LCD第三行显示 设置参数指示显示位置
- write_12864data(Buff3[2]);
- Buff3[0]=Buff[ actual_speed/10]; //占空比十位
- write_12864com(0x88+4); //12864LCD第三行显示
- write_12864data(Buff3[0]);
- Buff3[1]=Buff[ actual_speed%10]; // 占空比个位
- write_12864com(0x88+5);
- write_12864data(Buff3[1]);
- Display_string(6,2,"km/h");
-
- write_12864com(0x98+3); //12864LCD第四行显示 设置参数指示显示位置
- write_12864data(Buff4[0]);
- Buff4[0]=Buff[distant/100]; //占空比十位
- write_12864com(0x98+4); //12864LCD第三行显示
- write_12864data(Buff4[1]);
- Buff4[1]=Buff[(distant/10)%10]; // 占空比个位
- write_12864com(0x98+5);
- write_12864data(Buff4[2]);
- Buff4[2]=Buff[distant%10];
- Display_string(6,3,"m");
- }
- /*****************报警*************/
- void warn(void)
- {
- if(actual_speed>speed_high||actual_speed==speed_high)
- {
- bee=0;
- }
- else
- {
- bee=1;
- }
- }
- /**********************************************************/
- //T0中断服务程序
- void time0(void) interrupt 1
- {
- EX0=0; //关闭INT0中断
- PWM=~PWM; //取反
- if( NextState )
- {
- TL0=Time0L;
- TH0=Time0H;
- NextState=0;
- }
- else
- {
- TL0=Time1L;
- TH0=Time1H;
- NextState=1;
- us500++;
- }
- if( us500 > 199 ) //定时100ms到否
- {
- ……………………
- …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码
所有资料51hei提供下载:
51测速测距12864.zip
(47.96 KB, 下载次数: 114)
|