超声波模块工作原理:
(1)采用IO触发测距,给至少10us的高电平信号;
(2)模块自动发送8个40khz的方波,自动检测是否有信号返回;
(3)有信号返回,通过IO输出一高电平,高电平持续的时间就是
超声波从发射到返回的时间.测试距离=(高电平时间*声速(340M/S))/2;
定时器初始化:
考虑到原理(3)有信号返回时输出一个高电平,所以TMOD设置为0x09,GATE=1(需要TR0和中断0(INT0)口都=0,中断才会启动),然后用杜邦线将中断0的引脚和超声波模块的I0口(echo口)连接,这样当超神波返回时,echo=1,INT0=1,中断启动。
我试过将初始设置为10us和100us两种,10us时,s=vt,100us时,s=vt/2,按照公式s=vt/2才是正确的,但是我10us时,值相差也不大,不知道什么原因,但是这个不对,所以下面代码中,用的是100us这个。
------------------------------------------------分割线----------------------------------------------------------------
#include "reg52.h" typedef unsigned char uchar; typedef unsigned int uint; sbit trig=P2^0; sbit echo=P2^1; sbit beep=P1^5; sbit LSA=P2^2; sbit LSB=P2^3; sbit LSC=P2^4; uint num=0; //计时 float distance; //距离 float cm_per_num=3.40; //按照我的定时器初始化设定,1个num是100us uchar DisplayData[6]; uchar code smgduan[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07, 0x7f,0x6f};//显示0~9的值 void delay1ms(uchar xms) { uchar a,b,c; for(c=xms;c>0;c--) for(b=142;b>0;b--) for(a=2;a>0;a--); } /* 设置工作方式为方式1,GATE=1,当中断0口输入1且TR0=1 时定时器工作 因为超声波模块的工作原理就是在接收回波时,从开始到结束,ech0=1 所以在单片机上用杜邦线将ech0的P21口和 中断0口 P32口链接 使得在回波期间,定时器工作,计算回波的时间,进而s=vt算出距离 */ void TimerInit() //初始化,定时10us { TMOD = 0x09; TH0 = 0xFF; TL0 = 0x9C; EA = 1; ET0 = 1; TR0 = 1; } void Timer0() interrupt 1 //中断 每过100us,num+1 { TH0 = 0xFF; TL0 = 0x9C; num++; } void value_distance() { trig=0; echo=0; delay1ms(1); trig=1; delay1ms(11); //给trig一个10us以上的高电平信号 trig=0; if(echo==1) //如果有反射回的超声波,echo脚会在这期间持续输入高电平 { delay1ms(300); //接收超声波期间不做任何动作。 } distance=num*cm_per_num/2; //计算距离,单位CM num=0; } void datapros() //对取得的距离进行处理 { float a= distance*100; DisplayData[0]=smgduan[(int)a%10]; DisplayData[1]=smgduan[(int)a%100/10]; DisplayData[2]=smgduan[(int)a%1000/100]+0x80; //数字+小数点 DisplayData[3]=smgduan[(int)a%10000/1000]; DisplayData[4]=smgduan[(int)a/10000]; } void DigDisplay() //数码管显示 { uchar i; for(i=0;i<6;i++) { switch(i) //位选,选择点亮的数码管, { case(0): LSA=0;LSB=0;LSC=0; break;//显示第0位 case(1): LSA=1;LSB=0;LSC=0; break;//显示第1位 case(2): LSA=0;LSB=1;LSC=0; break;//显示第2位 case(3): LSA=1;LSB=1;LSC=0; break;//显示第3位 case(4): LSA=0;LSB=0;LSC=1; break;//显示第4位 case(5): LSA=1;LSB=0;LSC=1; break;//显示第5位 } P0=DisplayData[i];//发送段码 delay1ms(1); //间隔一段时间扫描 P0=0x00;//消隐 } } void main() { while(1) { TimerInit(); value_distance(); datapros(); DigDisplay(); } }