HC-SR04超声波测距模块是一种常用的测距模块,它通过检测超声波发射后遇到障碍物所反射的回波,从而测量出传感器与障碍物之间的距离。
HC-SR04超声波测距模块一般包括VCC、Trig、Echo、GND四个引脚。其中VCC和GND分别为正负电源引脚,Trig为触发引脚,用于控制超声波的发射;Echo为回波引脚,用于接收反射回来的超声波信号。
HC-SR04超声波测距模块的工作原理是利用超声波在空气中传播的速度来计算距离。具体过程如下:
模块通过IO口触发测距,给Trig引脚至少10μs的高电平信号。
模块自动发送8个40kHz的超声波脉冲,并自动检测是否有信号返回。
当超声波射向目标物体后,它会被反射回来,并被模块的回波引脚Echo接收到。
在接收到回波信号后,模块会将Echo引脚的电平置高,表示回波信号已经接收到。此时,开始计时。
直到回波信号被传回模块,模块将Echo引脚的电平置低,表示回波信号已经结束,停止计时。
通过计算超声波发出后到达障碍物再反射回传感器的时间差,并结合已知的超声波传播速度(通常为340m/s,但易受温度、湿度、压强等因素影响),就可以得出障碍物与传感器的距离。
测距算法本质就是小学行程问题
距离S=声速V*时间t=340t
V是常量,t可以用定时器测量
一、MCUXpresso Config Tools配置
配置了若个GPIO驱动LCD和HC-SR04
配置一个UART打印日志
配置一个TIMER用来给HC-SR04计时
TRIG: OUTPUT ECHO:INPUT 下拉
二、程序
1、LPTMR0定时器初始化
#define LPTMR_USEC_COUNT 200 #define LPTMR_SOURCE_CLOCK (12000U) //时钟 CLOCK_SetClockDiv(kCLOCK_DivLPTMR0, 1u); CLOCK_AttachClk(kFRO12M_to_LPTMR0); CLOCK_SetupFRO16KClocking(kCLKE_16K_SYSTEM | kCLKE_16K_COREMAIN); LPTMR_GetDefaultConfig(&lptmrConfig); /* Initialize the LPTMR */ LPTMR_Init(LPTMR0, &lptmrConfig); LPTMR_SetTimerPeriod(LPTMR0, USEC_TO_COUNT(LPTMR_USEC_COUNT, LPTMR_SOURCE_CLOCK)); /* Enable timer interrupt */ LPTMR_EnableInterrupts(LPTMR0, kLPTMR_TimerInterruptEnable); /* Enable at the NVIC */ EnableIRQ(LPTMR0_IRQn); /* Start counting */ LPTMR_StartTimer(LPTMR0);
关于LPTMR0设置没有深究,可能取值不是特别合理。
2、定时器中断
void LPTMR0_IRQHandler(void) { LPTMR_ClearStatusFlags(DEMO_LPTMR_BASE, kLPTMR_TimerCompareFlag); lptmrCounter++; /* * Workaround for TWR-KV58: because write buffer is enabled, adding * memory barrier instructions to make sure clearing interrupt flag completed * before go out ISR */ __DSB(); __ISB(); }
中断一次,lptmrCounter加一,lptmrCounter结果为时间t
3、建立一个HC_SR04_Task
stat = xTaskCreate(HC_SR04_Task, "HC_SR04", configMINIMAL_STACK_SIZE + 200, NULL, tskIDLE_PRIORITY + 3, NULL);
void HC_SR04_Task(void *param) { unsigned int distVal; //距离s,单位cm ResetTrig(); //trig引脚置低电平 vTaskDelay(3000); for (;;) { if(disp_flush_enabled) //如果LCD LVGL初始化完成 { distVal=Measure_Distance(); //获得距离 PRINTF("distVal:%d\r\n",distVal); lv_label_set_text_fmt(guider_ui.screen_label_2, "%d", distVal); //LVGL显示结果 vTaskDelay(1000); //延时1秒 } } }
测距函数:
unsigned int Measure_Distance(void) //测距 { unsigned int distance=0; SetTrig(); //10us的脉冲触发信号 SDK_DelayAtLeastUs(10, SystemCoreClock); ResetTrig(); while(ReadEcho()==0); //等待Echo输出高电平 lptmrCounter=0; //开始记录回波信号脉宽 while(ReadEcho()==1); //等待Echo输出低电平 PRINTF("%d\r\n",lptmrCounter); distance=lptmrCounter*1.7;//根据声速和时间计算距离,即distance=time*340/2/100 /* 关于分辨力(mm): 定时器每次对time加1是10us,10us=0.01ms,340m/s=340mm/ms 计算距离时,最小分辨力为:0.01(ms) * 340(mm/ms) / 2 = 1.7(mm) 小于模块标准精度3mm,故测距结果十分精准 */ return distance; //返回距离,单位mm }
Trig发出一个10us的脉冲触发信号后,HC-SR04开始工作。如果ECHO为零一直等待,直到ECHO为一,设置lptmrCounter=0;定时器计算初始化。等到Echo输出低电平,根据定时器计数计算距离。
三、运行效果