一、超声波HC_SR04简介
超声波传感器模块上面通常有两个超声波元器件,一个用于发射,一个用于接收。
电路板上有四个引脚:VCC、GND、Trig(触发)、Echo(回应)。
工作电压与电流:5V,15mA
感应距离:2~400cm
感测角度:不小于15度
被测物体的面积不要小于50平方厘米并且尽量平整
具备温度补偿电路
二、超声波原理
距离公式:
高电平持续时间*声速(340m/s)/2
三、超声波测距步骤
- 配置GPIO引脚结构体(Trig,Echo)
- 配置定时器4结构体
- 配置定时器4中断结构体
- 开启时钟(定时器、GPIO)
- Trig引脚输出高电平(10us以上),然后关闭
- 等待Echo引脚输出高电平开始,定时器打开->开启计数器计数
- 等待Echo引脚输出高电平结束,定时器关闭->停止计数器计数
四、硬件接线
- GND——GND
- VCC——5V
- Trig——PB11
- Echo——PB10
五、模块化程序
#ifndef __SYS_H
#define __SYS_H
#include "stm32f10x.h"
#define SYSTEM_SUPPORT_UCOS 0
#define BITBAND(addr, bitnum) ((addr & 0xF0000000)+0x2000000+((addr &0xFFFFF)<<5)+(bitnum<<2))
#define MEM_ADDR(addr) *((volatile unsigned long *)(addr))
#define BIT_ADDR(addr, bitnum) MEM_ADDR(BITBAND(addr, bitnum))
#define GPIOA_ODR_Addr (GPIOA_BASE+12) //0x4001080C
#define GPIOB_ODR_Addr (GPIOB_BASE+12) //0x40010C0C
#define GPIOC_ODR_Addr (GPIOC_BASE+12) //0x4001100C
#define GPIOD_ODR_Addr (GPIOD_BASE+12) //0x4001140C
#define GPIOE_ODR_Addr (GPIOE_BASE+12) //0x4001180C
#define GPIOF_ODR_Addr (GPIOF_BASE+12) //0x40011A0C
#define GPIOG_ODR_Addr (GPIOG_BASE+12) //0x40011E0C
#define GPIOA_IDR_Addr (GPIOA_BASE+8) //0x40010808
#define GPIOB_IDR_Addr (GPIOB_BASE+8) //0x40010C08
#define GPIOC_IDR_Addr (GPIOC_BASE+8) //0x40011008
#define GPIOD_IDR_Addr (GPIOD_BASE+8) //0x40011408
#define GPIOE_IDR_Addr (GPIOE_BASE+8) //0x40011808
#define GPIOF_IDR_Addr (GPIOF_BASE+8) //0x40011A08
#define GPIOG_IDR_Addr (GPIOG_BASE+8) //0x40011E08
#define PAout(n) BIT_ADDR(GPIOA_ODR_Addr,n) //Êä³ö
#define PAin(n) BIT_ADDR(GPIOA_IDR_Addr,n) //ÊäÈë
#define PBout(n) BIT_ADDR(GPIOB_ODR_Addr,n) //Êä³ö
#define PBin(n) BIT_ADDR(GPIOB_IDR_Addr,n) //ÊäÈë
#define PCout(n) BIT_ADDR(GPIOC_ODR_Addr,n) //Êä³ö
#define PCin(n) BIT_ADDR(GPIOC_IDR_Addr,n) //ÊäÈë
#define PDout(n) BIT_ADDR(GPIOD_ODR_Addr,n) //Êä³ö
#define PDin(n) BIT_ADDR(GPIOD_IDR_Addr,n) //ÊäÈë
#define PEout(n) BIT_ADDR(GPIOE_ODR_Addr,n) //Êä³ö
#define PEin(n) BIT_ADDR(GPIOE_IDR_Addr,n) //ÊäÈë
#define PFout(n) BIT_ADDR(GPIOF_ODR_Addr,n) //Êä³ö
#define PFin(n) BIT_ADDR(GPIOF_IDR_Addr,n) //ÊäÈë
#define PGout(n) BIT_ADDR(GPIOG_ODR_Addr,n) //Êä³ö
#define PGin(n) BIT_ADDR(GPIOG_IDR_Addr,n) //ÊäÈë
void NVIC_Configuration(void);
#endif
#include "sys.h"
#include "stm32f10x.h"
void NVIC_Configuration(void)
{
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
}
#include "hc.h"
#include "Delay.h"
#define HCSR04_PORT GPIOB
#define HCSR04_CLK RCC_APB2Periph_GPIOB
#define HCSR04_TRIG GPIO_Pin_11
#define HCSR04_ECHO GPIO_Pin_10
u16 msHcCount = 0;
void HC_Init(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(HCSR04_CLK, ENABLE);
GPIO_InitStructure.GPIO_Pin =HCSR04_TRIG;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(HCSR04_PORT, &GPIO_InitStructure);
GPIO_ResetBits(HCSR04_PORT,HCSR04_TRIG);
GPIO_InitStructure.GPIO_Pin = HCSR04_ECHO;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(HCSR04_PORT, &GPIO_InitStructure);
GPIO_ResetBits(HCSR04_PORT,HCSR04_ECHO);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);
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(TIM4, &TIM_TimeBaseStructure);
TIM_ClearFlag(TIM4, TIM_FLAG_Update);
TIM_ITConfig(TIM4,TIM_IT_Update,ENABLE);
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
NVIC_InitStructure.NVIC_IRQChannel = TIM4_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
TIM_Cmd(TIM4,DISABLE);
}
static void OpenTimerForHc()
{
TIM_SetCounter(TIM4,0);
msHcCount = 0;
TIM_Cmd(TIM4, ENABLE);
}
static void CloseTimerForHc()
{
TIM_Cmd(TIM4, DISABLE);
}
void TIM4_IRQHandler(void)
{
if (TIM_GetITStatus(TIM4, TIM_IT_Update) != RESET)
{
TIM_ClearITPendingBit(TIM4, TIM_IT_Update );
msHcCount++;
}
}
u32 GetEchoTimer(void)
{
u32 t = 0;
t = msHcCount*1000;
t += TIM_GetCounter(TIM4);
TIM4->CNT = 0;
Delay_ms(50);
return t;
}
float HC_Get(void )
{
int 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);//cm
sum = lengthTemp + sum ;
}
lengthTemp = sum/5.0;
return lengthTemp;
}
#ifndef __HC_H
#define __HC_H
#include "sys.h"
void HC_Init(void);
static void OpenTimerForHc(void);
static void CloseTimerForHc(void);
void TIM4_IRQHandler(void);
u32 GetEchoTimer(void);
float HC_Get(void );
#define TRIG_Send PBout(11)
#define ECHO_Reci PBin(10)
#endif
#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "OLED.h"
#include "HC.h"
uint32_t Length;
float length;
int main(void)
{
OLED_Init();
OLED_ShowString(1,1,"Length:");
OLED_ShowString(2,10,"cm");
HC_Init();
while(1)
{
length =HC_Get();
Length = length*100; //eg:54.25->5425
OLED_ShowNum(2,4,Length/1000,1); // 千
OLED_ShowNum(2,5,Length%1000/100,1); //百
OLED_ShowString(2,6,".");
OLED_ShowNum(2,7,Length%100/10,1); //十
OLED_ShowNum(2,8,Length%10/1,1); //个
}
}
六、实验现象
附录 串口调试版本
1、连线图
2、调试截图
3、模块化函数(相较于 五、模块化程序 新增部分)
#include "stm32f10x.h" // Device header
#include <stdio.h>
#include <stdarg.h>
uint8_t Serial_RxData;
uint8_t Serial_RxFlag;
void Serial_Init(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
USART_InitTypeDef USART_InitStructure;
USART_InitStructure.USART_BaudRate = 9600;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_Init(USART1, &USART_InitStructure);
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_Init(&NVIC_InitStructure);
USART_Cmd(USART1, ENABLE);
}
void Serial_SendByte(uint8_t Byte)
{
USART_SendData(USART1, Byte);
while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
}
void Serial_SendArray(uint8_t *Array, uint16_t Length)
{
uint16_t i;
for (i = 0; i < Length; i ++)
{
Serial_SendByte(Array[i]);
}
}
void Serial_SendString(char *String)
{
uint8_t i;
for (i = 0; String[i] != '\0'; i ++)
{
Serial_SendByte(String[i]);
}
}
uint32_t Serial_Pow(uint32_t X, uint32_t Y)
{
uint32_t Result = 1;
while (Y --)
{
Result *= X;
}
return Result;
}
void Serial_SendNumber(uint32_t Number, uint8_t Length)
{
uint8_t i;
for (i = 0; i < Length; i ++)
{
Serial_SendByte(Number / Serial_Pow(10, Length - i - 1) % 10 + '0');
}
}
int fputc(int ch, FILE *f)
{
Serial_SendByte(ch);
return ch;
}
void Serial_Printf(char *format, ...)
{
char String[100];
va_list arg;
va_start(arg, format);
vsprintf(String, format, arg);
va_end(arg);
Serial_SendString(String);
}
uint8_t Serial_GetRxFlag(void)
{
if (Serial_RxFlag == 1)
{
Serial_RxFlag = 0;
return 1;
}
return 0;
}
uint8_t Serial_GetRxData(void)
{
return Serial_RxData;
}
void USART1_IRQHandler(void)
{
if (USART_GetITStatus(USART1, USART_IT_RXNE) == SET)
{
Serial_RxData = USART_ReceiveData(USART1);
Serial_RxFlag = 1;
USART_ClearITPendingBit(USART1, USART_IT_RXNE);
}
}
#ifndef __SERIAL_H
#define __SERIAL_H
#include <stdio.h>
void Serial_Init(void);
void Serial_SendByte(uint8_t Byte);
void Serial_SendArray(uint8_t *Array, uint16_t Length);
void Serial_SendString(char *String);
void Serial_SendNumber(uint32_t Number, uint8_t Length);
void Serial_Printf(char *format, ...);
uint8_t Serial_GetRxFlag(void);
uint8_t Serial_GetRxData(void);
#endif
#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "OLED.h"
#include "HC.h"
#include "Serial.h"
uint32_t Length;
float length;
int main(void)
{
OLED_Init();
HC_Init();
Serial_Init();
OLED_ShowString(1,1,"Length:");
OLED_ShowString(2,10,"cm");
// Serial_SendByte(0x41);
//
// uint8_t MyArray[] = {0x42, 0x43, 0x44, 0x45};
// Serial_SendArray(MyArray, 4);
//
// Serial_SendString("\r\nNum1=");
//
// Serial_SendNumber(111, 3);
//
// printf("\r\nNum2=%d", 222);
//
// char String[100];
// sprintf(String, "\r\nNum3=%d", 333);
// Serial_SendString(String);
//
// Serial_Printf("\r\nNum4=%d", 444);
// Serial_Printf("\r\n");
while(1)
{
length =HC_Get();
Length = length*100; //eg:54.25->5425
OLED_ShowNum(2,4,Length/1000,1); // ǧ
OLED_ShowNum(2,5,Length%1000/100,1); //°Ù
OLED_ShowString(2,6,".");
OLED_ShowNum(2,7,Length%100/10,1); //Ê®
OLED_ShowNum(2,8,Length%10/1,1); //¸ö
Serial_SendString("The length is:");
Serial_SendNumber(Length/1000, 1);
Serial_SendNumber(Length%1000/100, 1);
Serial_SendString(".");
Serial_SendNumber(Length%100/10, 1);
Serial_SendNumber(Length%10/1, 1);
Serial_Printf("\r\n");
Delay_ms(500);
}
}