首页 > 其他分享 >【STM32F103】HC-SR04超声波测距模块详解(附工程文件)

【STM32F103】HC-SR04超声波测距模块详解(附工程文件)

时间:2023-12-01 18:00:27浏览次数:52  
标签:STM32F103 SR04 NVIC TIM GPIO HC 测距

前言:
使用的硬件:STM32F103C8T6,HC-SR04,ST-Link(其他烧录器也可以),0.96寸OLED屏幕(非必须,仅供显示测距结果,可以使用串口助手代替),若干杜邦线。

涉及操作stm32的GPIO口,外部中断,定时器,本文中不会详细解释,仅提供代码思路。

HC-SR04:
HC-SR04超声波测距模块提供2cm~400cm的测距功能,精度达3mm。

以下图片截取自深圳市捷深科技有限公司的《HC-SR04超声波测距模块说明书》


通过时序图我们可以知道,我们给HC-SR04发送长达10us的TTL脉冲,然后模块就会进行测距,测距的结果通过回响信号传达,回响的TTL电平信号时间即是超声波从HC-SR04模块发出,触碰到障碍物后返回到HC-SR04模块的时间总和。

TTL是逻辑电平标准,当电压达到2.4V~5V之间,那么为逻辑1(高电平),电压在0V~0.4V之间,那么为逻辑0(低电平)。所以我们可以直接通过GPIO口来输出以及输入时序所需的电平信号。

总所周知,声音的速度为340m/s,因此我们将回响电平的时间除340再除2之后得到的就是单位为米的测距结果。

编写思路:


结合说明书我们可以知道,我们仅需提供10us的高电平给Trig口即可。然后HC-SR04在测量完毕之后会将结果通过Echo回响回来。

所以我们只需要将Trig口拉高,等待10us(最好再延长一些,代码中用的是15us)后再拉低即可。

接着就只需要等待Echo将数据传输回来,通过时序图我们可以得知回响信号是拉高Echo口,再拉低,中间持续的时间就是测距的结果。

所以我们给Echo口配置一个中断事件,设置为上跳变下跳变都触发,另外再用一个变量记录Echo口到底是拉高还是拉低即可。

如果是拉高,那么我们需要记录下持续的时间,这时候我们需要用定时器计时,所以需要在一开始的时候就配置好定时器的初始化。唯一的问题就是该如何配置定时器的预分频器和自动重装器了。

根据说明书我们可以知道HC-SR04的精度为3mm,而测距的公式为 us/58-cm,稍加计算可知,如果我们需要测量3mm,那么得到的时间为17.4us,以此为一个刻度,那么定时器的频率应该为57471Hz。然而这样太麻烦了,而且也不好用,因此我们可以随意一些,我在代码中使用的是预分频器为72,自动重装器为100,那么得到的频率为72MHz/72/100=1000Hz,也就是一次定时器中断的时间为100us,而自动重装器里的每一个值就是1us,所以每次外部中断的下降沿触发之后只需要将定时器触发的次数*100再加上自动重装器里的值就可以得到回响信号的持续时间了,单位是us。

接线:


HC-SR04需要单独提供5V的供电,因此不能与stm32共用一个VCC(3.3V),而ST-Link有5V的供电接口,因此我将5V电压单独拉出来给HC-SR04供电,GND与stm32用同一个。

HC-SR04的Trig接GPIOA的6号口,Echo接GPIOA的7号口。

接线端口没有硬性要求,只需要修改对应代码即可。需要注意的是修改GPIO口的同时还需要修改为对应的中断通道。

OLED的SCK接GPIOB的8号口,SDA接GPIOB的9号口。

 

 

精度还是可以的。

完整代码:

  1 #include "stm32f10x.h"                  // Device header
  2 #include "Delay.h"           //使用的是b站江科大的延时函数,可以自己用别的替代延时功能
  3 #include "OLED.h"            //使用的是b站江科大的OLED驱动代码,用于展示测距结果,可以在相应的地方更换为串口通信展示到电脑的串口助手上
  4  
  5 uint8_t flag=0;                //用于记录中断信号是上升沿还是下降沿
  6 uint32_t number=0;            //记录定时器中断的次数
  7 uint32_t times=0;            //记录回响信号的持续时间
  8  
  9 int main(void){
 10     OLED_Init();
 11     OLED_ShowString(1,1,"Hello World!!!");
 12     
 13     //初始化GPIO口,Trig使用推挽输出,Echo使用浮空输入
 14     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);        //使能GPIOA的外设时钟
 15     GPIO_InitTypeDef itd;
 16     itd.GPIO_Mode=GPIO_Mode_Out_PP;                             //选择推挽输出模式
 17     itd.GPIO_Pin=GPIO_Pin_6;                                    //选择GPIO_Pin_6
 18     itd.GPIO_Speed=GPIO_Speed_50MHz;                            //默认选择50MHz
 19     GPIO_Init(GPIOA,&itd);
 20     
 21     itd.GPIO_Mode=GPIO_Mode_IN_FLOATING;                        //选择浮空输入模式
 22     itd.GPIO_Pin=GPIO_Pin_7;                                    //选择GPIO_Pin_7
 23     GPIO_Init(GPIOA,&itd);
 24     
 25     //AFIO映射中断引脚
 26     RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);         //使能AFIO的外设时针
 27     GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource1);  //选择外部中断源和中断通道
 28     
 29     //EXTI中断配置
 30     EXTI_InitTypeDef itd1;
 31     itd1.EXTI_Line=EXTI_Line7;                                  //echo使用的端口7,因此选择7号中断线
 32     itd1.EXTI_LineCmd=ENABLE;
 33     itd1.EXTI_Mode=EXTI_Mode_Interrupt;
 34     itd1.EXTI_Trigger=EXTI_Trigger_Rising_Falling;              //上升沿和下降沿都触发中断
 35     EXTI_Init(&itd1);
 36     
 37     //NVIC分配外部中断的中断优先级
 38     NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);             //指定中断分组
 39     NVIC_InitTypeDef itd2;
 40     itd2.NVIC_IRQChannel=EXTI9_5_IRQn;                          //使用的端口7,因此选择这个参数
 41     itd2.NVIC_IRQChannelCmd=ENABLE;
 42     itd2.NVIC_IRQChannelPreemptionPriority=2;                   //抢占优先级
 43     itd2.NVIC_IRQChannelSubPriority=2;                          //响应优先级 
 44     NVIC_Init(&itd2);
 45     
 46     //配置定时器
 47     RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
 48     TIM_TimeBaseInitTypeDef itd3;
 49     itd3.TIM_ClockDivision=TIM_CKD_DIV1;                        //使用时钟分频1
 50     itd3.TIM_CounterMode=TIM_CounterMode_Up;                    //向上计数
 51     //72MHz/72/100=1000,每秒定时器计数1000个,因此每个计数为100us
 52     itd3.TIM_Period=72-1;                                       //预分频系数
 53     itd3.TIM_Prescaler=100-1;                                   //自动重装器
 54     itd3.TIM_RepetitionCounter=0;                               //该参数仅给高级定时器使用
 55     TIM_TimeBaseInit(TIM2,&itd3);
 56     TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);                    //使能中断输出信号
 57     TIM_InternalClockConfig(TIM2);                              //选择内部时钟    
 58     
 59     //NVIC分配定时器的中断优先级
 60     NVIC_InitTypeDef itd4;
 61     itd4.NVIC_IRQChannel=TIM2_IRQn;                             //指定Tim2的中断通道
 62     itd4.NVIC_IRQChannelCmd=ENABLE;
 63     itd4.NVIC_IRQChannelPreemptionPriority=1;                   //抢占优先级
 64     itd4.NVIC_IRQChannelSubPriority=1;                          //响应优先级
 65     NVIC_Init(&itd4);
 66     
 67     uint32_t distance;
 68     while(1){
 69         distance=0;
 70         for(int i=0;i<10;++i){              //每次取10次测距数据,取平均值减少误差
 71             GPIO_SetBits(GPIOA,GPIO_Pin_6);
 72             Delay_us(15);                   //根据说明书,需要提供至少10us的高电平
 73             GPIO_ResetBits(GPIOA,GPIO_Pin_6);
 74             Delay_ms(65);                   //根据说明书,每个周期至少需要等待60ms
 75             distance+=(times/5.8);          //根据说明书提供的公式,获取单位为mm的距离
 76         }
 77         distance/=10;
 78         OLED_ShowNum(2,1,distance,4);
 79     }
 80 }
 81  
 82 //定时器中断函数
 83 void TIM2_IRQHandler(void){
 84     if(SET==TIM_GetITStatus(TIM2,TIM_FLAG_Update)){
 85         number++;                                   //每次中断将次数++
 86         TIM_ClearITPendingBit(TIM2,TIM_FLAG_Update);
 87     }
 88 }
 89  
 90 //外部中断函数
 91 void EXTI9_5_IRQHandler(void){
 92     if(SET==EXTI_GetITStatus(EXTI_Line7)){
 93         if(flag==0){
 94             //上升沿即回响电平开始,打开计数器
 95             number=0;flag=1;
 96             TIM_SetCounter(TIM2,0);
 97             TIM_Cmd(TIM2,ENABLE);
 98             
 99         }else{
100             //下降沿即回响电平结束,统计高电平持续时长
101             TIM_Cmd(TIM2,DISABLE);
102             flag=0;
103             times=number*100+TIM_GetCounter(TIM2);  //得到回响的高电平持续的us
104         }
105         EXTI_ClearITPendingBit(EXTI_Line7);
106     }
107 }

 

参考:
《HC-SR04超声波测距模块说明书》—— 深圳市捷深科技有限公司
b站江科大

STM32驱动HC-SR04超声波测距模块测距_哔哩哔哩_bilibili

完整的工程文件在这边:

链接:https://pan.baidu.com/s/1k4oXI_XNgQwquPyXXRIafQ
提取码:yvz6
————————————————
版权声明:本文转载CSDN博主「折途」的原创文章,遵循CC 4.0 BY-SA版权协议。
原文链接:https://blog.csdn.net/m0_63235356/article/details/134635107

标签:STM32F103,SR04,NVIC,TIM,GPIO,HC,测距
From: https://www.cnblogs.com/soliang/p/17870635.html

相关文章

  • HighCharts 极地图图表绘制及添加标示线+柱状图找最值
    需求:绘制极地图并给极地图图表加上标示线,在柱状图中找出最值分析:图表加上标示线在需要的轴上面用plotLines(标示线)属性来进行添加,极地图则是在chart(图表)属性里开启polar(极)属性然后进行绘制,找出最值需要在plotOptions属性里进行修改解决:源代码:示例:标示线总是垂直于它属于的轴。......
  • 华为认证 | 华为HCIE笔试一共多少道题?HCIE证书怎么查?
    HCIE证书的含金量非常高。然而,要想获得这张宝贵的证书,考生需要先通过HCIE笔试。那么,华为HCIE笔试到底有多少道题?如何查询HCIE证书呢?下面将为您一一解答。01华为HCIE笔试一共多少道题华为HCIE笔试题目数量并不是固定的,而是根据不同的考试级别和考试内容有所差异。对于HCIE-Datacom......
  • 三大存储协议介绍与存储资源盘活系统 AHCI、NVMe、SCSI
    存储协议目前主流的有三种,AHCI、NVMe、SCSI。HDD磁盘和早期SSD磁盘的传输协议一般采用AHCI(高级主机控制器接口,AdvancedHostControllerInterface)。AHCI为单队列模式,主机和HDD/SSD之间通过单队列进行数据交互。对于HDD这种慢速设备来说,主要瓶颈在存储设备,而非AHCI协议......
  • Highcharts 人口金字塔和对数折线图​
    需求人口金字塔是一种用来描述和展示人口结构的图表,可以通过设置数据源、坐标轴样式、图例等参数来自定义图表的外观和行为;对数折线图通常用于显示数据的指数增长或减少,以及数据之间的相对比较。分析柱状图人口金字塔:通过(categories)指定了过(data)指定了男性和女性在每个年龄段的数据......
  • HCIP 路由策略
    路由策略   基于FIB转发表转发报文,FIB基于IP路由表生成   路由策略,通过修改或删除路由来影响FIB转发表,实现控制设备转发报文路径       通过修改控制平面来影响数据平面   应用场景:1.过滤路由,从路由表删除发布的路由、接收的路由   ......
  • 浅谈为什么重写equals方法,就要必须重写hashcode方法
    在hashmap中是要保证key的唯一,如果新的key放入map中,发现和已有的key相同,那么就要覆盖。那么这个“唯一”是怎么确定的?或者说怎么认为两个key是相同的?那么这里的相同是指内容相同,比如newString("aaa"),newString("aaa"),new了两个字符串,是两个对象,但是内容是相同的,我们认为他们......
  • HighCharts 修改版权标识+面积图堆叠及断裂
    要使用Higcharts最快学会的方法,就是拿着官网给我们的例子,加以分析和修改。兼容IE6+、完美支持移动端、图表类型丰富的HTML5交互图表|Highcharts需求:修改图表右下角的版权标识,生成一个堆叠面积图和一个断裂面积图分析:修改版权标识用credits来进行修改,生成堆叠面积图和堆叠......
  • CaltechCS122 笔记:Assignment 2: SQL Translation and Joins
    Assignment2:SQLTranslationandJoinsTranslationandjoinPlanNode及其子类,如图所示:......
  • 什么时候会重写equals和hashcode方法
    在Java中,通常情况下,当你使用自定义类的实例作为集合的元素、键(key)或者在需要进行对象比较的场景,你可能会需要重写equals()和hashCode()方法。这两个方法在Object类中定义,但默认的实现是基于对象的内存地址,而不是基于对象的内容。通过重写这两个方法,你可以自定义对象相等性的......
  • 【Windows】DHCP部署与安全
    目录DHCP原理DHCP续约部署DHCP服务器删除DHCP服务wireshark抓取DHCP获取地址的四个步骤DHCP攻击与防御DHCP地址池耗尽攻击作用DynamicHostConfigureProtocol)自动分配IP地址相关概念地址池/作用域:(IP、子网掩码、网关、DNS、租期),DHCP协议端口是UDP67/68DHCP原理也成为DHCP......