1.前言(闲话)
众所周知传感器(transducer/sensor)是一种检测装置,能感受到被测量的信息,并能将感受到的信息,按一定规律变换成为电信号或其他所需形式的信息输出,以满足信息的传输、处理、存储、显示、记录和控制等要求。传感器在生活中无处不在,小到温湿度传感器测量温湿度,大到当今最火热的领域——物联网IoT,传感器总是发挥着重要的作用。而学习传感器也尤为重要,特别是在电子设计中。
2.HC-SR04模块介绍
1.简介 HC-SR04模块性能稳定,测度距离精确,模块高精度,盲区小。在日常生活中,以下地方都可应用超声波测距模块: (1)机器人避障 (2)物体测距 (3)液位检测 (4)公共安防 (5)停车场检测 (6)电子设计中的避障智能车也正是应用到了此模块,才能达到避开障碍的功能。 2.电气参数
电气参数 | HC-SR04超声波测距模块 |
---|
工作电压 | DC 5V | 工作电流 | 15mA | 工作频率 | 40Hz | 最远射程 | 4米 | 最近射程 | 2厘米 | 测量角度 | 15度 | 输入触发信号 | 10us的TTL脉冲 | 输出回响信号 | 输出与射程成正比的TTL电平信号 | 规格尺寸 | 40x20x15mm |
3.工作原理 第一步:通过IO口给Trig接口周期不小于10us的脉冲信号。 第二步:HC-SR04接收到单片机发来的脉冲信号后自动发送8个频率为4KHz的方波,自动检测是否有信号返回。 第三步:若有信号返回,则通过Echo接口向单片机相连的IO口发送一个高电平,高电平持续时间就是超声波从发射到返回的总时间。 假设高电平持续时间为T,声速为v(一般为340m/s),那么测到的距离S=(T*v)/2。 4.换算单位 (1)us / 58 ——>cm (2)cm / 148 ——>英寸
5.HC-SR04时序图 结合HC-SR04的时序图,其工作原理可以更好地解释。 6.实物图
3.硬件连接
1.VCC —— 5V 2.GND——GND 3.Trig ——PA0(TIM2_CH1) 4.Echo ——PA1(TIM2_CH2)
4.软件代码
hcsr04.h
#ifndef __HCSR04_H
#define __HCSR04_H
#include "sys.h"
void Hcsr04Init(void);
void TIM2_RQHandler(void);
u32 GetEchoTimer(void);
float Hcsr04GetLength(void);
#endif
hcsr04.c
#include "hcsr04.h"
#include "stm32f10x.h"
#include "sys.h"
#include "delay.h"
#define TRIG_Send PAout(0)
#define ECHO_Reci PAin(1)
u16 msHcCount = 0;
void Hcsr04Init(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
GPIO_InitTypeDef GPIO_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_ResetBits(GPIOA,GPIO_Pin_0);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_ResetBits(GPIOA,GPIO_Pin_1);
TIM_DeInit(TIM2);
TIM_TimeBaseStructure.TIM_Period = (1000-1);
TIM_TimeBaseStructure.TIM_Prescaler =(72-1);
TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);
NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
TIM_Cmd(TIM2,DISABLE);
}
static void OpenTimerForHc()
{
TIM_SetCounter(TIM2,0);
msHcCount = 0;
TIM_Cmd(TIM2, ENABLE);
}
static void CloseTimerForHc()
{
TIM_Cmd(TIM2, DISABLE);
}
void TIM2_IRQHandler(void)
{
if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET)
{
TIM_ClearITPendingBit(TIM2, TIM_IT_Update );
msHcCount++;
}
}
u32 GetEchoTimer(void)
{
u32 t = 0;
t = msHcCount*1000;
t += TIM_GetCounter(TIM2);
TIM2->CNT = 0;
delay_ms(50);
return t;
}
float Hcsr04GetLength(void)
{
u32 t = 0;
int i = 0;
float lengthTemp = 0;
float sum = 0;
while(i!=5)
{
TRIG_Send = 1;
delay_us(20);
TRIG_Send = 0;
while(ECHO_Reci == 0);
OpenTimerForHc();
i = i + 1;
while(ECHO_Reci == 1);
CloseTimerForHc();
t = GetEchoTimer();
lengthTemp = ((float)t/58.0);
sum = lengthTemp + sum ;
}
lengthTemp = sum/5.0;
return lengthTemp;
}
main.c
#include "stm32f10x.h"
#include "uart.h"
#include "delay.h"
#include "hcsr04.h"
#include "usart.h"
#include "stdio.h"
int main()
{
float length = 0;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
delay_init();
uart_init(115200);
printf("串口初始化成功!\r\n");
Hcsr04Init();
printf("HcSr04初始化成功!\r\n");
while(1)
{
length = Hcsr04GetLength();
printf("距离为 %f cm\r\n",length);
}
}
5.学习补充
补充1:利用正点原子官方模板中system中的usart.c文件里面的uart_init函数来进行串口打印距离。 但是注意,如果要想使用printf函数打印数据,必须要加入以下语句(正点原子的模板默认是加入了的),否则将无法打印数据:
#if 1
#pragma import(__use_no_semihosting)
struct __FILE
{
int handle;
};
FILE __stdout;
void _sys_exit(int x)
{
x = x;
}
int fputc(int ch, FILE *f)
{
while((USART1->SR&0X40)==0);
USART1->DR = (u8) ch;
return ch;
}
#endif
补充2:静态局部函数不需要在头文件中声明 在hcsr04.c中,使用了static void OpenTimerForHc() 和static void CloseTimerForHc() 两个局部函数,这两个局部函数只服务于hcsr04.c该文件,不需要在hcsr04.h中加以声明。 补充3.us/58——>cm换算原理 声音在干燥、摄氏 20度的空气中的传播速度大约为343米/秒,合34,300厘米/秒。或者,我们作一下单位换算,34,300除以1,000,000厘米/微秒。即为:0.0343厘米/微秒再换一个角度,1/(0.0343 厘米/微秒)即:29.15 微秒/厘米。这就意味着,每291.5微秒表示10CM的距离。1厘米就是29.15微秒。但是发送后到接收到回波,声音走过的是2倍的距离。所以实际距离就是1厘米,对应58.3微秒。实际上整个测距过程是测的发出声波到收到回波的时间,你的程序里的第一个distance实际上是时间us。所以换成距离cm,要除以58。当然除以58.3可能更精确。 该补充的参考链接
6.效果展示(可以先过来看效果)
7.参考链接
[1]百度百科 传感器 [2]博客:us/58——>cm换算原理
8.完整版代码链接
完整版代码下载链接
往期博客: 《OpenMv与Stm32单片机通信》 欢迎大家来访!
|