/********************************************************************************************************************
HC-SR04 超声波测距模块可提供 2cm-400cm 的非接触式距离感测功能, 测距精度可达高到 3mm;模块包括超声波发射器、接收器与控制电路。
基本工作原理:
(1)采用 IO 口 TRIG 触发测距,给至少 10us 的高电平信号;
(2)模块自动发送 8个40khz 的方波,自动检测是否有信号返回;
(3)有信号返回,通过IO口ECHO 输出一个高电平,高电平持续的时间就是超声波从发射到返回的时间。测试距离=(高电平时间*声速(340M/S))/2;
*********************************************************************************************************************/
#include
#include
typedef unsigned int u16;
typedef unsigned char u8;
sbit LSA=P2^2;
sbit LSB=P2^3;
sbit LSC=P2^4;
u8 DisplayData[3];
u8 code table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
//TRIG为控制端
sbit TRIG = P1^6; //超声波的 TRIG端 插在了P1.6口
//ECHO 为接收端
sbit ECHO = P1^7; //超声波的 ECHO端 插在了P1.7口
u8 flag = 0; //标志定时器是否溢出
/*******************************************************************************
* 函 数 名 : delay
* 函数功能 : 延时函数,i=1时,大约延时10us
*******************************************************************************/
void delay(u16 i)
{
while(i--);
}
void init_time()
{
TMOD = 0x01; //选择定时器0工作 工作方式为方式1
TH0 = 0; //装初值0
TL0 = 0;
TF0 = 0; //中断溢出标志位
ET0 = 1; //开定时器中断
EA = 1; // 开总中断
}
/*******************************************************************************
* 函数名 :display(int num)
* 函数功能 :数码管显示函数
* 输入 : 无
* 输出 : 无
*******************************************************************************/
void display(int num) //显示函数
{
u8 i;
if(num == -1) //当超出范围 显示999
{
DisplayData[0] = table[9];
DisplayData[1] = table[9];
DisplayData[2] = table[9];
}
else //显示到前三个数码管上 因为测距范围为2-400cm 故3位即可
{
//取百位
DisplayData[0] = table[num / 100]|0x80;
//取十位
DisplayData[1] = table[num/10%10];
//取个位
DisplayData[2] = table[num %10];
}
for(i=0;i<3;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位
}
P0=DisplayData[i];//发送数据
delay(100); //间隔一段时间扫描
P0=0x00;//消隐
}
}
void delayed(unsigned int x) //延时xmS
{
unsigned int i,j;
for(i = x; i > 0; i--)
{
for(j = 113; j >0; j--);
}
}
void main()
{
int x;
u16 distance,out_TH0,out_TL0;
TRIG = 0; // 先给控制端初始化为0
while(1)
{
/*超声波传感器的使用方法:
控制口发一个10US 以上的高电平,就可以在接收口等待高电平输出。一有输出就可以开定时器计时,当此口变为低电平时就可以读定时器的,此时就为此次测距的时间,方可算出距离。如此不断的周期测, 就可以达到移动测量的值了*/
init_time(); //初始化定时器
flag = 0; //置溢出标志位为0
//控制口发一个10US 以上的高电平
TRIG = 1;
delay(2);
TRIG = 0;
//等待接收端出现高电平
while(!ECHO);
TR0 = 1; //启动计时器 开始计时
while(ECHO); //等待高电平结束
TR0 = 0; //关闭低电平
out_TH0 = TH0; //取定时器的值
out_TL0 = TL0;
out_TH0 <<= 8; //右移8位
distance = out_TH0 | out_TL0; //合并为16位的值
distance /= 58;
if(flag == 1) //如果定时器溢出 则超出超声波测量范围
{
display(-1);
flag = 0;
}
else
{
for(x =5; x >=0; x--)//加此循环只是为了将结果在数码管上停留时间长点便于观察
{
display(distance);
}
}
delay(600);//60ms的周期,这里不是6ms,太多会闪烁。
}
}
void timer0() interrupt 1 //中断函数
{
flag=1; //溢出标志位置1
}
实验结果: