一、超声波简介
超声波原理:
利用声音测距,声音在空气中的速度是340m/s(15℃)
当声音传播时,若遇到障碍物时,就会被反弹回来,通过计时反弹回来的时间就可以计算出从发射端到障碍物的距离
引脚定义:
工作电压:3V-5.5V宽电压供电
测距盲区:2cm最小盲区
接口定义如图
序号 |
接口定义 |
说明 |
1 |
Vcc |
供电电源 |
2 |
Trig/Rx/SCL |
GPIO模式: Trig 触发信号 UART模式: Rx 接收信号 IIC 模式: SCL 时钟信号 |
3 |
Echo/Tx/SDA |
GPIO模式为 Echo 反馈信号 UART模式: Tx 发射信号 ICC 模式: SCL 数据信号 |
4 |
Gnd |
地 |
GPIO模式测量原理:
外部MCU给模块Trig脚一个大于10uS的高电平脉冲;模块会给出一个与距离等比的高电平脉冲信号,可根据脉宽时间“T”算出:距离=T*C/2 (C为声速)
即本文中使用的距离 = t / 58 cm
声速温度公式:c=(331.45+0.61t/℃)m•s-1 (其中330.45是在0℃)
0℃声速: 330.45M/S
20℃声速: 342.62M/S
40℃声速: 354.85M/S
0℃-40℃声速误差7%左右。实际应用,如果需要精确距离值,必需要考虑温度影响,做温度补偿。
二、代码解析
HCSR04.c
初始化部分
void Sr04_Init()
{
/*GPIO初始化*/
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;//推挽输出
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;//设置发生电平引脚trig
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB,&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;//接受电平引脚echo
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_ResetBits(GPIOB,GPIO_Pin_11);//默认低电平
GPIO_ResetBits(GPIOB,GPIO_Pin_10);//默认低电平
/*定时器TIM2初始化*/
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
TIM_InternalClockConfig(TIM2);
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseStructure.TIM_Period = 1000-1;//ARR
TIM_TimeBaseStructure.TIM_Prescaler = 72-1;//PSC
TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
TIM_ClearFlag(TIM2, TIM_FLAG_Update);//清除标志位
TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);//使能更新中断->NVIC
/*NVIC初始化*/
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_Init(&NVIC_InitStructure);
}
开、关定时器
/*打开定时器*/
void OpenTimer()
{
TIM_SetCounter(TIM2,0);
count=0;//计数为零
TIM_Cmd(TIM2,ENABLE);
}
/*关闭定时器*/
void CloseTimer()
{
TIM_Cmd(TIM2,DISABLE);
}
定时器中断
void TIM2_IRQHandler(void)
{
if(TIM_GetITStatus(TIM2,TIM_IT_Update)== SET)
{
TIM_ClearITPendingBit(TIM2,TIM_IT_Update);
count++;// 72M/(PSC+1)/(ARR+1)即72M/72/1000=1ms
}
}
获取计数值
u32 GetEchoTimer()
{
u32 t=0;
t = count*1000;
t +=TIM_GetCounter(TIM2);
TIM2->CNT = 0;
Delay_ms(50);
return t;
}
计算距离
float Sr04GetLength()
{
u32 t = 0;
int i = 0;
float length = 0;
float sum = 0;
while(i!=5)
{
GPIO_SetBits(GPIOB,GPIO_Pin_11);//trig发出高电平
Delay_us(20);
GPIO_ResetBits(GPIOB,GPIO_Pin_11);
while(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_10) == 0);//echo等待回响
OpenTimer();//´打开定时器
i = i + 1;//每收到一次,回响信号+1,计算收到5次的平均值
while(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_10) == 1);
CloseTimer();//关闭定时器
t = GetEchoTimer();
length = ((float)t/58.0);//cm
sum = length + sum ;
}
length = sum/5.0;
return length;
}
LED.c
我这里LED接的是高电平,所以STM32给低电平点亮
/*LED初始化*/
void LED_Init()
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_10MHz;
GPIO_Init(GPIOA,&GPIO_InitStructure);
}
void LED_ON()
{
GPIO_ResetBits(GPIOA,GPIO_Pin_0);
}
void LED_OFF()
{
GPIO_SetBits(GPIOA,GPIO_Pin_0);
}
main.c
OLED显示距离。文章来源:https://www.toymoban.com/news/detail-766520.html
当距离小于10cm时,LED点亮;大于10cm时,LED熄灭。文章来源地址https://www.toymoban.com/news/detail-766520.html
a=Sr04GetLength();//距离变量a
int main(void)
{
LED_Init();
OLED_Init();
Sr04_Init();
OLED_ShowString(1,1,"length:");
while(1)
{
a=Sr04GetLength();
OLED_ShowNum(2,1,a,4);
if(a<10)
{
LED_ON();
}
else
{
LED_OFF();
}
}
}
到了这里,关于STM32超声波测距(OLED显示距离)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!