51单片机例程
51单片机
HC-SR04超声波
一、基本介绍
超声波测距模块是根据超声波遇障碍反射的原理进行测距的,能够发送超声波、接收超声波并通过处理,输出一段和发送与接收间隔时间相同的高电平信号,是常用的测距模块之一。HC-SR04是最常用的超声波测距模块之一,HC-SR04超声波模块可提供2cm~400cm的非接触式距离感测功能,测距精度可达3mm,工作电压为5V;内部模块包括超声波发射器、接收器与控制电路。
Vcc:+5V电源供电;
Trig:输入触发信号(可以触发测距);
Echo:传出信号回响(可以传回时间差);
GND:接地。
二、基本工作原理
(1)采用I/O口连接Trig触发测距,给最少10us的高电平后即可发送超声波;
(2)模块自动发送8个40kHz的方波,并自动检测是否有信号返回;
(3)若有信号返回,经内部电路处理后,通过Echo到I/O口输入一个高电平,高电平持续的时间就是超声波从发射到返回的时间;
(4)测试距离=(高电平时间*音速)/2;音速=340m/s=0.034cm/us。
代码实现
/* 8051单片机头文件,包含特殊功能寄存器定义 */
#include<reg52.h>
/* 内联函数库,包含_nop_()等函数 */
#include<intrins.h>
/* 延时函数,z为延时参数,值越大延时越长 */
void delay(unsigned char z)
{
unsigned char x,y;
/* 外层循环,循环z次 */
for(x=0;x<z;x++)
{
/* 内层循环,循环110次(固定延时) */
for(y=0;y<110;y++)
{
; /* 空指令实现延时 */
}
}
}
/* LCD控制引脚定义 */
sbit EN = P2^7; /* 使能信号 */
sbit RS = P2^6; /* 寄存器选择(1:数据 0:指令) */
sbit RW = P2^5; /* 读写控制(1:读 0:写) */
/* 检测LCD忙状态函数 */
void jc()
{
unsigned char i;
P0 = 0XFF; /* P0口置高电平(准备读取) */
RS = 0; /* 选择指令寄存器 */
RW = 1; /* 设置为读模式 */
/* 循环检测忙标志,最多200次 */
for(i=0;i<200;i++)
{
EN = 0; /* 使能脉冲下降沿 */
EN = 1; /* 使能脉冲上升沿 */
/* 读取P0.7(BF忙标志),为0表示不忙 */
if(!(P0&0X80))
{
break; /* 不忙则退出循环 */
}
}
EN = 0; /* 结束使能 */
}
/* 写数据到LCD函数 */
void xrsj(unsigned char date)
{
jc(); /* 先检测忙状态 */
RS = 1; /* 选择数据寄存器 */
RW = 0; /* 设置为写模式 */
P0 = date; /* 输出数据到P0口 */
delay(5); /* 短暂延时 */
EN = 1; /* 使能脉冲上升沿 */
delay(5); /* 保持使能 */
EN = 0; /* 结束使能 */
}
/* 写指令到LCD函数 */
void xrml(unsigned char com)
{
jc(); /* 先检测忙状态 */
RS = 0; /* 选择指令寄存器 */
RW = 0; /* 设置为写模式 */
P0 = com; /* 输出指令到P0口 */
delay(5); /* 短暂延时 */
EN = 1; /* 使能脉冲上升沿 */
delay(5); /* 保持使能 */
EN = 0; /* 结束使能 */
}
/*********************** 超声波测距部分 **************************/
unsigned int distance[]={0,0,0,0}; /* 存储距离的各位数字(千、百、十、个位) */
sbit trig = P1^0; /* 超声波触发引脚 */
sbit echo = P1^1; /* 超声波回波引脚 */
/* 函数声明 */
void chufa(); /* 触发超声波 */
void jisuan(); /* 计算距离 */
/* 超声波测距主函数 */
void ceshi()
{
chufa(); /* 发送触发脉冲 */
while(!echo); /* 等待回波引脚变高 */
TR0 = 1; /* 启动定时器0开始计时 */
while(echo); /* 等待回波引脚变低 */
TR0 = 0; /* 停止定时器0 */
jisuan(); /* 计算距离值 */
delay(5); /* 短暂延时 */
}
/* 超声波触发函数 */
void chufa()
{
trig = 0; /* 初始低电平 */
trig = 1; /* 触发高电平 */
/* 16个_nop_()实现约16us的脉冲(12MHz时钟) */
_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();
trig = 0; /* 恢复低电平 */
}
/* 距离计算函数 */
void jisuan()
{
unsigned int x,y;
/* 计算定时器计数值(TH0为高8位,TL0为低8位) */
x = TH0 * 256 +TL0;
/* 时钟校正(12MHz时钟,11.0592MHz计算) */
x *= 12/11.0592;
/* 计算距离(cm):340m/s声速,时间x单位为us */
/* 0.017 = 34000/1000000/2 (往返时间要除以2) */
y = x * 0.017;
/* 重置定时器 */
TH0 = 0;
TL0 = 0;
/* 分解距离的各位数字 */
distance[3] = y / 1 % 10; /* 个位 */
distance[2] = y / 10 % 10; /* 十位 */
distance[1] = y / 100 % 10; /* 百位 */
distance[0] = y / 1000 % 10;/* 千位 */
}
/* 显示距离函数 */
void xsjl()
{
unsigned char i;
/* 设置LCD显示位置(第二行开头) */
xrml(0x80+0x40);
/* 显示4位距离数字 */
for(i=0;i<4;i++)
{
/* 数字转ASCII码(加0x30) */
xrsj(0x30+distance[i]);
delay(5);
}
}
/*********************** 初始化部分 **************************/
void init()
{
EA = 1; /* 开启总中断 */
ET0 = 1; /* 开启定时器0中断 */
TMOD = 0X01; /* 设置定时器0为模式1(16位定时器) */
TH0 = 0; /* 定时器初值清零 */
TL0 = 0;
/* LCD初始化指令序列 */
xrml(0x38); /* 8位数据接口,两行显示,5x7点阵 */
xrml(0x0c); /* 开显示,关光标 */
xrml(0x06); /* 地址自动增加 */
xrml(0x01); /* 清屏 */
}
/*********************** 主函数 **************************/
void main()
{
/* LCD显示内容定义 */
unsigned char yi[] = {"ChaoShengBo JuLi"}; /* 第一行文本 */
unsigned char er[] = {"cm"}; /* 单位 */
unsigned int k = 0;
init(); /* 系统初始化 */
/* 显示第一行文本 */
xrml(0x80); /* 设置第一行起始地址 */
for(k=0;k<16;k++)
{
xrsj(yi[k]); /* 逐个字符显示 */
delay(5);
}
/* 显示单位"cm" */
xrml(0x80+0x44); /* 设置第二行第5列位置 */
for(k=0;k<2;k++)
{
xrsj(er[k]); /* 显示"c"和"m" */
delay(5);
}
/* 主循环 */
while(1)
{
ceshi(); /* 执行测距 */
xsjl(); /* 显示距离 */
}
}

浙公网安备 33010602011771号