原理:
超声波方面:
超声波指向性强,能量消耗缓慢,在介质中传播的距离较远,因而超声波可用于距离的测量。
超声波发射器向某一方向发射超声波,在发射时刻的同时开始计时,超声波在空气中传播,途中碰到障碍物就立即返回来,超声波接收器收到反射波就立即停止计时。超声波在空气中的传播速度为340m/s,根据计时器记录的时间t,就可以计算出发射点距障碍物的距离(s),
即:S=Vt/2 。
51单片机方面:
震荡周期,时钟周期:晶振提供
机器周期:CPU完成一个独立操作,为十二个震动周期
即:外接12MHz晶振51单片机每进行一次操作需要1us
HC-SR04方面:
(1)采用IO口TRIG触发测距,给至少10us的高电平信号; (2)模块自动发送8个40khz的方波,自动检测是否有信号返回; (3)有信号返回,通过IO口ECHO输出一个高电平,高电平持续的时间就是超声波从发射到返回的时间。
时序图:
代码实现部分:
#include <reg52.h>
#include <intrins.h>
typedef unsigned int u16; //对数据类型进行声明定义
typedef unsigned char u8;
sbit Trig = P2^1;
sbit Echo = P2^0;
sbit LED=P2^2;
u8 str[20]={0};
u8 zhi=10;
u8 code strerror[]={"error"};
u8 i;
u16 time;
u16 S=0;
bit flag=0;
/*******************************************************************************
函数功能 :串口通信配置
*******************************************************************************/
void USARTinit()
{
SCON=0X50; //设置为工作方式1
TMOD=0X20|TMOD; //设置计数器工作方式2
PCON=0X80; //波特率加倍
TH1=0XF3; //计数器初始值设置,波特率是4800
TL1=0XF3;
ES=1; //打开串口中断
EA=1; //打开总中断
TR1=1; //打开计数器
}
/*******************************************************************************
函数功能 : 串口通信发送中断函数
输入 : 要发送的一字节数据
*******************************************************************************/
void send(u8 Data)
{
SBUF=Data; //数据放入到发送寄存器
while(!TI); //等待发送数据完成
TI=0; //清除发送完成标志位
}
/*******************************************************************************
函数功能 : 定时器0初始化,用于计算时间
*******************************************************************************/
void T0inti()
{
TMOD=0x01|TMOD; //设T0为方式1
TH0=0;
TL0=0;
ET0=1; //允许T0中断
EA=1; //开启总中断
}
/*******************************************************************************
函数功能 : 外部中断初始化
*******************************************************************************/
void EXinit()
{
EX0=1; //打开外部中断0
IT0=1; //边沿触发方式
EX1=1; //打开外部中断1
IT1=1; //边沿触发
EA=1; //打开总中断
}
/*******************************************************************************
函数功能 : 阈值初始化
*******************************************************************************/
void zhiinit() interrupt 0
{
zhi=10;
}
/*******************************************************************************
函数功能 : 阈值加10
*******************************************************************************/
void zhichuli() interrupt 2
{
zhi=zhi+10;
}
/*******************************************************************************
函数功能: 提示计数器溢出,超过测距范围
*******************************************************************************/
void error() interrupt 1
{
flag=1; //中断溢出标志
S=0;
}
/*******************************************************************************
函数功能 : 定时器0初始化,用于计算距离
*******************************************************************************/
void Conut()
{
if(flag==0)
{
time=TH0*256+TL0;
TH0=0;
TL0=0;
(u16)S=(time*1.7)/100; //算出来是CM
}
}
/*******************************************************************************
函数功能 : 对计算数据做处理,并发送,同时做量程判断
*******************************************************************************/
void chuli()
{
ES=1; //打开串口中断
TI=0;
if(S<=zhi) //距离小于阈值cm或者距离大于测量值LED点亮,LED低电平点亮 (初始为10)
{
LED=0;
}
else
{
LED=1;
}
if(S==0)
{
for(i=0;i<=5;i++)
{
send(strerror[i]);
}
flag=0;
TH0=0;
TL0=0;
}
if(S>0)
{
for(i=1;S>=1;i++)
{
str[i]=(unsigned char)(S%10)+'0';
(u16)S=S/10;
}
for(i=i-1;i>0;i--)
{
send(str[i]);
}
send('\r');
send('\n');
ES=0; //关闭串口中断
}
}
/*******************************************************************************
函数功能 : 启动HC-SR04
*******************************************************************************/
void Start() //启动HC-SR04需要10us高电平,一个_nop_()是1us,保险起见设置20个
{
Trig=1;
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
Trig=0;
}
void main()
{
T0inti();
EXinit();
USARTinit() ;
while(1)
{
Start() ;
while(!Echo); //当Echo为零时等待
TR0=1; //开启计数
while(Echo); //当Echo为1计数并等待
TR0=0; //关闭计数
Conut() ;
chuli();
}
}
收获:
对于单片机串口通信有了更深理解。
模块化编程有了一些尝试。