一 超声波硬件详解
参数 | 说明 |
---|---|
产品名称 | HC-SR04超声波模块 |
工作电压 | DC 5V |
工作电流 | 15mA |
工作频率 | 40KHz |
射程范围 | 2cm — 400cm |
测量角度 | <= 15度 |
输入触发信号 | 10us的TTL脉冲 |
输出回响信号 | 输出TTL电平信号,与射程成正比 |
二 工作原理
- 采用(IO触发测距,至少给10us的高电平)
- 模块自动发送8个40kHz的方波,自动检测是否有信号返回
- 有信号返回时,通过IO输出一高电平、高电平持续时间就是超声波从发射到返回的时间
三 代码编写
- GPIO结构体的初始化
- EXTI外部中断结构体的初始化
- NVIC中断结构体的初始化
- TimeBase时基结构体的初始化
- 超声波Trig发送信号
- 外部中断服务函数接收返回信号并计算出距离(全局变量)
- 关键代码
/**
* 函数名:HSR04_Init()
* 功能:超声波的初始化
* 引脚:PB5(Trig) | PB4(Echo)
* 占用的内设资源:TIM6,EXTI_Line4
*/
void HSR04_Init()
{
GPIO_InitTypeDef GPIO_InitSture;
EXTI_InitTypeDef EXTI_InitSture;
NVIC_InitTypeDef NVIC_InitSture;
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitSture;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);//打开外部中断exti挂载时钟线
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6,ENABLE);
GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable,ENABLE);
/**************************GPIO结构体的初始化**********************************/
GPIO_InitSture.GPIO_Mode=GPIO_Mode_Out_PP;
GPIO_InitSture.GPIO_Pin=Trig;
GPIO_InitSture.GPIO_Speed=GPIO_Speed_10MHz;
GPIO_Init(Trig_Port,&GPIO_InitSture);
GPIO_InitSture.GPIO_Mode=GPIO_Mode_IN_FLOATING;
GPIO_InitSture.GPIO_Pin=Echo;
GPIO_Init(Echo_Port,&GPIO_InitSture);
/**************************EXTI外部中断结构体的初始化***************************/
GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource4);//将外部中断引脚重映射到GPIO
EXTI_InitSture.EXTI_Line=EXTI_Line4;
EXTI_InitSture.EXTI_LineCmd=ENABLE;
EXTI_InitSture.EXTI_Mode=EXTI_Mode_Interrupt;//选择中断方式
EXTI_InitSture.EXTI_Trigger=EXTI_Trigger_Rising;
EXTI_Init(&EXTI_InitSture);
/**************************NVIC中断结构体的初始化*******************************/
NVIC_InitSture.NVIC_IRQChannel=EXTI4_IRQn;
NVIC_InitSture.NVIC_IRQChannelCmd=ENABLE;
NVIC_InitSture.NVIC_IRQChannelPreemptionPriority=2;
NVIC_InitSture.NVIC_IRQChannelSubPriority=2;
NVIC_Init(&NVIC_InitSture);
/***********************TimeBase时基结构体的初始化*******************************/
TIM_TimeBaseInitSture.TIM_CounterMode=TIM_CounterMode_Up;
TIM_TimeBaseInitSture.TIM_Period=5000;
TIM_TimeBaseInitSture.TIM_Prescaler=7199;
TIM_TimeBaseInitSture.TIM_ClockDivision=0;//无需分频
TIM_TimeBaseInit(TIM6,&TIM_TimeBaseInitSture);
}
四 知识点分析
观察以下两段代码
TIM_SetCounter(TIM6,0);
TIM_Cmd(TIM6,ENABLE);
while(GPIO_ReadInputDataBit(GPIOB,Echo)==1)
TIM_Cmd(TIM6,DISABLE);
Distance_test=TIM_GetCounter(TIM6)*340/200;
TIM_SetCounter(TIM6,0);
TIM_Cmd(TIM6,ENABLE);
while(GPIO_ReadInputDataBit(GPIOB,Echo)==1);
TIM_Cmd(TIM6,DISABLE);
Distance_test=TIM_GetCounter(TIM6)*340/200;
第三行的while循环中,第一个无分号(;),第二个有分号(;).
所以第一段代码中,由于没有分号,所以相当于
while(GPIO_ReadInputDataBit(GPIOB,Echo)==1)
{
TIM_Cmd(TIM6,DISABLE);
}
所以在高电平的时间段,定时器一直在关闭,那么超声波测出来的距离始终为0
而第二段代码则是可以正常运行的
改了好久的bug,权当纪念~
相关代码:超声波模块的使用