一 超声波硬件详解
- 硬件参数
参数 | 说明 |
产品名称 | 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,权当纪念~
相关代码:超声波模块的使用