【STM32cubeMX+HAL库】US100超声波模块原理篇

【STM32cubeMX+HAL库】US100超声波模块的使用

1、原理简介

US-100超声波测距模块可实现2cm4.5m的非接触测距功能,拥有2.45.5V的宽电压输入范围,静态功耗低于2mA,自带温度传感器对测距结果进行校正,同时具有GPI0,串口等多种通信方式,内带看门狗,工作稳定可靠。

2、电气参数

电气参数US-100超声波测距模块
工作电压DC2.4V5.5V
静态电流2mA
工作温度20w+70度
输出方式电平或UART(跳线帽选择)
感应角度小于15度
探测距离2cm-450cm
探测精度0.3cm+1%
UART模式下串口配置波特率9600,起始位1位,停止位1位,数据位8位,无奇偶校验,无流控制

3、接口说明

本模块共有两个接口,即模式选择跳线和5Pin接口。模式选择跳线的间距为2.54mm,当插上跳线帽时为UART(串口模式,拔掉时为电平触发模式。
从左到右依次编号1,2,3,4,5。它们的定义如下:
1号Pin:接VCC电源(供电范围2.4V~5.5V)
2号Pin:当为UART模式时,接外部电路UART的TX端;当为电平触发模式 时,接外部电路的Trig端
3号Pin:当为UART模式时,接外部电路UART的RX端;当为电平触发模式 时,接外部电路的Echo端。
4号Pin:接外部电路的地。(接一个就行)
5号Pin:接外部电路的地。

在这里插入图片描述

4、产品尺寸

在这里插入图片描述
在这里插入图片描述

5、 IO模式(电平模式)

在模块上电前,首先去掉模式选择跳线上的跳线帽,使模块处于电平触发模式。电平触发测距的时序如下图所示:
在这里插入图片描述

US-100测距时序图表明:只需要在Trig/TX管脚输入一个10US以上的高电平,系统便可发出8个40KHZ的超声波脉冲,然后检测回波信号。当检测到回波信号后,模块还要进行温度值的测量,然后根据当前温度对测距结果进行
校正,将校正后的结果通过Echo/RX管脚输出。在此模式下,模块将距离值转化为340m/s时的时间值的2倍,通过Echo端输出一高电平,可根据此高电平的持续时间来计算距离值。即距离值为:(高电平时间*340m/s)/2。注:因为距离值经经过温度校正,此时无需再根据环境温度对超声波声速进行校正,即不管温度多少,声速选择340/s即可

6、UART串口模式

6.1、UART串口模式测距

在模块上电前,首先插上模式选择跳线上的跳线帽,使模块处于串口
触发模式。
在这里插入图片描述
在此模式下只需要在Trig/TX管脚输入0X55(波特率9600),系统便
可发出8个40KHZ的超声波脉冲,然后检测回波信号。当检测到回波信
号后,模块还要进行温度值的测量,然后根据当前温度对测距结果进
行校正,将校正后的结果通过Echo/RX管脚输出。
输出的距离值共两个字节,个字节是距离的高8位(HDate),第二个
字节为距离的低8位(LData),单位为毫米。即距离值为(HData*256+
LData)mm。

6.2、UART串口模式测温

在模块上电前,首先插上模式选择跳线上的跳线帽,使模块处于串口
触发模式。
在这里插入图片描述
在此模式下只需要在Trig/TX管脚输入0X50(波特率9600),系统便
启动温度传感器对当前温度进行测量,然后将温度值通过Echo/RX管
脚输出。
测量完成温度后,本模块会返回一个字节的温度值(TData),实际
的温度值为TData-45。例如通过TX发送完0X50后,在RX端收到0X45,
则此时的温度值为[69(0X45的10进制值)-45]=24度。

7、STM32cubeMX配置

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

8、程序篇(未完篇)

8.1、 IO模式测距(电平模式)

8.2、定时器输入捕获模式 IO模式测距

搞这个首先吐槽一下这杜邦线,是真的拉,从硬件到软件检查了十几遍,没想到是杜邦线出了问题,建议同学们学习一个模块可以立创EDA自己画个板子,直接插上去,避免这种低级错误!
言归正传,超声波定时器输入捕获模式 IO模式测距的原理就是IO测距的原理,只不过将IO模式下的while(ECNO ==0)变成了HAL_TIM_ReadCapturedValue()而已。大同小异。会这种方式,第一种简单的不要不要的,首先还是编程思路:
开启定时器中断,中断使能,以确保能够进行输入捕获,给TRIG一个高电平,时间大于10US,然后拉低,如果正常,则会触发两种回调,一种中断溢出回调,一种捕获回调
中断溢出:
当计时到达我们预设的装载值时,就会产生溢出,我们本次实验是65535,当到达这个值时,会触发中断溢出,我们可以进行的操作时计数,就是看他离触发捕获回调一共产生了多少个中断溢出,

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
    if (TIM2 == htim->Instance) 
    {
        tim_capture_overflow_count++;
    }
}

捕获回调函数:
就是收到了信号,因为ECNO引脚我们设置为输入捕获状态,当其引脚电平变化时,就会触发该回调
逻辑与(&&)的作用是确定定时器和通道正确。

void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
/* void US100_Capture_Cb(TIM_HandleTypeDef *htim)//这个函数是自己注册的,也可以使用HAL_TIM_RegisterCallback(&htim2, HAL_TIM_IC_CAPTURE_CB_ID, US100_Capture_Cb)进行注册一个自己定义的回调,都一样*/
{ 
    // printf("US100_Capture_Cb\r\n");

    if (( htim->Instance== TIM2) && (htim->Channel == HAL_TIM_ACTIVE_CHANNEL_4))
    {
        switch (tim_capture_cnt)
        {
            case 1:
            {
                // printf("case 1\r\n");
                capture_Buf[0] = HAL_TIM_ReadCapturedValue(&htim2, TIM_CHANNEL_4);//捕获到上升沿,获取第一个时间节点
                
                __HAL_TIM_SET_CAPTUREPOLARITY(&htim2, TIM_CHANNEL_4, TIM_ICPOLARITY_FALLING); // 清除上一次的捕获极性,并设置为下降沿捕获
                tim_capture_cnt++;
                tim_capture_overflow_count = 0;//清除溢出值
                break;

            } 
            
            case 2:
            {   
                // printf("case 2\r\n");
                capture_Buf[1] = HAL_TIM_ReadCapturedValue(&htim2, TIM_CHANNEL_4); // 获取第二个时间节点.
               
                
                // HAL_TIM_IC_Stop_IT(&htim2, TIM_CHANNEL_4);

                us100_rev_flag  = 1;// 标志位为1,则为接收到了正确的数据
                tim_capture_cnt = 0;//case值记为零
                
                break;
            }
        }
    }
}

然后就是计算高电平时间:

float US100_High_Time(void)
{
    uint16_t length;
    capture_Buf[1] = capture_Buf[1] + tim_capture_overflow_count*65536;//加上溢出值
    high_time[0] = capture_Buf[1] - capture_Buf[0];

    //high_time[0]是微秒,先化为秒,high_time[0]/1000000,再通过公式计算距离,high_time[0]/1000000*340/2=Value (m/s),可以再乘以100,就是(cm/s)
    length = (high_time[0])*34000/2000000.0;
    return length;
}

在TIMz.c文件中,要使能中断

void MX_TIM2_Init(void)
{

  /* USER CODE BEGIN TIM2_Init 0 */

  /* USER CODE END TIM2_Init 0 */

  TIM_MasterConfigTypeDef sMasterConfig = {0};
  TIM_IC_InitTypeDef sConfigIC = {0};

  /* USER CODE BEGIN TIM2_Init 1 */

  /* USER CODE END TIM2_Init 1 */
  htim2.Instance = TIM2;
  htim2.Init.Prescaler = 71;
  htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim2.Init.Period = 65535;
  htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;
  if (HAL_TIM_IC_Init(&htim2) != HAL_OK)
  {
    Error_Handler();
  }
  sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != HAL_OK)
  {
    Error_Handler();
  }
  sConfigIC.ICPolarity = TIM_INPUTCHANNELPOLARITY_RISING;
  sConfigIC.ICSelection = TIM_ICSELECTION_DIRECTTI;
  sConfigIC.ICPrescaler = TIM_ICPSC_DIV1;
  sConfigIC.ICFilter = 0;
  if (HAL_TIM_IC_ConfigChannel(&htim2, &sConfigIC, TIM_CHANNEL_4) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN TIM2_Init 2 */

    // HAL_TIM_Base_Start_IT(&htim2);
    
    HAL_TIM_IC_Start_IT(&htim2, TIM_CHANNEL_4);
    __HAL_TIM_SET_CAPTUREPOLARITY(&htim2, TIM_CHANNEL_4, TIM_INPUTCHANNELPOLARITY_RISING); 
  
  /* USER CODE END TIM2_Init 2 */

}

main函数中:

 while (1)
    {
        if (us100_rev_flag == 1)
        {
            us100_rev_flag = 0;
            tim_capture_cnt++;

            printf("Lengh:%.2fcm\r\n", US100_High_Time());

            memset(high_time, 0, HIRG_TIME_LEN);
            US100_Start();
            __HAL_TIM_SET_CAPTUREPOLARITY(&htim2, TIM_CHANNEL_4, TIM_INPUTCHANNELPOLARITY_RISING);
        }
        /* USER CODE END WHILE */

        /* USER CODE BEGIN 3 */
    }
    /* USER CODE END 3 */
}

bsp_us100.h中

/*
 * @Author: MBW
 * @Date: 2023-04-14 11:00:56
 * @LastEditors: MBW
 * @LastEditTime: 2023-04-14 18:06:09
 * @FilePath: \stm32f103rct6_us100_tset\bsp\inc\bsp_us100.h
 * @Description: 
 * 
 * Copyright (c) 2023 by MBW, All Rights Reserved. 
 */
#ifndef  __BSP_US100_H__
#define __BSP_US100_H__

#include "main.h"
#include "tim.h"
#include "usart.h"

#define HIRG_TIME_LEN   1
extern uint16_t tim_capture_cnt;            //溢出次数
extern uint8_t  us100_rev_flag;             //接收标志位
extern uint16_t capture_Buf[3];             //存放计数值
extern uint16_t high_time[HIRG_TIME_LEN];   //高电平时间

#define TRIG_HIGH   HAL_GPIO_WritePin(TRIG_GPIO_Port, TRIG_Pin, GPIO_PIN_SET)
#define TRIG_LOW    HAL_GPIO_WritePin(TRIG_GPIO_Port, TRIG_Pin, GPIO_PIN_RESET)


void US100_Start(void);
float US100_High_Time(void);

#endif // ! __BSP_US100_H__

bsp_us100.c

/*
 * @Author: MBW
 * @Date: 2023-04-14 11:01:04
 * @LastEditors: MBW
 * @LastEditTime: 2023-04-14 23:44:38
 * @FilePath: \stm32f103rct6_us100_tset\bsp\src\bsp_us100.c
 * @Description:
 *
 * Copyright (c) 2023 by MBW, All Rights Reserved.
 */
#include "bsp_us100.h"
#include "bsp_delay.h"

// high_time = tim_capture_cnt*65536+tim_capture_val

uint16_t tim_capture_cnt = 0;                   // 计数
uint16_t tim_capture_overflow_count = 0;        //溢出值
uint8_t us100_rev_flag = 0;                     // 接收标志位
uint16_t capture_Buf[3] = {0};                  // 存放计数值
uint16_t high_time[HIRG_TIME_LEN];              // 高电平时间

void US100_Start(void);
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim);
void US100_Capture_Cb(TIM_HandleTypeDef *htim);
float US100_High_Time(void);




void US100_Start(void)
{
    TRIG_LOW;
    HAL_Delay(1);
    TRIG_HIGH;
    HAL_Delay(1);
    TRIG_LOW;
    // HAL_TIM_RegisterCallback(&htim2, HAL_TIM_IC_CAPTURE_CB_ID, US100_Capture_Cb);
}

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
    if (TIM2 == htim->Instance)
    {
        tim_capture_overflow_count++;
    }
}

void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
// void US100_Capture_Cb(TIM_HandleTypeDef *htim)
{ 

    if (( htim->Instance== TIM2) && (htim->Channel == HAL_TIM_ACTIVE_CHANNEL_4))
    {
        switch (tim_capture_cnt)
        {
            case 1:
            {
                // printf("case 1\r\n");
                capture_Buf[0] = HAL_TIM_ReadCapturedValue(&htim2, TIM_CHANNEL_4);//捕获到上升沿,获取第一个时间节点
                
                __HAL_TIM_SET_CAPTUREPOLARITY(&htim2, TIM_CHANNEL_4, TIM_ICPOLARITY_FALLING); // 清除上一次的捕获极性,并设置为下降沿捕获
                tim_capture_cnt++;
                tim_capture_overflow_count = 0;//清除溢出值
                break;

            } 
            
            case 2:
            {   
                // printf("case 2\r\n");
                capture_Buf[1] = HAL_TIM_ReadCapturedValue(&htim2, TIM_CHANNEL_4); // 获取第二个时间节点.
                us100_rev_flag  = 1;// 标志位为1,则为接收到了正确的数据
                tim_capture_cnt = 0;//case值记为零
                
                break;
            }
        }
    }
}

float US100_High_Time(void)
{
    uint16_t length;
    capture_Buf[1] = capture_Buf[1] + tim_capture_overflow_count*65536;//加上溢出值
    high_time[0] = capture_Buf[1] - capture_Buf[0];

    length = (high_time[0])*34000/2000000.0;
    return length;
}

8.3、UART串口模式测距

8.4、UART串口模式测温

  • 4
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值