STM32用HCS-R04超声波传感器测距,当距离小于8厘米时蜂鸣器响
时间: 2023-07-18 18:05:27 浏览: 107
STM32实现超声波测距
3星 · 编辑精心推荐
可以通过以下步骤来实现:
1. 连接HCS-R04超声波传感器到STM32开发板上,连接蜂鸣器到开发板的GPIO口。
2. 在STM32的程序中,使用定时器来生成10微秒的脉冲信号,作为超声波传感器的触发信号。
3. 通过外部中断来检测HCS-R04传感器返回的超声波信号,计算出距离值。
4. 判断距离是否小于8厘米,如果是,则控制蜂鸣器响起。
下面是一份示例代码,仅供参考:
```c
#include "stm32f10x.h"
// 定义超声波传感器的IO口
#define TRIG_PORT GPIOB
#define TRIG_PIN GPIO_Pin_0
#define ECHO_PORT GPIOB
#define ECHO_PIN GPIO_Pin_1
// 定义蜂鸣器的IO口
#define BEEP_PORT GPIOC
#define BEEP_PIN GPIO_Pin_13
// 定义计时器和计数器的初值
#define TIM_PRESCALER 71 // 1us的计数频率
#define TIM_PERIOD 0xFFFF
#define COUNT_MAX 30000 // 超过30ms认为超声波信号丢失
// 定义超声波传感器距离转换系数
#define DISTANCE_FACTOR 58.0f // 转换为厘米需要除以58
// 定义全局变量
volatile uint16_t count = 0;
volatile uint32_t distance = 0;
void TIM2_IRQHandler(void)
{
if(TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET)
{
TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
count++;
}
}
void EXTI1_IRQHandler(void)
{
if(EXTI_GetITStatus(EXTI_Line1) != RESET)
{
if(GPIO_ReadInputDataBit(ECHO_PORT, ECHO_PIN) == SET)
{
TIM_SetCounter(TIM2, 0);
}
else
{
uint16_t cnt = TIM_GetCounter(TIM2);
if(cnt < COUNT_MAX)
{
distance = cnt * DISTANCE_FACTOR;
if(distance < 8)
{
GPIO_SetBits(BEEP_PORT, BEEP_PIN);
}
else
{
GPIO_ResetBits(BEEP_PORT, BEEP_PIN);
}
}
}
EXTI_ClearITPendingBit(EXTI_Line1);
}
}
void init_gpio(void)
{
// 初始化超声波传感器的IO口
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = TRIG_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(TRIG_PORT, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = ECHO_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Init(ECHO_PORT, &GPIO_InitStructure);
// 初始化蜂鸣器的IO口
GPIO_InitStructure.GPIO_Pin = BEEP_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(BEEP_PORT, &GPIO_InitStructure);
}
void init_timer(void)
{
// 初始化定时器2为1us的计数频率
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_TimeBaseStructure.TIM_Period = TIM_PERIOD;
TIM_TimeBaseStructure.TIM_Prescaler = TIM_PRESCALER;
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
TIM_Cmd(TIM2, ENABLE);
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
void init_exti(void)
{
// 初始化外部中断1
EXTI_InitTypeDef EXTI_InitStructure;
EXTI_InitStructure.EXTI_Line = EXTI_Line1;
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising_Falling;
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure);
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = EXTI1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
int main(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOC, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
init_gpio();
init_timer();
init_exti();
while(1)
{
// 发送10us的脉冲信号
GPIO_SetBits(TRIG_PORT, TRIG_PIN);
delay_us(10);
GPIO_ResetBits(TRIG_PORT, TRIG_PIN);
delay_ms(100);
}
}
```
需要注意的是,在使用外部中断检测超声波信号时,需要在中断服务函数中判断当前是上升沿还是下降沿,并分别进行处理。同时,为了避免超声波信号丢失导致距离计算错误,需要设置一个计数器,当超过一定时间仍未收到超声波信号时,认为信号丢失。
阅读全文