香橙派开发系列-超声波测量距离

前言

超声波模块是非常简单也非常好用的一个模块,不需要你会多少概念,你只需要会IO口的控制和定时器的操作就可以就行操作了。这一篇文章我会从stm32和香橙派一直来讲解这个超声波测距怎么玩。

一、HC-SR04芯片

这个是我们超声波模块使用的芯片,我们就对它就行IO操作就可以了。

超声波模块有4个引脚,分别是

  • VCC
  • GND
  • Trig
  • Echo

然后这个模块的时序图如下:

当向Trig发送一个高电平,这个高电平要持续10~20us才可以,然后Echo就会发送一个高电平回来就代表着超声波已经发送,当超声波碰到物体后就会反弹,反弹回来后Echo引脚就会变成一个低电平来告诉用户已经发送来回了。

我们知道这个的时序图后我们就可以知道如何通过这个超声波来进行测距了,我们可以在它发送超声波后开启定时,当接送到超声波后就停止定时,然后通过获取的时间去除以340m/s并再除以2就可以得到距离了。

二、stm32代码编写

我们知道上面讲的内容后我们就可以开始编写代码了,首先我们要初始化GPIO口,让其能进行接收和发送数据,然后再初始化一个计数器来获取超声波在过程中经过的时间。

首先是IO口的初始化代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
GPIO_InitTypeDef GPIO_InitStruct = {0};

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);

// 理解Tiger引脚
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_1;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStruct);

// 连接Echo引脚
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU;
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStruct);
GPIO_ResetBits(GPIOB, GPIO_Pin_0);

然后我们开始初始化Timer定时器,使用的是定时器2,你也可以用其它的标准定时器或者基础定时器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
TIM_TimeBaseInitTypeDef TIM_TimeBaseStruct = {0};
NVIC_InitTypeDef NVIC_InitStruct = {0};

RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);

TIM_TimeBaseStruct.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseStruct.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseStruct.TIM_Period = 1000 - 1; // 重装值
TIM_TimeBaseStruct.TIM_Prescaler = 72 - 1; // 预重装系数
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStruct);

NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
NVIC_InitStruct.NVIC_IRQChannel = TIM2_IRQn;
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 2;
NVIC_InitStruct.NVIC_IRQChannelSubPriority = 2;
NVIC_Init(&NVIC_InitStruct);
TIM_Cmd(TIM2, DISABLE);

这里我们设置的定时器是1us的,然后我们就可以写一下中断处理函数

1
2
3
4
5
6
void TIM2_IRQHandler(void){
if (TIM_GetITStatus(TIM2, TIM_IT_Update)){
count++;
TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
}
}