目录
一、模块介绍(个人理解)
1.简单理解
2.该模块的参数
二、HC-SR04的操作
三、代码
1.代码前的注意事项
2.关键代码
四、代码实战效果图
五、结束
一、模块介绍(个人理解)
1.简单理解
HC-SR04是一个超声波测距模块,通过发出超声波然后接收超声波,利用这个往返时间算出距离的模块。
HC-SR04模块 (实物图)
2.该模块的参数
参数图
二、HC-SR04的操作
HC-SR04的操作相对其他模块来说还是很简单的。首先该模块有四个口VCC、Gnd、Trig、Echo,并不多。在模块工作的时候,先要给Trig口拉高电平至少10us,然后Echo口会返回一个高电平信号,同时发射超声波。在HC-SR04接收到发出去反射回来的声波后,会给一个低电平。至此,一次检测就完成了。我们可以用定时器在发射声波时开始计数,等到接收声波后,停止计数。这样我们就有了时间。但是这个是往返时间,我们要除2,声音的传播速度时340m/s(这里暂时不考虑其他因素的影响)。有了时间和速度,路程就可以算出来了。我的代码会有详细的介绍,这部分内容。
三、代码
1.代码前的注意事项
1) 如果你的HC-SR04不能够回应你的单片机发送的信号,可能就是该模块有问题。
2)下面代码我是看了很多博主的,才写下来的,相对来说比较简单。移植性比较好,没 有在文件外定义有什么变量。
3)本人用stm32单片机的,型号是stm32f103c8t6 。
4)代码的解释非常详细,可以结合上面的操作过程看。特别是在操作模块的那个函数的代码。
5)代码在计算阶段并没有对(温度等)影响做修正,也没有取多次距离再取平均数。大家可以自己加上去,毕竟这个是最低门槛的写法了。
2.关键代码
HC-SR04.h
#ifndef _HC_SR04_H
#define _HC_SR04_H
uint32_t Get_Timer(void);
static void OpenTIM2();
static void CloseTIM2();
void HC_SR04_Init();
void HC_SR04_GPIO_Init();
void HC_SR_04_TIME_NVIC_Init();
float Get_Length();
#endif
HC-SR04.c
#include "stm32f10x.h"
#include "Delay.h"
#include "OLED.h"
#define RCC_GPIO RCC_APB2Periph_GPIOB
#define GPIOx GPIOB
#define trigGPIO GPIO_Pin_6
#define echoGPIO GPIO_Pin_7
//给毫秒ms计数
uint16_t count = 0;
//GPIO口的初始化
void HC_SR04_GPIO_Init(){
//定义结构体
GPIO_InitTypeDef GPIO_InitStruct;
//开启GPIOB RCC时钟
RCC_APB2PeriphClockCmd(RCC_GPIO,ENABLE);
//对结构体成员赋值
//发送GPIOB6 模式为推挽输出 trig
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStruct.GPIO_Pin = trigGPIO;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_ResetBits(GPIOx,trigGPIO); //设置默认为低电平 高电平会触发HC-SR发射超声波
GPIO_Init(GPIOx,&GPIO_InitStruct);
//返回GPIOB7 模式设置为浮空输入(因为该GPIO口需要被外设改变电平)
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_InitStruct.GPIO_Pin = echoGPIO;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_ResetBits(GPIOx,echoGPIO); //设置默认低电平
//初始化GPIO外围设备 echo
GPIO_Init(GPIOx,&GPIO_InitStruct);
}
//初始化定时器
void HC_SR_04_TIME_NVIC_Init(){
//定义定时器的结构体
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
//NVIC结构体
NVIC_InitTypeDef NVIC_InitStructure;
//开启TIM2
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
//将TIMx外围寄存器反初始化为其默认重置值。
TIM_DeInit(TIM2);
//设置在下一个更新事件装入活动的自动重装载寄存器周期的值,计数到1000为1ms
TIM_TimeBaseInitStructure.TIM_Period = 1000-1;
//设置用来作为TIMx时钟频率除数的预分频值 1M的计数频率 1US计数
TIM_TimeBaseInitStructure.TIM_Prescaler =72-1;
//不分频
TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1;
//TIM向上计数模式
TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
//根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx TimeBase Unit外设
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure);
//打开定时器的更新中断
TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
//选择串口1中断
NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
//抢占式中断优先级设置为1
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
//响应式中断优先级设置为1
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
//使能中断
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
//先关掉定时器,先不让它计时
TIM_Cmd(TIM2,DISABLE);
}
void HC_SR04_Init(){
HC_SR04_GPIO_Init();
HC_SR_04_TIME_NVIC_Init();
}
//打开定时器
static void OpenTIM2()
{
TIM_SetCounter(TIM2,0); //清除计数
count = 0;
TIM_Cmd(TIM2, ENABLE); //使能TIM2外设
}
//关闭定时器
static void CloseTIM2()
{
TIM_Cmd(TIM2, DISABLE); //使能TIM2外设
}
//TIM2定时器的中断函数
void TIM2_IRQHandler(void)
{
//检查是否是更新中断位
if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET)
{
//清除标志位 清除TIMx的中断挂起位
TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
count++;
}
}
//获取定时器时间
uint32_t Get_Timer(void)
{
uint32_t t = 0;
//此处t为us
t = count*1000;
//TIM_GetCounter 获取TIM2计数器值
t += TIM_GetCounter(TIM2);
//将TIM2计数寄存器的计数值清零
TIM2->CNT = 0;
delay_ms(50);
return t;
}
float Get_Length(){
//存储时间
float t = 0,length = 0;
// 1. 先将trig置位(设置为高电平)
GPIO_SetBits(GPIOx,trigGPIO);
// 2. 持续时间至少要10us 这里我就给20了
Delay_us(20);
// 3. 然后需要将trig位清零(也就是设置为低电平)
GPIO_ResetBits(GPIOx,trigGPIO);
// 4. 等待 HC-SR04 将echo置位(也就是高电平),如果置位了就开始发出声波了,我们要开始计时
// 这里用GPIO_ReadInputDataBit 是读取GPIO的输入
while (GPIO_ReadInputDataBit(GPIOx,echoGPIO) == RESET){
};
// 5. 打开定时器 开始计时
OpenTIM2();
// 6. 等待 HC-SR04 将echo清零(也就是低电平),如果清零了就是收到了声波
while (GPIO_ReadInputDataBit(GPIOx,echoGPIO) == SET);
// 7. 关闭定时器 停止计时
CloseTIM2();
// 8. 获取时间,因为是us(微秒),我们要转化为ms(毫秒)所以除1000
t = Get_Timer() / 1000.0;
// 9. 计算长度cm(厘米)
// 声音在空气中传播的速度是340m/s,我们转换一下就是 34cm/ms
length = t*34.0;
// 10. 返回长度,因为是一个往返我们要除2
return length/2;
}
main.c
#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "OLED.h"
#include "HC_SR04.h"
// 不需要的头文件就不用就好了
int main(void)
{
float length = 0;
OLED_Init();
HC_SR04_Init();
while (1)
{
OLED_ShowString(1, 1, "kiana");
length = Get_Length();
Delay_ms(500);
OLED_ShowSignedNum(2,1,length,3);
}
}
四、代码实战效果图
这里对齐不好固定,我就大概来一下大概的了哦。
效果图文章来源:https://www.toymoban.com/news/detail-597566.html
五、结束
为了美好的明天继续奋斗吧!文章来源地址https://www.toymoban.com/news/detail-597566.html
到了这里,关于HC-SR04超级简单教程(快速入门)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!