[讨论] HC-SR04如何测距

bbs.pan.com   2014-8-10 22:29 楼主
怎么使用HC-SR04模块测距呢,网上好多程序都试了,都不行,求教

回复评论 (10)

时间差折算成距离就是了
点赞  2014-8-10 22:39
引用: huo_hu 发表于 2014-8-10 22:39
时间差折算成距离就是了

我也是这样,不过还是得不到结果,以下是我的程序,麻烦帮看下有什么问题

#include      //包括一个52标准内核的头文件
#include
#include "lcd1602.h"    //1602LCD的头文件,这个没问题
#define uchar unsigned char //定义一下方便使用
#define uint  unsigned int
#define ulong unsigned long
sbit Trig  = P3^3; //产生脉冲引脚
sbit Echo  = P3^2; //回波引脚
sbit VCC = P1^1;
sbit GND = P1^0;
uchar count = 0;
uchar time = 0;
uint distance[4];  //测距接收缓冲区
uchar ge,shi,bai,temp,flag,outcomeH,outcomeL,i;  //自定义寄存器
bit succeed_flag;  //测量成功标志
//********函数声明
void conversion(uint temp_data);
void delay_20us();
void Init_timer();  //初始化定时器

void main(void)   // 主程序
{  
uint distance_data;
uint t = DELAY;
delay_20us();
Init_timer();
lcd1602_Init();
Trig=0;       //首先拉低脉冲输入引脚
VCC = 1;
GND = 0;

while(1)         //程序循环
{
     TH0=0x3c; //写入定时器0初始值
  TL0=0xb0;
  count = 0;

  Trig=1;
  delay_20us();
  Trig=0;         //产生一个20us的脉冲,在Trig引脚
  while(!Echo);  //等待Echo回波引脚变高电平
  TR0 = 1;
  while(Echo);
  TR0 = 0;     
  
  
  outcomeH =TH0;    //取出定时器的值
  outcomeL =TL0;    //取出定时器的值
  succeed_flag = 1;

     distance_data=outcomeH;                //测量结果的高8位
     distance_data<<=8;                   //放入16位的高8位
     distance_data=distance_data|outcomeL;//与低8位合并成为16位结果数据
     distance_data = count * 50 * 1000 + distance_data - (0x3c << 8) - 0xb0;
     distance_data/=58;                   //微秒的单位除以58等于厘米
            //为什么除以58等于厘米,  Y米=(X秒*344)/2
                                          // X秒=( 2*Y米)/344 ==》X秒=0.0058*Y米 ==》厘米=微秒/58
   

  conversion(distance_data);
  lcd1602_WriteComm(0x80);
  lcd1602_WriteData('0' + bai);
  lcd1602_WriteData('.');
  lcd1602_WriteData('0' + shi);
  lcd1602_WriteData('0' + ge);         
}
}

//****************************************************************
//定时器0中断,用做计数,12M每次定时50ms
void timer0() interrupt 1  // 定时器0中断是1号
{
EA = 0;
TH0=0x3c; //写入定时器0初始值
TL0=0xb0;
count++;
EA = 1;
}

//显示数据转换程序
void conversion(uint temp_data)  
{  
    uchar ge_data,shi_data,bai_data ;
    bai_data=temp_data/100 ;
    temp_data=temp_data%100;   //取余运算
    shi_data=temp_data/10 ;
    temp_data=temp_data%10;   //取余运算
    ge_data=temp_data;
    bai = bai_data;
    shi = shi_data;
    ge  = ge_data ;
}


void delay_20us()
{  
_nop_();_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();nop_();_nop_();_nop_();
}

void Init_timer()
{
TMOD=0x01;   //定时器0,16位工作方式
TH0=0x3c; //写入定时器0初始值
TL0=0xb0;
TR0 = 0;

TF0 = 0;
ET0 = 1;        //打开定时器0中断
EA=1;         //打开总中断0  
}
点赞  2014-8-11 09:35
这个帖子有人顶吗 问题你解决了吗
点赞  2016-4-18 14:30
楼主请问有调试好的测距程序吗?
点赞  2016-6-29 09:24
引用: Jzeng123 发表于 2016-4-18 14:30
这个帖子有人顶吗 问题你解决了吗

都快两年了,楼主的问题早就应该解决了。
点赞  2016-7-13 10:54
我也正在做测距的程序,正好可以参考这些代码。
点赞  2016-7-13 10:54
我在贴一个 测试通过来源网络 SMC1602A(16*2)模拟口线接线方式 连接线图: --------------------------------------------------- |LCM-----51 | LCM-----51 | LCM------51 | --------------------------------------------------| |DB0-----P0.0 | DB4-----P0.4 | RW-------P2.3 | |DB1-----P0.1 | DB5-----P0.5 | RS------- P2.4 | |DB2-----P0.2 | DB6-----P0.6 | E-------- P2.2 | |DB3-----P0.3 | DB7-----P0.7 | VLCD接3K电阻到GND| --------------------------------------------------- 接线:模块TRIG接 P3.7 ECH0 接P3.6 =============================================================*/ #include //器件配置文件 #include #define RX P3_6 #define TX P3_7 #define LCM_RW P2_3 //定义LCD引脚 #define LCM_RS P2_4 #define LCM_E P2_2 #define LCM_Data P0 #define Busy 0x80 //用于检测LCM状态字中的Busy标识 void LCMInit(void); void DisplayOneChar(unsigned char X, unsigned char Y, unsigned char DData); void DisplayListChar(unsigned char X, unsigned char Y, unsigned char code *DData); void Delay5Ms(void); void Delay400Ms(void); void Decode(unsigned char ScanCode); void WriteDataLCM(unsigned char WDLCM); void WriteCommandLCM(unsigned char WCLCM,BuysC); unsigned char ReadDataLCM(void); unsigned char ReadStatusLCM(void); unsigned char code mcustudio[] ={"==Range Finder=="}; unsigned char code email[] = {"heyaodz@163.com "}; unsigned char code Cls[] = {" "}; unsigned char code ASCII[15] = {'0','1','2','3','4','5','6','7','8','9','.','-','M'}; static unsigned char DisNum = 0; //显示用指针 unsigned int time=0; unsigned long S=0; bit flag =0; unsigned char disbuff[4] ={ 0,0,0,0,}; //写数据 void WriteDataLCM(unsigned char WDLCM) { ReadStatusLCM(); //检测忙 LCM_Data = WDLCM; LCM_RS = 1; LCM_RW = 0; LCM_E = 0; //若晶振速度太高可以在这后加小的延时 LCM_E = 0; //延时 LCM_E = 1; } //写指令 void WriteCommandLCM(unsigned char WCLCM,BuysC) //BuysC为0时忽略忙检测 { if (BuysC) ReadStatusLCM(); //根据需要检测忙 LCM_Data = WCLCM; LCM_RS = 0; LCM_RW = 0; LCM_E = 0; LCM_E = 0; LCM_E = 1; } //读数据 unsigned char ReadDataLCM(void) { LCM_RS = 1; LCM_RW = 1; LCM_E = 0; LCM_E = 0; LCM_E = 1; return(LCM_Data); } //读状态 unsigned char ReadStatusLCM(void) { LCM_Data = 0xFF; LCM_RS = 0; LCM_RW = 1; LCM_E = 0; LCM_E = 0; LCM_E = 1; while (LCM_Data & Busy); //检测忙信号 return(LCM_Data); } void LCMInit(void) //LCM初始化 { LCM_Data = 0; WriteCommandLCM(0x38,0); //三次显示模式设置,不检测忙信号 Delay5Ms(); WriteCommandLCM(0x38,0); Delay5Ms(); WriteCommandLCM(0x38,0); Delay5Ms(); WriteCommandLCM(0x38,1); //显示模式设置,开始要求每次检测忙信号 WriteCommandLCM(0x08,1); //关闭显示 WriteCommandLCM(0x01,1); //显示清屏 WriteCommandLCM(0x06,1); // 显示光标移动设置 WriteCommandLCM(0x0F,1); // 显示开及光标设置 } //按指定位置显示一个字符 void DisplayOneChar(unsigned char X, unsigned char Y, unsigned char DData) { Y &= 0x1; X &= 0xF; //限制X不能大于15,Y不能大于1 if (Y) X |= 0x40; //当要显示第二行时地址码+0x40; X |= 0x80; //算出指令码 WriteCommandLCM(X, 1); //发命令字 WriteDataLCM(DData); //发数据 } //按指定位置显示一串字符 void DisplayListChar(unsigned char X, unsigned char Y, unsigned char code *DData) { unsigned char ListLength; ListLength = 0; Y &= 0x1; X &= 0xF; //限制X不能大于15,Y不能大于1 while (DData[ListLength]>0x19) //若到达字串尾则退出 { if (X <= 0xF) //X坐标应小于0xF { DisplayOneChar(X, Y, DData[ListLength]); //显示单个字符 ListLength++; X++; } } } //5ms延时 void Delay5Ms(void) { unsigned int TempCyc = 5552; while(TempCyc--); } //400ms延时 void Delay400Ms(void) { unsigned char TempCycA = 5; unsigned int TempCycB; while(TempCycA--) { TempCycB=7269; while(TempCycB--); }; } /********************************************************/ void Conut(void) { time=TH0*256+TL0; TH0=0; TL0=0; S=(time*1.8)/10; //算出来是MM if((S>=7000)||flag==1) //超出测量范围显示“-” { flag=0; DisplayOneChar(0, 1, ASCII[11]); DisplayOneChar(1, 1, ASCII[10]); //显示点 DisplayOneChar(2, 1, ASCII[11]); DisplayOneChar(3, 1, ASCII[11]); DisplayOneChar(4, 1, ASCII[11]); DisplayOneChar(5, 1, ASCII[12]); //显示M } else { disbuff[0]=S/1000; disbuff[1]=S/100%10; disbuff[2]=S/10%10; disbuff[3]=S%10; DisplayOneChar(0, 1, ASCII[disbuff[0]]); DisplayOneChar(1, 1, ASCII[10]); //显示点 DisplayOneChar(2, 1, ASCII[disbuff[1]]); DisplayOneChar(3, 1, ASCII[disbuff[2]]); DisplayOneChar(4, 1, ASCII[disbuff[3]]); DisplayOneChar(5, 1, ASCII[12]); //显示M } } /********************************************************/ void zd0() interrupt 1 //T0中断用来计数器溢出,超过测距范围 { flag=1; //中断溢出标志 RX=0; } /********************************************************/ void StartModule() //启动模块 { TX=1; //启动一次模块 _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); TX=0; } void Timer_Count(void) { TR0=1; //开启计数 while(RX); //当RX为1计数并等待 TR0=0; //关闭计数 Conut(); //计算 } /********************************************************/ void delayms(unsigned int ms) { unsigned char i=100,j; for(;ms;ms--) { while(--i) { j=10; while(--j); } } } /*********************************************************/ void main(void) { unsigned int valA; unsigned char TempCyc; Delay400Ms(); //启动等待,等LCM讲入工作状态 LCMInit(); //LCM初始化 Delay5Ms(); //延时片刻(可不要) DisplayListChar(0, 0, mcustudio); DisplayListChar(0, 1, email); ReadDataLCM();//测试用句无意义 for (TempCyc=0; TempCyc<10; TempCyc++) Delay400Ms(); //延时 DisplayListChar(0, 1, Cls); TMOD=0x01; //设T0为方式1,GATE=1; TH0=0; TL0=0; ET0=1; //允许T0中断 EA=1; //开启总中断 while(1) { delayms(60); RX=1; StartModule(); for(valA=7510;valA>0;valA--) { if(RX==1) { Timer_Count(); } } } } 本帖最后由 jinxiang 于 2016-11-24 11:25 编辑
点赞  2016-11-24 11:17
我有50对40kHz超声传感器,谁要,可联系zzlls@126.com
点赞  2016-12-1 09:52
引用: hujj 发表于 2016-7-13 10:54
都快两年了,楼主的问题早就应该解决了。

有道理哈,不过我现在不搞单片机啦~~~
点赞  2017-7-31 16:21
上网找个1602显示距离的,打吧
点赞  2017-8-8 11:53
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复