精华内容
下载资源
问答
  • HC-SR04超声波测距模块
    2022-05-09 16:57:29

    1. 基本参数

    工作电压

    DC5V

    工作电流

    15mA

    工作频率

    40Khz

    最远射程

    4m

    最近射程

    2cm

    测量角度

    15°

    输入触发角度

    10uS的TTL脉冲

    输出回响信号

    输出TTL信号

    规格尺寸

    45*20*15mm

    2. 基本原理

    1) 单片机IO口发送≥10us的持续高电平信号,作为起始信号。

    2)模块自动发送8个40Khz的方波,单片机自动检测Ehco引脚是否有信号返回;

    3)若有信号返回,开启定时器计时,当检测到Echo引脚为低电平则关闭定时器,此时的时间为发射超声到接收回波的时间,因为物体的距离=(定时器时间*340)/2。

    4)若无信号返回,则继续等待信号返回。

    3. 时序图

    4. 程序范例

    单片机选型为STC15W204S。

    #ifndef __HCSR04_H__
    
    #define __HCSR04_H__
    
    
    
    sbit TRIG=P5^5;
    
    sbit ECHO=P3^2;
    
    
    
    bit flag=0;         
    
    bit succed_flag=0;   //测距中断完成标志位
    
    bit single_flag=0;   //单总线标志位
    
    
    
    float distance=0;
    
    u16 temp=0;
    
    
    
    void tim0_init()
    
    {
    
        //AUXR = 0x80;                //定时器1为1T模式
        TMOD = 0x00;                //定时器1为模式2(8位自动重载)
        TL0 = 0xCD;                  //设置定时初始值
        TH0 = 0xD4;                  //设置定时初始值
        TR0 = 0;                    //定时器1开始启动
    }
    
    //hc-sr04起始信号
    void hcsr04_start_single()
    {
         TRIG=1;
         Delay20us();
         TRIG=0;
    }
    
    //hc-sr04测距转换函数
    u8 hcsr04_covert()
    {
         temp=TH0*256+TL0;                           
         TH0=0;
         TL0=0;
         distance=(temp*1.87)/10000;
         return distance;
    }
    #endif
    
    更多相关内容
  • HC-SR04超声波测距模块及原理图
  • 本工程采用两路轮询触发HC-SR04超声波测距模块,将测到的距离通过RS485发送至上位机。测量频率高。抗干扰强!
  • 1、适用于STM32RCT6最小系统板,HC-SR04超声波测距模块(工作电压5V,静态工作电流) 2、量程2cm--700cm,感应角度°(R8=4.7K);R8=3.9K/4.3K时:量程2cm--450cm,感应角度° 3、精度3mm,盲区2cm
  • 通过STM32 超声波测量距离 通过寄存器来写的 距离如果接近或开挨住 可能会出现没有数据 最大距离3米
  • HC-SR04超声波测距模块及原理图
  • 1、典型工作用电压:5V 2、超小静态工作电流:小于 5mA 3、感应角度(R3 电阻越大,增益越高,探测角度越大): R3 电阻为 392,不大于 15 度 R3 电阻为 472, 不大于 30 度 4、探测距离(R3 电阻可调节增益,即调节探测距离): ...
  • 代码规范,注释清晰,各个模块文件清晰,可以用来扩展。
  • HC-SR04超声波测距模块资料C51软件驱动+DEMO演示例程KIEL源码: HC-SR04超声波测距模块.pdf TCT40-16T.R1规格书.pdf 超声波PIC单片机C程序 超声波原理图.jpg 超声波模块原理图.pdf 超声波模块参考.pdf 超声波模块说明...
  • 基于89C52的HC-SR04超声波测距模块12864显示
  • 在STM32平台上利用HC-SR04超声波测距模块进行测距,然后利用OLED12864显示测量距离(测距范围0~3米,误差1mm)
  • HC-SR04超声波测距,串口输出,数码管显示,STM32F103C8T6
  • 智能小车最常用的测距避障模块,有C51+1602测距例程,如果需要stm32超声波舵机避障的程序,可以加评论。
  • 本JSN-SR04T超声波测距模块性能稳定,测度距离精确。能和国外的SRF05,SRF02等超声波测距模块相媲美。模块高精度,盲区(25cm),稳定的测距是此产品成功走向市场的有力依据。 基本工作原理: 采用IO口TRIG触发测距,给...
  • HC-SR04 超声波测距模块可提供 2cm-400cm 的非接触式距离感测功 能,测 距精度可达高到 3mm;模块包括超声波发射器、接收器与控制电路。
  • STM32F103ZET6单片机实现HC-SR04超声波模块测距源码,利用定时器中断方式测距,直接兼容正点原子开发板。亲测有效!
  • 【实验73】HC-SR04超声波测距模块.zip源码arduino例程源码GL9例程源代码【实验73】HC-SR04超声波测距模块.zip源码arduino例程源码GL9例程源代码【实验73】HC-SR04超声波测距模块.zip源码arduino例程源码GL9例程源...
  • 基于正点原子的精英板的程序,超声波模块HC-SR04HC-SR05都可以使用,对应的两个引脚采用的PF0和PF1
  • CS100A-CS102探超声波模块技术资料,包括HC-SR04等4款超声波模块AD设计硬件原理图PCB文件,及相关文档技术资料,包括完整的原理图和PCB文件,可用Altium Designer(AD)软件打开或修改,可作为你产品设计的参考。
  • HC-SR04超声波测距模块的原理介绍与代码实现

    万次阅读 多人点赞 2020-12-22 23:25:46
    文章目录1、超声波模块介绍...HC-SR04 超声波测距模块可提供 2cm-400cm 的非接触式距离感测功能,测 距精度可达高到的非接触式距离感测功能,测距精度可达高到 3mm ;模块包括超声波发射器、接收器与控制电路。 2)基本

    1、超声波模块介绍

    超声波模块一般使用的都是HC-SR04来进行测距
    在这里插入图片描述

    1)产品特点

    HC-SR04 超声波测距模块可提供 2cm-400cm 的非接触式距离感测功能,测
    距精度可达高到的非接触式距离感测功能,测距精度可达高到 3mm ;模块包括超声波发射器、接收器与控制电路。

    2)基本工作原理

    (1)采用 IO 口 TRIG 触发测距,给最少 10us 的高电平信呈。
    (2)模块自动发送 8 个 40khz 的方波,自动检测是否有信号返回;
    (3)有信号返回,通过 IO 口 ECHO 输出一个高电平,高电平持续的时间就是超声
    波从发射到返回的时间。测试距离=(高电平时间*声速(340M/S))/2;

    3)实物图

    在这里插入图片描述
    如右图接线,

    • Vcc:+5V电源供电
    • Trig:输入触发信号(可以触发测距)
    • Echo:传出信号回响(可以传回时间差)
    • Gnd:接地
    4)电气参数

    在这里插入图片描述

    2、超声波模块原理

    1)超声波时序图

    在这里插入图片描述
    以上时序图表明你只需要提供一个 10uS 以上脉冲触发信号,该模块内部将发出 8 个 40kHz 周期电平并检测回波。一旦检测到有回波信号则输出回响信号 。回响信号的脉冲宽度与所测的距离成正比。由此通过发射信号到收到的回响信号时间间隔可以计算得到距离。公式:uS/58=厘米或者 uS/148=英寸;或是:距离=高电平时间*声速(340M/S)/2;建议测量周期为 60ms 以上,以防止发射信号对回响信号的影响。
    注:
    1 、此模块不宜带电连接,若要带电连接,则先让模块的 GND 端先连接,否则会影响模块的正常工作。
    2 、测距时,被测物体的面积不少于 0.5 平方米且平面尽量要求平整,否则影响测量的结果

    2)实现思路
    • 1.直接给trig高电平,然后读取ECHO引脚是否为高电平,若为高电平,则开启定时器,然后继续检测等待其为低电平的时候,获取计数器值,然后进行计算

    • 2.开启外部中断,先将ECHO配置上升沿中断,当中断来临的时候,在中断函数里面开启定时器,再将其配置为下降沿中断,等待下降沿中断来临的时候,获取计数器值。

    其实上面的两种方法,其思路都是通过计算定时器的counter值,来计算距离

    • 3.定时器一路PWM控制触发以及触发周期,超声波返回信号高电平时间用定时器通道捕捉功能获取

    定时器输入捕获的使用方法可以参考一下我其他的文章:TIM定时器使用介绍

    3、参考代码

    1)stm8基于TIM1的ch1输入捕获实现
    // 关于超声波测距的宏定义
    #define HCSR04_TRIG PC_ODR_ODR0  //PC0为TRIG,输出10us的高电平
    #define HCSR04_ECHO PC_IDR_IDR1  //PC1为ECHO,输入一个脉冲信号
    #define SYS_CLOCK   16000000     //定义系统当前fmaster频率值15797600UL。
    
    //获取距离的函数
    float Hcsr04_getdistance(void)
    {
        u16 B_num = 0;  
        u32 Time = 0;
        float Distance = 0;
      
          HCSR04_TRIG = 0; 
    //   printf("准备开始测试...\n");
     
        //   TIM1_CCR1H=0x00;//清除捕获/比较寄存器1高8位
     //   TIM1_CCR1L=0x00;//清除捕获/比较寄存器1低8位
        TIM1_SR1&=0xF9;//清除CC1IF标志位与CC2IF标志位
        TIM1_SR2&=0xF9;//清除CC1OF标志位与CC2OF标志位
        TIM1_CCER1|=0x11;//捕获功能使能
     //   printf("捕获功能开启,等待ECHO信号...\n");
       
         //TRIG给最少 10us 的高电平信呈    
          HCSR04_TRIG = 1;
          delay_10us(5);
          HCSR04_TRIG = 0;
       //   overflow_count = 0;
      //    printf("TRIG已发送 10uS 以上脉冲触发信号...\n");
          
         while((TIM1_SR1&0x02)==0);//等待捕获比较1标志位CC1IF变为“1”
      //   TIM1_CR1|=0x01;        //使能TIM1计数器功能“CEN=1”
      //   printf("上升沿信号捕获...\n");
         
        while((TIM1_SR1&0x04)==0);//等待捕获比较2标志位CC2IF变为“1”
     //   printf("下降沿信号捕获...\n");
         
        //取出数据CC2IF位就自动清0
        B_num=(u16)TIM1_CCR2H<<8;//取回捕获/比较寄存器2高8位
        B_num|=TIM1_CCR2L;//取回捕获/比较寄存器2低8位并与高8位拼合
     //   printf("B_num:%d\n",B_num);
       
       // TIM1_SR1&=0xFB;//清除CC2IF标志位
        
         Time = B_num*1000000/SYS_CLOCK; //脉冲长度单位为us
      //   printf("Time:%d\n",Time);
         
         Distance = B_num/16.05*0.017;
     //    printf("Distance:%f cm\n",Distance);
         
    
    
         TIM1_CCER1&=0xEE;//捕获功能禁止
        
         return Distance;
    }
    
    
    /****************************************************************/
    //TIM1功能初始化函数TIM1_init(),无形参,无返回值
    /****************************************************************/
    void TIM1_init(void)
    {
      //1.CC1通道被配置为输入,IC1映射在TI1FP1上“CC1S[1:0]=01”
      // 0x000000001 : CC1通道被配置为输入,IC1映射在TI1FP1上;
      TIM1_CCMR1|=0x01;
      
      //2.配置TI1FP1信号边沿极性为上升沿“CC1P=0”
      // 0x11111101 : 捕获发生在TI1F或TI2F的上升沿;
      TIM1_CCER1&=0xFD;
      
      //3.CC2通道被配置为输入,IC2映射在TI1FP2上“CC2S[1:0]=10”
      // 0x00000010 : CC2通道被配置为输入,IC1映射在TI2FP2上;
      TIM1_CCMR2|=0x02;
      
      //4.配置TI1FP2信号边沿极性为下降沿“CC2P=1”
      // 0x00100000 : 1:捕获发生在TI1F或TI2F的下降沿
      TIM1_CCER1|=0x20; 
      
      //5.配置触发输入信号为TI1FP1,“TS[2:0]=101”
      // 0x01010000 : 选择用于选择同步计数器的触发输入,滤波后的定时器输入1(TI1FP1)
      TIM1_SMCR|=0x50;
      
      //6.配置触发模式为复位触发,“SMS[2:0]=100”
      // 0x00000100 : 复位模式 – 在选中的触发输入(TRGI)的上升沿时重新初始化计数器,并且产生一个更新寄存器的信号
      TIM1_SMCR|=0x04;
      
      //7.使能TIM1计数器功能“CEN=1”
      TIM1_CR1|=0x01;
      
      //没有设置在外部触发寄存器(TIM1_ETR)中的采样频率
    }
    
    //初始化
    void HCSR04_Init(void)
    {
      //PC1为ECHO,PC0为TRIG
        //设置TRIG引脚为PC0,TRIG输出一个10us的高电平触发
        PC_DDR_DDR0 = 1;  
        PC_CR1_C10 = 1;   
        PC_CR2_C20 = 0;   
        
        //设置ECHO引脚为PC1,ECHO输入一个脉冲信号,需要用定时器测出持续时间
      
        PC_DDR_DDR1 = 0;  //设置为PC1为输入
        PC_CR1_C11 = 1;   //设置诶上拉输入
        PC_CR2_C21 = 0;   //带中断
       
       
     /*   
        PC_DDR_DDR1 = 0;  //设置为PD2为输入
        PC_CR1_C11 = 1;   //设置诶上拉输入
        PC_CR2_C21 = 1;   //带中断
      */
    }
    
    2)51实现测距并使用数码管显示(淘宝提供)
    //超声波测距
    //晶振=8M
    //MCU=STC10F04XE
    //P0.0-P0.6共阳数码管引脚
    //Trig  = P1^0
    //Echo  = P3^2
    #include <reg52.h>     //包括一个52标准内核的头文件
    #define uchar unsigned char //定义一下方便使用
    #define uint  unsigned int
    #define ulong unsigned long
    //***********************************************
    sfr  CLK_DIV = 0x97; //为STC单片机定义,系统时钟分频
                         //为STC单片机的IO口设置地址定义
    sfr   P0M1   = 0X93;
    sfr   P0M0   = 0X94;
    sfr   P1M1   = 0X91;
    sfr   P1M0   = 0X92;
    sfr	P2M1   = 0X95;
    sfr	P2M0   = 0X96;
    //***********************************************
    sbit Trig  = P1^0; //产生脉冲引脚
    sbit Echo  = P3^2; //回波引脚
    sbit test  = P1^1; //测试用引脚
    
    uchar code SEG7[10]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90};//数码管0-9
    uint distance[4];  //测距接收缓冲区
    uchar ge,shi,bai,temp,flag,outcomeH,outcomeL,i;  //自定义寄存器
    bit succeed_flag;  //测量成功标志
    //********函数声明
    void conversion(uint temp_data);
    void delay_20us();
    //void pai_xu();
    
    void main(void)   // 主程序
    {  uint distance_data,a,b;
       uchar CONT_1;   
       CLK_DIV=0X03; //系统时钟为1/8晶振(pdf-45页) 
         P0M1 = 0;   //将io口设置为推挽输出
         P1M1 = 0;
         P2M1 = 0;
         P0M0 = 0XFF;
         P1M0 = 0XFF;
         P2M0 = 0XFF;
       i=0;
       flag=0;
    	test =0;
    	Trig=0;       //首先拉低脉冲输入引脚
    	TMOD=0x11;    //定时器0,定时器1,16位工作方式
    	TR0=1;	     //启动定时器0
       IT0=0;        //由高电平变低电平,触发外部中断
    	ET0=1;        //打开定时器0中断
     //ET1=1;        //打开定时器1中断
    	EX0=0;        //关闭外部中断
    	EA=1;         //打开总中断0	
      
    	
    while(1)         //程序循环
    	{
      EA=0;
    	     Trig=1;
            delay_20us();
            Trig=0;         //产生一个20us的脉冲,在Trig引脚  
            while(Echo==0); //等待Echo回波引脚变高电平
    	     succeed_flag=0; //清测量成功标志
    	     EX0=1;          //打开外部中断
    	 	  TH1=0;          //定时器1清零
            TL1=0;          //定时器1清零
    	     TF1=0;          //
            TR1=1;          //启动定时器1
       EA=1;
    
          while(TH1 < 30);//等待测量的结果,周期65.535毫秒(可用中断实现)  
    		  TR1=0;          //关闭定时器1
            EX0=0;          //关闭外部中断
    
        if(succeed_flag==1)
    	     { 	
    		   distance_data=outcomeH;                //测量结果的高8位
               distance_data<<=8;                   //放入16位的高8位
    		     distance_data=distance_data|outcomeL;//与低8位合并成为16位结果数据
                distance_data*=12;                  //因为定时器默认为12分频
               distance_data/=58;                   //微秒的单位除以58等于厘米
             }                                      //为什么除以58等于厘米,  Y米=(X秒*344)/2
    			                                       // X秒=( 2*Y米)/344 ==》X秒=0.0058*Y米 ==》厘米=微秒/58 
        if(succeed_flag==0)
    		   {
                distance_data=0;                    //没有回波则清零
    		   	test = !test;                       //测试灯变化
               }
    
         ///       distance[i]=distance_data; //将测量结果的数据放入缓冲区
         ///        i++;
      	  ///	 if(i==3)
    	  ///	     {
    	  ///	       distance_data=(distance[0]+distance[1]+distance[2]+distance[3])/4;
         ///        pai_xu();
         ///        distance_data=distance[1];
    
          
    	   a=distance_data;
           if(b==a) CONT_1=0;
           if(b!=a) CONT_1++;
           if(CONT_1>=3)
    		   { CONT_1=0;
    			  b=a;
    			  conversion(b);
    			}       
    	  ///		 i=0;
     	  ///		}	     
    	 }
    }
    //***************************************************************
    //外部中断0,用做判断回波电平
    INTO_()  interrupt 0   // 外部中断是0号
     {    
         outcomeH =TH1;    //取出定时器的值
         outcomeL =TL1;    //取出定时器的值
         succeed_flag=1;   //至成功测量的标志
         EX0=0;            //关闭外部中断
      }
    //****************************************************************
    //定时器0中断,用做显示
    timer0() interrupt 1  // 定时器0中断是1号
       {
     	 TH0=0xfd; //写入定时器0初始值
    	 TL0=0x77;	 	
    	 switch(flag)   
          {case 0x00:P0=ge; P2=0xfd;flag++;break;
    	    case 0x01:P0=shi;P2=0xfe;flag++;break;
    	    case 0x02:P0=bai;P2=0xfb;flag=0;break;
          }
       }
    //*****************************************************************
    /*
    //定时器1中断,用做超声波测距计时
    timer1() interrupt 3  // 定时器0中断是1号
        {
    TH1=0;
    TL1=0;
         }
    */
    //******************************************************************
    //显示数据转换程序
    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_data=SEG7[bai_data];
        shi_data=SEG7[shi_data];
        ge_data =SEG7[ge_data];
    
        EA=0;
        bai = bai_data;
        shi = shi_data;
        ge  = ge_data ; 
    	 EA=1;
     }
    //******************************************************************
    void delay_20us()
     {  uchar bt ;
        for(bt=0;bt<100;bt++);
     }
    /*
    void pai_xu()
      {  uint t;
      if (distance[0]>distance[1])
        {t=distance[0];distance[0]=distance[1];distance[1]=t;} /*交换值
      if(distance[0]>distance[2])
        {t=distance[2];distance[2]=distance[0];distance[0]=t;} /*交换值
      if(distance[1]>distance[2])
        {t=distance[1];distance[1]=distance[2];distance[2]=t;} /*交换值	 
        }
    */
    
    展开全文
  • HC-SR04超声波测距模块ALTIUM设计硬件原理图+PCB工程文件+CS100A-CS102等相关器件技术资料,包括完整的原理图和PCB文件,硬件可用Altium Designer(AD)软件打开或修改,可作为你产品设计的参考。
  • STM32—驱动HC-SR04超声波测距模块

    万次阅读 多人点赞 2019-11-23 20:21:52
    利用HC-SR04超声波测距模块可以实现比较精确的直线测距,其测距原理图如下: HC-SR04的一端发出超声波,接触到反射物后反射,被另一个端口接收到,所以只要知道发射和接收的时间差,就可以根据声波传播的速率算出HC...

    超声波测距原理

    利用HC-SR04超声波测距模块可以实现比较精确的直线测距,其测距原理图如下:
    在这里插入图片描述
    HC-SR04的一端发出超声波,接触到反射物后反射,被另一个端口接收到,所以只要知道发射和接收的时间差,就可以根据声波传播的速率算出HC-SR04和反射物直接的距离。
    所以实现超声波测距就需要俩个条件:

    • 发射和接收的时间差
    • 超声波传输的速率

    HC-SR04工作原理

    HC-SR04模块的电气参数如示:
    在这里插入图片描述
    HC-SR04模块的实物图如示:
    在这里插入图片描述
    有四个引脚:

    • Vcc:+5V电源供电
    • Trig:输入触发信号(可以触发测距)
    • Echo:传出信号回响(可以传回时间差)
    • Gnd:接地

    用Trig和Echo引脚实现测距的流程:
    1.通过Trig输出一段至少10us的高电平(脉冲),触发一次测距,超声波在传输的过程中Echo一直输出高电平。
    2.在Trig脉冲输出后,立即检测Echo引脚的电平,测出Echo高电平持续的时间t,t就是超声波在所测距离一个来回所需时间。
    测距时序图如示:
    在这里插入图片描述

    STM32实现驱动

    利用STM32驱动HC-SR04需要做好几个关键点:

    • 引脚的配置
    • 时序的控制
    • 时间差的测量

    下面来分开实现几个关键点

    1.引脚的配置

    HC-SR04四个引脚,Vcc和Gnd直接接在开发板的电源上即可,主要是Trig和Echo引脚的配置,我选择了PB1连接Trig引脚、PB2连接Echo引脚。
    因为要控制Trig输出电平,所以PB1引脚模式是推挽输出GPIO_Mode_Out_PP
    Echo要检测高电平持续的时间,所以PB2引脚模式是浮空输入GPIO_Mode_IN_FLOATING
    相关的配置代码如下:

    void SR04_GPIO_Init( void )
    {
    	GPIO_InitTypeDef GPIO_InitStruct;
    	RCC_APB2PeriphClockCmd( Trig_Clock  |Echo_Clock , ENABLE );
    	
    	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
    	GPIO_InitStruct.GPIO_Pin = Trig_PIN;
    	GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
    	GPIO_Init(Trig_PORT, &GPIO_InitStruct);
    	
    	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    	GPIO_InitStruct.GPIO_Pin = Echo_PIN;
    	GPIO_Init(Echo_PORT, &GPIO_InitStruct);
    }
    

    2.时序控制

    HC-SR04的时序是:先来一段10us的Trig高电平,接着接收一段Echo的高电平,伪代码如下:

    #define Trig_H  GPIO_SetBits(GPIOB, GPIO_Pin_1)
    #define Trig_L  GPIO_ResetBits(GPIOB, GPIO_Pin_1)
    
    /* Trig给一个至少10us的高电平,超声波进行一次测距 */
    	Trig_H;
    	Delay_us( 10 );
    	Trig_L;
    /* 等待Echo高电平 */
    

    3.时间差测量

    这个是最重要的一步,要测量Echo高电平持续的时间,因为光传播的速率是340m/s,而测距的范围大多是cm级别,所以相应Echo高电平持续的时间也就是us级别的。
    所以,测量时间差的条件就比较苛刻,我是利用SysTick(系统计数器)的原理实现计时的。SysTick计数器原理是对通过SysTick_Config()函数配置每俩次中断之间的节拍数,也就是俩次中断之间的机器周期,我大概算出了,测出0.1cm距离的Echo高电平时间约为6um,而系统时钟的频率是72MHz,所以配置每俩次中断之间的节拍为432的时候,进入一次中断就代表0.1cm的距离,所以只需要记录进入中断的次数就可以算出距离。通过一个全局变量在中断函数中自增来记录中断次数。SysTick_Config函数源代码如下:

    static __INLINE uint32_t SysTick_Config(uint32_t ticks)
    { 
    	/* 判断ticks 是否超出装填值和重装值的最大值 */
      if (ticks > SysTick_LOAD_RELOAD_Msk)  return (1);            
      
      /* 配置 装载寄存器 */	
      SysTick->LOAD  = (ticks & SysTick_LOAD_RELOAD_Msk) - 1;     
    	/* 配置 内核中断的优先级,也是在NVIC中 */
      NVIC_SetPriority (SysTick_IRQn, (1<<__NVIC_PRIO_BITS) - 1); 
    	/* 加载计数器的值 */
    	/* SysTick->VAL是当前数值寄存器的值 */
      SysTick->VAL   = 0;      
     
    	/* CTRL是SysTick控制及状态寄存器:
    		CLKSOURCE:位段2 时钟源选择,0=APB/8;1=APB  APB即72MHz
    	  TICKINT:   位段1 当置为1时,计数器递减到0时会产生中断请求;当置为0时无动作
    	  ENABLE:   位段0 使能位,可以启动SysTick定时器*/
    	SysTick->CTRL  = SysTick_CTRL_CLKSOURCE_Msk | 
                       SysTick_CTRL_TICKINT_Msk   | 
                       SysTick_CTRL_ENABLE_Msk;                  
      return (0);                                              
    }
    
    

    SysTick的具体原理可以参考一下我之前的博客:SysTick原理

    注意:SysTick_Config()函数执行完就开启了中断,所以必须在Echo为低电平后及时关闭中断,并且将记录中断的变量清零。
    中断函数如示:

    /* 用extern和volatile关键字修饰的 全局变量n */
    extern volatile uint32_t n;
    
    void SysTick_Handler(void)
    {
    	n++;
    }
    

    关闭中断及清零n的代码如下:

    /* 本来的使能位取反 */
    SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk;
    

    SysTick->CTRL寄存器的0位控制着中断的使能,具体情况在之前SysTick的博客中已做详细说明。

    4.如何将距离测出来

    我在main函数中实现了距离的测量,并且通过串口打印函数将距离传到上位机,具体代码如示:

    int main(void)
    {
    
    	int i=1,q;
    	float p;
    	/* HC-SR04模块引脚初始化 */
    	SR04_GPIO_Init();
    	/* 串口相关配置 */
    	GQ_UART_Config();
    	/* 打印调试信息 */
    	printf("慢漫的测距实验\n ");
    	
    	
    	while( 1 )
    	{
    		/* 每0.5s测一次距离 */
    		Delay_ms( 500 );
    	
    		/* Trig给一个至少10us的高电平,超声波进行一次测距 */
    		Trig_H;
    		Delay_us( 10 );
    		Trig_L;
    		/* 等待Echo高电平 */
    		while( Echo_Value != 1 );
    		/* 打开中断,对Echo高电平时间计时 */
    		/* 配置计数器的装载值是72*6=432,即一次中断6um,正好是超声波的0.1cm,所以中断次数n对应着n*0.1cm */
    		/* SysTick_Config()中已经使能计数器了,所以无需再开启	*/
    		SysTick_Config( 432 );
    		/* 等待直到Echo为低电平 */
    		while(Echo_Value == 1);
    		/* 关闭中断,通过参数n来取得距离参数 */
    		/* 本来的使能位取反 */
    		SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk;
    		/* p、q分别是距离的整数部分和小数部分 */
    		p=n/10;
    		q=n%10;
    		/* 打印距离信息 */
    		/* p-50时经过调试的,因为测量的距离和诸多因素有关,这个操作减小了误差 */
    		printf("第%d次测量为:%.0f.%dcm\n",i,p-50,q);
    		i++;
    		/* 清零中断记录变量n */
    		n=0;
    	}
    	
    }
    
    展开全文
  • HC-SR04超声波测距模块学习记录

    千次阅读 2021-06-03 19:43:53
    文章目录一、关于HC-SR04超声波测距模块1.硬件介绍2.工作原理二、基于STM32的驱动代码 一、关于HC-SR04超声波测距模块 1.硬件介绍 HC-SR04 超声波测距模块可提供 2cm-400cm 的非接触式距离感测功能,测距精度可达高...

    一、关于HC-SR04超声波测距模块

    1.硬件介绍

    在这里插入图片描述

    HC-SR04 超声波测距模块可提供 2cm-400cm 的非接触式距离感测功能,测距精度可达高到 3mm;模块包括超声波发射器、接收器与控制电路。
    相关引脚:
    VCC:电源
    GNN:接地
    Trig:触发信号输入
    Echo:回响信号输出
    在这里插入图片描述
    [注]: 1、此模块不宜带电连接,若要带电连接,则先让模块的 GND 端先连接,否则会影响模块的正常工作。

    2、测距时,被测物体的面积不少于 0.5 平方米且平面尽量要求平整,否则影响测量的结果。

    2.工作原理

    在这里插入图片描述

    通过脉冲触发引脚(trig)提供一个 10uS 以上高电平信号,该模块内部将发出 8 个 40kHz 周期电平并检测回波,一旦检测到有回波信号则通过Echo引脚输出一个高电平,高电平持续的时间就是超声波从发射到返回的时间。
    由此可得出计算公式:
    测试距离=(高电平时间*声速(340M/S))/2;
    我这里使用的是定时器的输入捕获功能来直接读取高电平的持续时间。

    二、基于STM32的驱动代码

    main.c

    #include "delay.h"
    #include "sys.h"
    #include "hcsr04.h"
    #include "usart.h"
    
    
     int main(void)
     {	
    	  
    	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);// 设置中断优先级分组2
    	delay_init();	    	 //延时函数初始化	
    	uart_init(9600);	 			//9600	 
    	HCSR04_TRIG_Init();
     	TIM3_Cap_Init(0XFFFF,72-1);		//以1Mhz的频率计数  ARR取最大
       	while(1)
    	{
     		delay_ms(1000);
    		HCSR04_TRIG_Send();	
        HCSR04_Distance();		
    
    	}
    }
    
    

    Trig的相关设置:

    void HCSR04_TRIG_Send(void)
    {
          TRIG=1;
    	  delay_us(15);
    	  TRIG=0;
    }
    
    void HCSR04_TRIG_Init(void)
    {  
    	 GPIO_InitTypeDef GPIO_InitStructure;
     	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA , ENABLE);  //使能GPIO外设时钟使能
    	                                                                     	
    	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8; 
    	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;  //推挽输出
    	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    	GPIO_Init(GPIOA, &GPIO_InitStructure);
      
    }
    

    输入捕获配置:
    将PA6的定时器3通道1作为输入捕获通道,也就是将ECHO接到PA6

    u8  TIM3CH1_CAPTURE_STA;		//输入捕获状态		    				
    u16	TIM3CH1_CAPTURE_VAL;	//输入捕获值
    
    TIM_ICInitTypeDef  TIM3_ICInitStructure;
    
    void TIM3_Cap_Init(u16 arr,u16 psc)
    {	 
    	GPIO_InitTypeDef GPIO_InitStructure;
    	TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
     	NVIC_InitTypeDef NVIC_InitStructure;
    
    	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);	//使能TIM3时钟
     	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);  //使能GPIOA时钟
    	
    	GPIO_InitStructure.GPIO_Pin  = GPIO_Pin_6;   
    	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; //PA6 输入  
    	GPIO_ResetBits(GPIOA,GPIO_Pin_6);						 //PA6 下拉						 
    	GPIO_Init(GPIOA, &GPIO_InitStructure);
    	//初始化定时器3 TIM3	 
    	TIM_TimeBaseStructure.TIM_Period = arr; //设定计数器自动重装值 
    	TIM_TimeBaseStructure.TIM_Prescaler =psc; 	//预分频器   
    	TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //设置时钟分割:TDTS = Tck_tim
    	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //TIM向上计数模式
    	TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位
      
    	//初始化TIM3输入捕获参数
    	TIM3_ICInitStructure.TIM_Channel = TIM_Channel_1; //CC1S=01 	选择输入端 IC1映射到TI1上
      	TIM3_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;	//上升沿捕获
      	TIM3_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI; //映射到TI1上 InDirect 不直接映射到TI1,即映射到TI2上
      	TIM3_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;	 //配置输入分频,不分频 
      	TIM3_ICInitStructure.TIM_ICFilter = 0x00;//IC1F=0000 配置输入滤波器 不滤波
      	TIM_ICInit(TIM3, &TIM3_ICInitStructure);
    	
    	//中断分组初始化
    	NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;  //TIM3中断
    	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;  //先占优先级2级
    	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;  //从优先级0级
    	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能
    	NVIC_Init(&NVIC_InitStructure);  //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器 
    	
    	TIM_ITConfig(TIM3,TIM_IT_Update|TIM_IT_CC1,ENABLE);//允许更新中断 ,允许CC1IE捕获中断	
    	
      TIM_Cmd(TIM3,ENABLE ); 	//使能定时器3
     
    }
    
    
    
    //计算高电平的持续时间
    //定时器3中断服务程序	 
    void TIM3_IRQHandler(void)
    { 
    
     	if((TIM3CH1_CAPTURE_STA&0X80)==0)//还未成功捕获	              更新中断,判断是否有溢出
    	{	  
    		if (TIM_GetITStatus(TIM3,TIM_IT_Update) != RESET)
    		 
    		{	  //第一次捕获  
    			if(TIM3CH1_CAPTURE_STA&0X40)//已经捕获到高电平了
    			{
    				if((TIM3CH1_CAPTURE_STA&0X3F)==0X3F)//高电平太长了
    				{
    					TIM3CH1_CAPTURE_STA|=0X80;//标记成功捕获了一次
    					TIM3CH1_CAPTURE_VAL=0XFFFF;
    				}else TIM3CH1_CAPTURE_STA++;
    			}	 
    		}
    	if (TIM_GetITStatus(TIM3, TIM_IT_CC1) != RESET)//捕获1发生捕获事件
    		{	
    			if(TIM3CH1_CAPTURE_STA&0X40)		//捕获到一个下降沿 		
    			{	  			
    				TIM3CH1_CAPTURE_STA|=0X80;		//标记成功捕获到一次上升沿
    				TIM3CH1_CAPTURE_VAL=TIM_GetCapture1(TIM3);
    		   		TIM_OC1PolarityConfig(TIM3,TIM_ICPolarity_Rising); //CC1P=0 设置为上升沿捕获
    			}else  								//还未开始,第一次捕获上升沿
    			{
    				TIM3CH1_CAPTURE_STA=0;			//清空
    				TIM3CH1_CAPTURE_VAL=0;
    	 			TIM_SetCounter(TIM3,0);
    				TIM3CH1_CAPTURE_STA|=0X40;		//标记捕获到了上升沿
    		   		TIM_OC1PolarityConfig(TIM3,TIM_ICPolarity_Falling);		//CC1P=1 设置为下降沿捕获
    			}		    
    		}			     	    					   
     	}
     
        TIM_ClearITPendingBit(TIM3, TIM_IT_CC1|TIM_IT_Update); //清除中断标志位
     
    }
    
    

    高电平时间及距离计算:

    void HCSR04_Distance(void)
    {
    	u32 temp=0; 
    	float distance=0; 
        if(TIM3CH1_CAPTURE_STA&0X80)//成功捕获到了一次高电平
    		{
    			temp=TIM3CH1_CAPTURE_STA&0X3F;
    			temp*=65536;					//溢出时间总和 us
    			temp+=TIM3CH1_CAPTURE_VAL;		//得到总的高电平时间
    			distance=(float)(temp*340)/20000;
    			printf("HIGH:%d us\r\n",temp);	//打印总的高点平时间
    			printf("distance:%.2f cm\r\n",distance);	//打印距离
     			TIM3CH1_CAPTURE_STA=0;			//开启下一次捕获
     		}
    }
    

    这里我用到了串口,一方面可以检测我的超声波模块是否成功测距,另一方面可以用来监测高电平持续时间及测距距离。

    调试结果如下:
    在这里插入图片描述

    展开全文
  • 本代码是和博客(【STM32学习】(13)STM32实现超声波测距(HC-SR04))中的一致,亲测可用。 内含:源码,串口调试助手,超声波的产品文档
  • 1、FPGA开发板,正点原子系列; 2、超声波模块HC-SR04; 3、语言verilog; 4、测试距离0-20厘米; 5、精度1mm;
  • 1、FPGA开发板,正点原子系列; 2、超声波模块HC-SR04; 3、语言verilog; 4、测试距离0-3米; 5、精度1mm;
  • 利用HC-SR04超声波测距模块可以实现比较精确的直线测距,其测距原理图如下: HC-SR04的一端发出超声波,接触到反射物后反射,被另一个端口接收到,所以只要知道发射和接收的时间差,就可以根据声波传播的速率算出HC-...
  • 超声波测距模块_HC-SR04_ 用户手册-V2.pdf

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,261
精华内容 504
关键字:

hc-sr04超声波测距模块

友情链接: chapter20.zip