005【GD32F470】HC-SR04 超声波测距模块 宽电压3-5.5V 工业级 传感器模块移植教程(有完整工程代码)

2.10 SR04超声波测距传感器
2.10.1 模块来源
采购链接:

资料下载链接:
https://pan.quark.cn/s/7c04be8b8ad6

2.10.2 规格参数
工作电压:5-5.5V
工作电流:5.3MA
感应角度:小于15度
探测距离:2CM-600CM
探测精度:0.1CM+1%
输出方式: GPIO
管脚数量:4 Pin
工作电流:5.3MA
感应角度:小于15度
探测距离:2CM-600CM
探测精度:0.1CM+1%
输出方式: GPIO
管脚数量:4 Pin

2.10.3 移植过程
我们的目标是在梁山派GD32F470上能够判断前方障碍物距离的功能。首先要获取资料,查看数据手册应如何实现,再移植至我们的工程。
2.10.3.1 查看资料

在这里插入图片描述

只需要在 Trig 管脚(触发信号)输入一个 10US 以上的高电平,系统便可发出 8 个 40KHZ 的超声波脉冲,然后检测回波信号。当检测到回波信号后,通过 Echo 管脚输出。根据 Echo 管脚输出高电平的持续时间可以计算距离值。即距离值为:(高电平时间*340m/s)/2。
当测量距离超过 HC-SR04 的测量范围时,仍会通过 Echo管脚输出高电平的信号,高电平的宽度约为 66ms。如图 6 所示:

在这里插入图片描述

测量周期:当接收到 HC-SR04 通过 Echo 管脚输出的高电平脉冲后,便可进行下一次测量,所以测量周期取决于测量距离,当距离被测物体很近时,Echo 返回的脉冲宽度较窄,测量周期 就很短;当距离被测物体比较远时,Echo 返回的脉冲宽度较宽,测量周期也就相应的变长。最坏情况下,被测物体超出超声波模块的测量范围,此时 返回的脉冲宽度最长,约为 66ms,所以最坏情况下的测量周期稍大于 66ms 即可(取 70ms 足够)。

2.10.3.2 引脚选择
实测模块的电源必须是5V!

超声波模块立创·梁山派
VCC5V
trigPC10
echoPC11
GNDGND

在这里插入图片描述

2.10.3.3 移植至工程
移植步骤中的导入.c和.h文件与上一节相同,只是将.c和.h文件更改为bsp_ultrasonic.c与bsp_ultrasonic.h。见2.2.3.3 移植至工程。这里不再过多讲述。移植完成后面修改相关代码。
在文件bsp_ultrasonic.c中,编写如下代码。

/********************************************************************************
  * 文 件 名: bsp_ultrasonic.c
  * 版 本 号: 初版
  * 修改作者: LC
  * 修改日期: 2023年04月17日
  * 功能介绍:          
  ******************************************************************************
  * 注意事项:
*********************************************************************************/

#include "bsp_ultrasonic.h"
#include "systick.h"


unsigned char msHcCount = 0;//ms计数
float distance = 0;

/******************************************************************
 * 函 数 名 称:bsp_ultrasonic
 * 函 数 说 明:超声波初始化
 * 函 数 形 参:无
 * 函 数 返 回:无
 * 作       者:LC
 * 备       注:TRIG引脚负责发送超声波脉冲串
******************************************************************/
void Ultrasonic_Init(void)
{
        // 定义定时器结构体
        timer_parameter_struct timer_initpara;          
        
        rcu_periph_clock_enable(RCU_TRIG);
    rcu_periph_clock_enable(RCU_ECHO);
    
        //设置TRIG引脚模式为推挽输出
        gpio_mode_set(PORT_TRIG, GPIO_MODE_OUTPUT, GPIO_PUPD_PULLUP, GPIO_TRIG);
        //设置引脚为推挽模式,翻转速度50MHz
        gpio_output_options_set(PORT_TRIG, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_TRIG);        
        //设置引脚输出低电平
        gpio_bit_write(PORT_TRIG, GPIO_TRIG, RESET);
        
    
        //设置echo引脚模式为浮空输入
        gpio_mode_set(PORT_ECHO, GPIO_MODE_INPUT, GPIO_PUPD_NONE, GPIO_ECHO);
        //设置引脚输出低电平
        gpio_bit_write(PORT_ECHO, GPIO_ECHO, RESET);

        /* 开启时钟 */
        rcu_periph_clock_enable(RCU_TIMER5);
        /*        将定时器时钟的频率4倍频为200MHz        */
        rcu_timer_clock_prescaler_config(RCU_TIMER_PSC_MUL4);        
        // 复位定时器
        timer_deinit(TIMER5);
        timer_initpara.period                                         = 1000-1;//定时1ms
        timer_initpara.prescaler                                 = 200-1;
        timer_initpara.clockdivision                 = TIMER_CKDIV_DIV1;     // 分频因子
        timer_initpara.alignedmode                         = TIMER_COUNTER_EDGE;         // 边缘对齐
        timer_initpara.counterdirection = TIMER_COUNTER_UP;                        // 向上计数
        
        /* 在输入捕获的时候使用 数字滤波器使用的采样频率之间的分频比例 */
        timer_initpara.clockdivision = TIMER_CKDIV_DIV1; // 分频因子
        /* 只有高级定时器才有 配置为 x,就重复 x+1 次进入中断 */
        timer_initpara.repetitioncounter = 0; // 重复计数器 0-255
        timer_init(TIMER5,&timer_initpara);         // 初始化定时器        
        /* 配置中断优先级 */
        nvic_irq_enable(TIMER5_DAC_IRQn,1,1); // 设置中断优先级为 1,1 断        
        /* 使能中断 */
        timer_interrupt_enable(TIMER5,TIMER_INT_UP); // 使能更新事件中断        
        /* 使能定时器 */
        timer_enable(TIMER5);
}

/******************************************************************
 * 函 数 名 称:TIMER5_DAC_IRQHandler
 * 函 数 说 明:定时器5的中断服务函数
 * 函 数 形 参:无
 * 函 数 返 回:无
 * 作       者:LC
 * 备       注:1ms中断一次
******************************************************************/
void TIMER5_DAC_IRQHandler(void)
{
        static int i = 0;
        if( timer_interrupt_flag_get(TIMER5, TIMER_INT_UP) != RESET )
        {
                msHcCount++;
                timer_interrupt_flag_clear(TIMER5,TIMER_INT_UP);
        }
}

/******************************************************************
 * 函 数 名 称:OpenTimer
 * 函 数 说 明:打开定时器
 * 函 数 形 参:无
 * 函 数 返 回:无
 * 作       者:LC
 * 备       注:无
******************************************************************/
static void OpenTimer(void) //
{
  /*清除计数器*/
        timer_counter_value_config(TIMER5,0);
        msHcCount = 0;
        timer_enable(TIMER5);//使能定时器
}
 /******************************************************************
  * 函 数 名 称:CloseTimer
  * 函 数 说 明:关闭定时器
  * 函 数 形 参:无
  * 函 数 返 回:无
  * 作       者:LC
  * 备       注:无
 ******************************************************************/
static void CloseTimer(void)
{
  /*关闭计数器使能*/
        timer_disable(TIMER5);
}
 
/******************************************************************
 * 函 数 名 称:GetEchoTimer
 * 函 数 说 明:获取定时器时间
 * 函 数 形 参:无
 * 函 数 返 回:返回获取到的时间
 * 作       者:LC
 * 备       注:无
******************************************************************/
unsigned int GetEchoTimer(void)
{
   unsigned int time = 0;
        /*//当回响信号很长是,计数值溢出后重复计数,overCount用中断来保存溢出次数*/
        time = msHcCount*1000;//overCount每++一次,代表overCount毫秒,time微妙
        time += timer_counter_read(TIMER5);//获取计TIM5数寄存器中的计数值,一边计算回响信号时间
        timer_counter_value_config(TIMER5,0);//将TIM2计数寄存器的计数值清零
        delay_1ms(10);
        return time;
}

/******************************************************************
 * 函 数 名 称:Hcsr04GetLength
 * 函 数 说 明:获取测量距离
 * 函 数 形 参:无
 * 函 数 返 回:测量距离
 * 作       者:LC
 * 备       注:无
******************************************************************/
float Hcsr04GetLength(void)
{
        /*测5次数据计算一次平均值*/
        float length = 0;
        float t = 0;
        float sum = 0;
        unsigned int  i = 0;
        while(i != 5){
                        gpio_bit_write(PORT_TRIG, GPIO_TRIG, SET);//trig拉高信号,发出高电平

                delay_1us(20);//持续时间超过10us
                gpio_bit_write(PORT_TRIG, GPIO_TRIG, RESET);//trig拉低信号,发出低电平
                /*Echo发出信号 等待回响信号*/
                /*输入方波后,模块会自动发射8个40KHz的声波,与此同时回波引脚(echo)端的电平会由0变为1;
                (此时应该启动定时器计时);当超声波返回被模块接收到时,回波引 脚端的电平会由1变为0;
                (此时应该停止定时器计数),定时器记下的这个时间即为
                        超声波由发射到返回的总时长;*/
                
                while(gpio_input_bit_get(PORT_ECHO, GPIO_ECHO) == 0);//echo等待回响
                /*开启定时器*/
                OpenTimer();
                i = i+1; //每收到一次回响信号+1,收到5次就计算均值
                while(gpio_input_bit_get(PORT_ECHO, GPIO_ECHO) == 1);
                /*关闭定时器*/
                CloseTimer();
                /*获取Echo高电平时间时间*/
                t = GetEchoTimer();
                length = (float)t/58;//单位时cm
                sum += length;                
        }
        length = sum/5;//五次平均值
        distance = length;
        return length;
}

/******************************************************************
 * 函 数 名 称:Get_distance
 * 函 数 说 明:返回测量后的距离;必须先采集有超声波数据
 * 函 数 形 参:无
 * 函 数 返 回:上一次测量过的距离
 * 作       者:LC
 * 备       注:无
******************************************************************/
float Get_distance(void)
{
        return distance;
}

在文件bsp_ultrasonic.h中,编写如下代码。

#ifndef _BSP_ULTRASONIC_H_
#define _BSP_ULTRASONIC_H_

#include "gd32f4xx.h"

#define RCU_TRIG RCU_GPIOC
#define PORT_TRIG GPIOC
#define GPIO_TRIG GPIO_PIN_10

#define RCU_ECHO RCU_GPIOC
#define PORT_ECHO GPIOC
#define GPIO_ECHO GPIO_PIN_11

void Ultrasonic_Init(void);//超声波初始化
float Hcsr04GetLength(void );//获取超声波测距的距离
float Get_distance(void);//获取上一次测距的距离

#endif


2.4.4 移植验证
在自己工程中的main主函数中,编写如下。

【完整代码资料见:https://pan.quark.cn/s/7c04be8b8ad6

移植现象:距离20CM处摆放障碍物,输出换算后的实际距离。

在这里插入图片描述
移植成功示例:
【完整代码资料见:https://pan.quark.cn/s/7c04be8b8ad6

GD32F470I-EVAL是一款基于GD32F470芯片的开发板。对于GD32F470I-EVAL的资料和使用说明,你可以参考GD32F4xxDemoSuites的开发板资料,可以在E:\development\GD32\开发板资料\GD32F4xxSeries\GD32F4xx_Demo_Suites_V2.6.1\GD32470Z_EVAL_Demo_Suites\Docs\Schematic位置找到电路板资料。此外,你还可以查阅GD32系列的用户手册,该手册详细地说明了GD32各个功能部件的信息以及使用方法。在Keil上开发GD32F470I-EVAL,你可以使用GD32的库进行开发。如果你需要搭建一个GD32工程模板,可以参考相关的开发板资料和用户手册,根据你的需求进行相应的配置和编程。希望这些资料能够帮助你完成GD32F470I-EVAL的开发工作。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [gd32f470总结](https://blog.csdn.net/wzgxhzdd/article/details/127885289)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 50%"] - *2* *3* [GD32F450I-EVAL学习准备工作](https://blog.csdn.net/qq_63759726/article/details/127141869)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值