本帖最后由 1五湖四海1 于 2011-8-1 20:38 编辑
上班以后,路程比较远就很少骑车了,最近单位发了一台自行车。周末休息时上公园骑了几圈。回来后想如果有个速度表就好了,看看自己能骑到多少Km/h。自己是个爱制作DIY的电子爱好者,坐着想了一个设计方案。这个要有里程表有速度显示和行驶时间显示。这些功能只要一个功能强大的单片机就可以完成要求。 功能上采用6个数码管做显示,打开后左边三位显示里程数单位为Km,右边两位显示速度单位为Km/h。当按下转换按钮后,显示内容切换到显示行驶时间,左边两位显示小时,右边两位显示分钟,秒信号用中间小数点闪烁显示。再次按下转换按钮时,所以数码管关闭以节省电能,再按下转换按钮回到显示里程速度。 那天坐公交车,汽车突然启动时,这时有个加速度到匀速行驶。这让我想起水银开关,利用水银开关成45度角放置在垂直平面水银开关头朝后。这样就可以完成加速度检测了。如果车停止或匀速前进时水银开关闭合。一旦汽车启动或加速后水银开关断开,等到匀速后水银开关再次闭合。只有计算出从闭合到断开再到闭合的时间就可以知道加速度大小了。同样原理可以制成减速检测。我利用这一原理将加速度检测加到了自行车速度里程表。我还利用555制作了一个1KHz的频率信号输入到扬声器做提示音,如果超速时发出提示音。 我制作这个自行车速度里程表出于自己对DIY单片机兴趣爱好,我认为在实用性上也很方便可以测速度,里程,行驶时间和加速度而且还带扬声器超速时提示,用起来蛮好的。 自行车速度里程表由硬件和软件组成,硬件是由单片机最小系统加六位扫描数码管和霍尔速度传感器构成。软件用C语言编写的下面是源程序还有单片机原理图 ///////////2010.08.09.21:00/////////////////// #include<reg52.h> #include<absacc.h> #include <intrins.h> #define uint unsigned int #define uchar unsigned char #define shum P1 //数码 #define saom P2 //数码扫描 unsigned char code xsjs[]={~0x3F,~0x06,~0x5B,~0x4F,~0x66,~0x6D,~0x7D,~0x07,~0x7F,~0x6F ,~0x00}; char disp[4]={0,0,0,0}; uchar T0count; //从T0的计数单元中读取计数的数值 uchar timecount; // bit flag; bit d_05s=0; uchar set=0; uchar sp=30; //标志位 unsigned long x; unsigned long z; unsigned long y; unsigned long a; unsigned long d; uchar hour=0,min=0,sec=0; uchar xPos,yPos; uchar i; uchar she=30; V[7]; uint j=0; sbit P0_1=P0^1; sbit P2_1=P2^1; sbit P1_7=P1^7; sbit P3_1=P3^1; sbit P3_2=P3^2; sbit P3_4=P3^4; sbit P3_5=P3^5; sbit P3_6=P3^6; sbit P3_7=P3^7; void delay(uint k) { uint i,j; for(i=0;j<k;i++) { for(j=0;j<121;j++); } } void scan_key() { delay(1); if(P3_2==0)set++; if(set>=3)set=0; if(set==1)flag=0x55; F0:if(P3_2==0)goto F0; } void display_led()//数码管模块 {char e,scan; disp[0]=hour/10; disp[1]=hour%10; disp[2]=min/10; disp[3]=min%10; P0=0xff; scan=0xdf; for(e=0;e<4;e++) { shum=0xff; saom=scan; if(d_05s==1) {if(e==1)P1_7=0;else P1_7=1;}
P1=xsjs[disp[e]]; delay(4); scan>>=1; } } void lidisp() { d=a/7;
P1=xsjs[y/10000]; P2=0xdf;delay(1); P1=xsjs[y%10000/1000]; P1_7=0; P2=0xef; delay(1); P1=xsjs[y%1000/100]; P2=0xf7;delay(1); P1=xsjs[10]; P2=0xfb;delay(1); P1=xsjs[d/10]; P2=0xfd;delay(1); P1=xsjs[d%10]; P2=0xfe;delay(1); }
void main(void) {
TMOD=0x15; //T0工作为16位计数器(方式1),T1工作方式为16位定时器 TH0=0; //计数为65536 TL0=0; // TH1=(65536-12000)/256; //定时器采用定时4ms. 初值为12000 TL1=(65536-12000)%256; TR1=1; //TR1=1,控制开关闭合,计数脉冲进入T1计数器,启动定时 TR0=1; //TR0=1,控制开关闭合,计数脉冲进入T1计数器,启动计数 ET0=1; //定时器0开中断 ET1=1; //定时器1开中断 EA=1; //CPU开中断 y=0; while(1) { if(P3_1==1) {
if(P3_2==0)scan_key(); switch(set) { case 0: lidisp(); break; case 1: display_led(); break; case 2: P1=0xff; break; default:break; }
if(flag==1) // { flag=0; //清标志位 z=2*(T0count*65536+TH0*256+TL0); //取得时间宽度参数 x=z*36/10; y=z+y;
if(j==0)
{ V[0]=x; V[1]=x; V[2]=x; V[3]=x; V[4]=x; V[5]=x; V[6]=x; j++; } if(0<j<=7) { V[j]=x; j++; } if(j>7) { j=0;V[j]=x; j++; } a=V[0]+V[1]+V[2]+V[3]+V[4]+V[5]+V[6];
timecount=0; T0count=0; TH0=0; TL0=0; TR0=1; //TR0=1,控制开关闭合,计数脉冲进入T1计数器,启动计数 } } else {if(P3_6==0)she++;if(P3_5==0)she--; P1=xsjs[she/10]; P2=0xfd;delay(5); P1=xsjs[she%10]; P2=0xfe;delay(5); } } } //;================================================================================== void t0() interrupt 1 using 0 //T0中断服务 { T0count++; //对P3。4口的脉冲进行计数 } //;================================================================================== void t1(void) interrupt 3 using 0 //T1中断服务 { TH1=(65536-12000)/256; //计数初值重装载 TL1=(65536-12000)%256; timecount++; if(timecount==250) { sec++; TR0=0; timecount=0; flag=1; // 置标志 } if(timecount<=125)d_05s=0; else d_05s=1; if(sec==60){min++;sec=0;} if(min==60){hour++;min=0;} if(hour==24){hour=0;} }
|