历史上的今天
今天是:2024年09月13日(星期五)
2021年09月13日 | 基于STM32的超声波HC-SR04详解
2021-09-13 来源:eefocus
HC-SR04基本工作原理:
(1)采用IO口TRIG触发测距,给最少10us的高电平信呈。
(2)模块自动发送8个40khz的方波,自动检测是否有信号返回;
(3)有信号返回, 通过IO口ECHO输出一个高电平, 高电平持续的时间就是超声波从发射到返回的时间。
测试距离=(高电平时间*声速(340M/S))/2。
程序编写思路是:
1、配置好使用到的GPIO以及定时器;
2、给模块TRIG端口发送大于10us的高电平信号,当收、收到ECHO回响信号是,打开定时器开始定时;
3、当回响信号消失,关闭定时器;
4、通过定时器定时时间来确定距离。
连线
1.这里,HC-SR04模块必须使用5V供电,不能是3.3V (若接3.3V,则数据出错)
2.Trig引脚我这里接GPIOB6
3.Echo引脚我这里接GPIOB7
相关代码
main.c
#include "led.h"
#include "delay.h"
#include "key.h"
#include "sys.h"
#include "usart.h"
#include "timer.h"
float Distance_Calculate(u32 count)
{
//单位cm
//v = 340m/s = 34000cm/s = 34000cm/10^6us = 0.034cm/us
//s = vt/2 = t*0.034/2 = t*0.017 ≈ t/58
float Distance = 0;
Distance = ((float)count / 58));
return Distance;
}
int main(void)
{
u32 count = 0;
float Distance = 0;
delay_init(); //延时函数初始化
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级
uart_init(115200); //串口初始化为115200
LED_Init(); //LED端口初始化
Ultrasonic_Config(); //引脚初始化
Timer2_Config(); //定时器2初始化
GPIO_SetBits(GPIOB,GPIO_Pin_5); //一开始我给它亮
LED0 = 0; //小灯指示用途
LED1 = 0;
printf("Test startn");
while(1)
{
//拉高Trig引脚10us
GPIO_ResetBits(GPIOB, GPIO_Pin_6);//预先拉低Trig引脚
GPIO_SetBits(GPIOB, GPIO_Pin_6);
delay_us(10);
GPIO_ResetBits(GPIOB, GPIO_Pin_6);//发出10us的脉冲
TIM2->CNT = 0; //计数器的值为0
while(GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_7) == 0); //等待高电平
TIM_Cmd(TIM2, ENABLE); //开启定时器
while(GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_7) == 1){} //等待低电平
TIM_Cmd(TIM2, DISABLE); //关闭定时器
count = TIM2->CNT; //获取定时器的值
printf("count = %drn",count);
//count是计数器,单位是us,可根据上图转换一下即可。
Distance = Distance_Calculate(count); //计算距离
printf("Distance = %f.", Distance);
delay_ms(500);
LED0 = !LED0;
LED1 = !LED1;
}
}
命名问题,不需要配置led
led.h
#ifndef __LED_H
#define __LED_H
#include "sys.h"
void Timer2_Config(void);
void Ultrasonic_Config(void);
led.c
void Ultrasonic_Config(void){
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6; //Trig
//GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //复用推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB,&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7; //ECHO,输入
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
//GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; //设为输入
GPIO_Init(GPIOB,&GPIO_InitStructure);
}
void Timer2_Config(void){
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
TIM_TimeBaseInitStructure.TIM_Prescaler = 71;
TIM_TimeBaseInitStructure.TIM_Period = 49999; //72*50000/72 = 50000us = 500ms.
TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStructure);
TIM_ClearFlag(TIM2,TIM_FLAG_Update); //更新产生中断
}
usart.c
void uart_init(u32 bound){
//GPIO端口设置
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA, ENABLE); //使能USART1,GPIOA时钟
//USART1_TX GPIOA.9
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //PA.9
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.9
//USART1_RX GPIOA.10初始化
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;//PA10
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.10
//Usart1 NVIC 配置
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3 ;//抢占优先级3
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //子优先级3
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能
NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化VIC寄存器
//USART 初始化设置
USART_InitStructure.USART_BaudRate = bound;//串口波特率
USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式
USART_InitStructure.USART_StopBits = USART_StopBits_1;//一个停止位
USART_InitStructure.USART_Parity = USART_Parity_No;//无奇偶校验位
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //收发模式
USART_Init(USART1, &USART_InitStructure); //初始化串口1
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启串口接受中断
USART_Cmd(USART1, ENABLE); //使能串口1
}
实验结果

说明:count是计数器
v = 340m/s,v = 0.034cm/us.
t = s/v = 400cm/0.034cm/us = 11764us
而我设置计数50000次,也就是50000us,因此,是能够测量最大距离的。
史海拾趣
|
在3月份我们在论坛搞了一个按键专题活动的讨论(https://bbs.eeworld.com.cn/viewthread.php?tid=97931 ),这个活动获得了大家的广泛支持,讨论的很是热烈根据讨论内容,从大家的讨论中,我们学习和了解到了更多的按键方面的知识。 俗话说的好: ...… 查看全部问答> |
|
各位大侠,小弟刚接触嵌入式。有些基本的问题还没有搞清楚,请教一下 在一块板子上,有sdram,nor flash,nand flash 哪个是用来存储系统的, 这3个又有什么区别呢?… 查看全部问答> |
|
C:\\Program Files\\Microsoft eMbedded C++ 4.0\\Common\\EVC\\MyProjects\\2\\2.cpp(4) : fatal error C1083: Cannot open precompiled header file: \'emulatorDbg/2.pch\': No such file or directory 随便什么程序,都是报这个错误,这是为什 ...… 查看全部问答> |
|
keil编译时,提示入下错误:(我估计不应该是程序的错误,不知道哪里没有设置正确) Build target \'Target 1\'assembling STARTUP.A51...compiling Lcd.c...C51 FATAL-ERROR - ACTION: GOBAL OPTIMIZATION ...… 查看全部问答> |
|
我收到的就一个SD卡,但带了个SD大卡卡槽。并不是传说中的,两个SD卡。 我破不急等地插到USB口上,当然迷你SD卡也插上,发现硬件。我等着自动装硬件。但显示了一个虚拟的U盘。我又傻等一会儿,还是要驱动。 应是U转串的驱动。 我查型号是FT2232H ...… 查看全部问答> |
|
主要要求:1.本系统负责对主排水泵的电压、电流、轴瓦温油温、润滑油油压、水泵真空度等一系列参数进行测量并显示。2.系统能自动根据所测量得到的参数进行综合逻辑分析,判断是否出现异常情况,并在异常情况出现时自动启动继电器接口来控制相应的节 ...… 查看全部问答> |







