HC-SR04 超声波测距模块
一、基本工作原理
1.主控板先向Trig控制端输入至少10us的高电平触发信号,
2.该模块内部将发送出8个40KHz的方波并检测回波信号,
3.一旦检测到有回波信号则Echo接收端输出高电平回响信号,高电平的持续时间就是超声波从发射到返回的时间。(回响信号的脉冲宽度与所测的距离成正比)
4.公式:距离=高电平时间*声速(340M/S)/2
二、HC-SR04图片
三、驱动原理及程序
方法一:
在向Trig控制端发送触发信号后,等待Echo引脚响应后(上升沿或者下降沿)触发外部中断,开启定时器计时直到Echo引脚变为低电平,关闭定时器记录下计时时间,在通过公式进行计算出具体距离。
程序
超声波引脚配置
hc-sr04.c
#include "hc-sr04.h"
#include "tim.h"
#include "delay.h"
#include "Printf.h"
/*2020.11.16
* HC-SR04超声波测距模块
* 基本工作原理:* 给TRIG引脚至少10us的高电平信号触发测距
* 模块自动发送8个40KHz的方波,自动检测是否有信号返回
* 有信号返回,通过Echo引脚输出一个高电平,高电平的持续时间就是超声波从发射到返回的时间
* 测量距离 = (高电平的持续时间 * 声速(340m/s))/ 2
*/
#define HC_SR04_TRIG_CLK RCC_APB2Periph_GPIOA //脉冲触发TRIG端口
#define HC_SR04_TRIG_PORT GPIOA
#define HC_SR04_TRIG_PIN GPIO_Pin_4
#define HC_SR04_ECHO_CLK RCC_APB2Periph_GPIOA //回波接收ECHO端口
#define HC_SR04_ECHO_PORT GPIOA
#define HC_SR04_ECHO_PIN GPIO_Pin_5
float Distance; //测的距离值
//HC_SR04超声波初始化
void HC_SR04_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
EXTI_InitTypeDef EXTI_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB2PeriphClockCmd(HC_SR04_TRIG_CLK, ENABLE); //使能PA端口时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);//外部中断,需要使能AFIO时钟
GPIO_InitStructure.GPIO_Pin = HC_SR04_TRIG_PIN; // 脉冲触发端口(Trig)配置PA4
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //IO口速度为50MHz
GPIO_Init(HC_SR04_TRIG_PORT, &GPIO_InitStructure); //根据设定参数初始化端口
GPIO_InitStructure.GPIO_Pin = HC_SR04_ECHO_PIN; // 回波接收端口(Echo)配置PA5
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; //上拉输入
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //IO口速度为50MHz
GPIO_Init(HC_SR04_ECHO_PORT, &GPIO_InitStructure); //根据设定参数初始化端口
//接收端口 中断线以及中断初始化配置
GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource5);
EXTI_InitStructure.EXTI_Line=EXTI_Line5;
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;//上升沿触发
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure); //根据EXTI_InitStruct中指定的参数初始化外设EXTI寄存器
NVIC_InitStructure.NVIC_IRQChannel = EXTI9_5_IRQn; //使能按键所在的外部中断通道
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02; //抢占优先级2,
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x01; //子优先级1
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能外部中断通道
NVIC_Init(&NVIC_InitStructure);
TIM3_Int_Init(49999,7199); //初始化TIM3定时器,计数一次为1/10000S(0.1ms)
}
//发送20us的脉冲触发信号
void HC_SR04_start(void)
{
GPIO_SetBits(HC_SR04_TRIG_PORT,HC_SR04_TRIG_PIN); //TRIG置高
delay_us(20);
GPIO_ResetBits(HC_SR04_TRIG_PORT,HC_SR04_TRIG_PIN); //TRIG置低
delay_ms(10);
}
void EXTI9_5_IRQHandler(void)
{
delay_us(10);
if(EXTI_GetITStatus(EXTI_Line5) != RESET) //检测外部中断触发5请求是否发生
{
//while(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_5) == RESET);
TIM_SetCounter(TIM3,0); //计数清零
TIM_Cmd(TIM3,ENABLE); //使能TIM3定时器
while(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_5)); //等待电平变为低电平
TIM_Cmd(TIM3,DISABLE); //关闭定时器
//获取TIM3计数器的值
Distance = TIM_GetCounter(TIM3)* 340/200.0; //计算距离:cnt * 1/10000 * 340 / 2(单位:m)
//printf("Counter:%d\n",TIM_GetCounter(TIM3));
printf("测的距离: %f cm \r\n",Distance);
EXTI_ClearITPendingBit(EXTI_Line5); //清除 EXTI 线路挂起位
}
}
hc-sr04.h
#include "sys.h"
//HC_SR04超声波初始化
void HC_SR04_Init(void);
//发送20us的脉冲触发信号
void HC_SR04_start(void);
float Senor_Using(void);
main.c
#include "sys.h"
#include "delay.h"
#include "hc-sr04.h"
#include "usart.h"
#include "Printf.h"
#include "tim.h"
int main(void)
{
RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK); //系统时钟设置PLL作为系统时钟
delay_init(); //初始化延时函数
uart_init(115200);
printf("开始测量距离\r\n");
/*Echo引脚需要接收并记录高电平的持续时间。
在发送触发信号后,Echo响应后(上升沿)触发外部中断,
开启定时器计时直到Echo变为低电平,
关闭定时器记录下计时时间*/
HC_SR04_Init(); //HC_SR04超声波初始化配置
HC_SR04_start(); //发送20us的脉冲触发信号
//while(1);
}
串口通信程序自己添加一下吧,我这就不添加了