本次讲解蓝桥杯超声波模块, 当然本程序也适用于大部分51单片机.
首先来看看蓝桥杯板载的超声波模块:
观察原理图,我们需要在板子上用跳线帽将J2的1,3短接,2,4短接.
下面我们来分析超声波模块的使用:
超声波模块的两个端口一个为超声波发送端,一个是接收端, 并且分别引出了两个端口,Trig发送和Echo接收,使用方法为利用Trig发送8个频率为40kHz的方波, 此时开启定时器,直到Echo接收到返回的超声波(接收信号为Echo的下降沿),停止定时器,采集到的时间便是求出超声波模块到障碍物之间的距离的关键.
根据空气中声波的平均速度340m/s, 利用公式:距离 = 340*(时间t) / (往返2). 由于51单片机的定时器计时周期为1us,则可以得出:距离 = (定时器时间t)*0.017.
但是51单片机处理浮点运算的时间太长, 这里对*0.017进行快速运算:
0.017 = (2^4+1)/1000 = 2^4/1000 + 0.001 约为 2^4/1000, 在精度要求不高的情况下可以约为 2^4/1024 = 2^4/2^10 = 2^-6
整理到C语言2^-6对应为>>6(右移6位), 这样的话对超声波的数据处理速度可以提高几十倍,.
下面给出代码:
/*
超声波实验:通过定时器控制端口发送8个40kHZ的方波,用接收端口测距
公式: 距离 = (高电平时间*340m/s)/2
@author:BelingBeling
PS: 初始化时将trig和echo端口置低, 然后给trig发送8个40KHz的方波
f=40KHz T=1/40K=12.5us 则使用延迟12us来实现
打开定时器开始定时, 捕捉echo的下降沿,当捕捉到下降沿时, 读出定时器的时间, 这就是超声波在空气中传播的时间
*/
#include "reg52.h"
#include "intrins.h"
#define uchar unsigned char
#define uint unsigned int
sbit Trig=P1^0;
sbit Echo=P1^1;
uchar code table[] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90, 0x88,0x80,0xc6,0xc0,0x86,0x8e,0xbf,0x7f};
uchar DisplayNum[]={0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
uchar DisplaySite=0; //数码管位置
uchar Distance=0;
void Sonic_Wave();
void Sonic_Distance();
void ChooseNixie(uchar site,uchar num);
void Display();
void Delay(uint i);
void Delay12us(); //@11.0592MHz
void main()
{
TMOD|=0x00; TH1=0; TL1=0; //定时器1初值载入
while (1)
{
Display();
}
}
//超声波//
void Sonic_Wave() //发送8个40KHz的方波
{
uchar i;
for (i=0;i<8;i++) //经过测试:i<7也可以
{
Trig=1;
Delay12us();
Trig=0;
Delay12us();
}
}
void Sonic_Distance() //距离测量
{
uint time; //记录时间
Sonic_Wave(); //发送波
TR1=1; //启动定时器
while ( (Echo==1)&&(TF1==0) ); //等待接收到波(Echo检测到下降沿)或者定时器溢出
TR1=0; //关闭定时器
/*计算距离:
定时器是1us计数加一, 求声速传播距离公式为 X = 340*t/2 (单位为 m)
将数码管的显示值转换为 cm ,乘以100, 获得的时间单位为us, 需要转化为s,除以1,000,000
故,Sonic_Distance = Sonic_Distance*0.017; 为了使处理速度加快,需要转化为整数操作
0.017 = 17/10/100
*/
if (TF1==0) //正常范围之内
{
time=TH1;
time=(time<<8)|TL1;
// Distance=time*0.017
// 0.017 = 17/1000 = (2^4+1)/1000 = 2^4/1000 + 0.001 约为 2^4/1000 在精度不高的情况下 约为 2^4/1024 = 2^4/2^10 = 2^-6
Distance = time>>6; 进行处理速度的提高
}
else
{
TF1=0;
Distance=999;
}
TH1=0; TL1=0; //恢复定时器
}
void Delay12us() //@11.0592MHz
{
unsigned char i;
_nop_();
_nop_();
_nop_();
i = 30;
while (--i);
}
void ChooseNixie(uchar site,uchar num)
{
P2=(P2&0x1F)|0xE0; P0=0xFF; P2&=0x1F;
P2=(P2&0x1F)|0xC0; P0=1<<site; P2&=0x1F;
P2=(P2&0x1F)|0xE0; P0=num; P2&=0x1F;
}
void Delay(uint i)
{
while (i--);
}
void Display()
{
static uchar i;
if (++i==10)
{
Sonic_Distance();
i=0;
}
DisplayNum[7]=table[Distance%10];
DisplayNum[6]=table[Distance%100/10];
DisplayNum[5]=table[Distance/100];
for (DisplaySite=5;DisplaySite<8;DisplaySite++)
{
ChooseNixie(DisplaySite,DisplayNum[DisplaySite]);
Delay(60);
}
}