超声波测距原理:
超声波发射器向某一方向发射超声波,在发射时刻的同时开始计时,超声波在空气中传播,途中碰到障碍物就立即返回来,超声波接收器收到反射波就立即停止计时。超声波在空气中的传播速度为340m/s,根据计时器记录的时间t,就可以计算出发射点距障碍物的距离(s),即:s=340t/2 。这就是所谓的时间差测距法。
利用超声波进行距离测量,要求精度一般都不高,取20摄氏度时候的声速344M/S进行计算,再进行适当的补偿就可以。所以,其计算公式为:
距离L = 344M/S * T / 2 = 172M/S * T 。
超声波传感器的谐振频率(中心频率)有23kHz、40kHz、75kHz、200kHz、400kHz等,蓝桥杯CT107D使用谐振为40KHZ的超声波。
使用超声波模块前需要将跳帽的1-3 , 2-4连接!!!
使用超声波模块前需要将跳帽的1-3 , 2-4连接!!!
使用超声波模块前需要将跳帽的1-3 , 2-4连接!!!
由跳帽图可知:P10为发射,P11为接收
所以我们需要在代码里定义收发引脚:
sbit TX=P1^0;
sbit RX=P1^1;
先上代码再分析:
void sendwave()
{
unsigned char i;
for(i=0;i<8;i++)
{
TX=1;
delay12us();
TX=0;
delay12us();
}
}
for循环内每次执行的是一高一低的变化,发送8次,就会产生八个40khz矩形脉冲,为什么是八个?可以简单理解为:概率事件,就是不一定每次发一个都能接收到。
注意:中间的延时也是一个重要的地方,经过我的测试在延时12us的时候测试距离可以达到大于200cm。至于这个延时怎么生成:
接收超声波需要用到定时器计时,为了方便,我们采用定时1进行定时。我们也是直接用ISP进行生成:
void Timer1Init(void) //1毫秒@11.0592MHz
{
AUXR | 0xBF; //定时器时钟12T模式
TMOD &= 0x0F; //设置定时器模式
TL1 = 0; //设置定时初始值
TH1 = 0; //设置定时初始值
TF1 = 0; //清除TF1标志
TR1 = 0; //定时器1开始计时
}
这里注意,软件生成的我们要适当修改:具体可以看我代码。
生成的时候注意一下这些地方,想要具体了解原因的可以移步其他文章。
unsigned int checksonic()//接收函数
{
unsigned int t;
unsigned int distance=888;
TH1=TL1=TF1=0;//这里要注意,写这个可以提高精准度
sendwave();//发送
TR1=1;//开始计时
while((RX==1)&&(TF1==0));//判断是否接收到返回来的超声波
TR1=0;//接收到之后停止计数
// if(TF1==0)
if(RX!=1)
{
t=TH1*256+TL1;//将TH1左移八位或上TL1
distance=(unsigned int)(t*0.017)+3;//将时间转化为距离
TH1=0;//清除计时
TL1=0;
}
else if(TF1==1)//如果超时没接收到数据,定时器TF1会置1,也就是距离太远,但是这里赋值999后要手动复位
{
TF1=0;
distance=999;
TH1=0;
TL1=0;
}
return distance;
}
转换那里为啥要加3,这是我自己调的参数,大家可以根据自己实际环境调整。
main.c
#include "stc15f2k60s2.h"
#include "sonic.h"
#define uchar unsigned char
#define uint unsigned int
/*数码管段码显示
一:0-9
二:0.-9.
三:u,p,a,b,c
四:-,.,关
*/
uchar code tab[28]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,
0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10,
0xc1,0x8c,0x88,0x80,0xc6,
0xbf,0x7f,0xff};
//数码管位选
uchar code tab_SMG[8]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};
//数码管内容
uchar t[8];
uchar yi,er,san,si,wu,liu,qi,ba;
uint juli;
uint time=0;
void Timer0Init(void);
void Timer1Init(void); //1毫秒@11.0592MHz
void main()
{
Timer0Init();
Timer1Init();
while(1)
{
t[0]=yi;
t[1]=er;
t[2]=san;
t[3]=si;
t[4]=wu;
t[5]=liu;
t[6]=qi;
t[7]=ba;
yi=juli/100;er=juli%100/10;san=juli%100%10;
si=wu=liu=qi=ba=27;
if(time==550)
{
time=0;
juli=checksonic();
}
}
}
void Timer0Init(void) //1毫秒@11.0592MHz
{
AUXR |= 0x80; //定时器时钟1T模式
TMOD &= 0xF0; //设置定时器模式
TL0 = 0xCD; //设置定时初始值
TH0 = 0xD4; //设置定时初始值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
ET0=1;
EA=1;
}
void timer0() interrupt 1
{
static n=0;
P2=0xc0;P0=tab_SMG[n];//位扫描
P2=0;
P2=0xe0;P0=tab[t[n]];//对应位内容
P2=0;
if(++n>=8)n=0;//移位变量
time++;
}
void Timer1Init(void) //1毫秒@11.0592MHz
{
AUXR |=0xBF; //定时器时钟12T模式
TMOD &= 0x0F; //设置定时器模式
TL1 = 0; //设置定时初始值
TH1 = 0; //设置定时初始值
TF1 = 0; //清除TF1标志
TR1 = 0; //定时器1开始计时
}
sonic.c
#include
sbit TX=P1^0;
sbit RX=P1^1;
void sendwave()
{
unsigned char i;
for(i=0;i<8;i++)
{
TX=1;
delay12us();
TX=0;
delay12us();
}
}
void delay12us()
{
unsigned char i;
_nop_();
_nop_();
_nop_();
i=30;
while(--i);
}
unsigned int checksonic()//接收函数
{
unsigned int t;
unsigned int distance=888;
TH1=TL1=TF1=0;//这里要注意,写这个可以提高精准度
sendwave();//发送
TR1=1;//开始计时
while((RX==1)&&(TF1==0));//判断是否接收到返回来的超声波
TR1=0;//接收到之后停止计数
// if(TF1==0)
if(RX!=1)
{
t=TH1*256+TL1;//将TH1左移八位或上TL1
distance=(unsigned int)(t*0.017)+3;//将时间转化为距离
TH1=0;//清除计时
TL1=0;
}
else if(TF1==1)//如果超时没接收到数据,定时器TF1会置1,也就是距离太远,但是这里赋值999后要手动复位
{
TF1=0;
distance=999;
TH1=0;
TL1=0;
}
return distance;
}
sonic.h
#ifndef _SONIC_H
#define _SONIC_H
#include "stc15f2k60s2.h"
#include "intrins.h"
void delay12us();
void sendwave();
unsigned int checksonic();
#endif