超声波测距原理
所选超声波测距模组:HC-SR04
官方解释
HC-SR04 超声波测距模块可供 2cm提-400cm 的非接触式距离感测功能,测距精度可达高到 3mm;模块包括超声波发射器、接收器与控制电路。
基本工作原理
- 采用 IO 口 TRIG 触发测距,给最少 10us 的高电平信号。
- 模块自动发送 8 个 40khz 的方波,自动检测是否有信号返回;
- 有信号返回,通过 IO 口 ECHO 输出一个高电平,高电平持续的时间就是超声波从发射到返回的时间。
- 测试距离=(高电平时间*声速(340M/S))/2
超声波时序图
以上时序图表明你只需要提供一个 10uS 以上脉冲触发信号,该模块内部将 发出 8 个 40kHz 周期电平并检测回波。一旦检测到有回波信号则输出回响信号。 回响信号的脉冲宽度与所测的距离成正比。由此通过发射信号到收到的回响信号 时间间隔可以计算得到距离。公式:uS/58=厘米或者 uS/148=英寸;或是:距离= 高电平时间*声速(340M/S)/2;建议测量周期为 60ms 以上,以防止发射信号对 回响信号的影响
电路分析
- P13引脚触发超声波控制信号
- P40引脚接受回波反馈信号
- 经过逻辑分析仪发现反馈信号一般在P13发送结束后的198us开始返回数据
编程思路
- P13_TRIG拉高电平持续10us以上再拉低电平,此时P40_ECHO引脚应为低电平,开始计数
- P40_ECHO为低电平时间在198us后结束,然后是高电平的数据返回,记录高电平的时间;
- 利用公式计算,距离=(高电平时间*声速(340M/S))/2
代码示例
Sonic.h
#ifndef __SONIC_H
#define __SONIC_H
#include "GPIO.h"#define TRIG_PIN P13
#define ECHO_PIN P40void Ultrasonic_init();
int Ultrasonic_Get_Distance(float * distance);#endif
Sonic.c
#include "Sonic.h"void Ultrasonic_init(){P1_MODE_IO_PU(GPIO_Pin_3);P4_MODE_IO_PU(GPIO_Pin_0);TRIG_PIN=0;// default: low power
}void Delay10us() //@24.000MHz
{unsigned char data i;i = 78;while (--i);
}int Ultrasonic_Get_Distance(float * distance){int count=0;TRIG_PIN=1; // set trig is high power,then ultrasonic start woringDelay10us();// at least 10us Delay10us();TRIG_PIN=0;//set trig is low powerdo{count++;Delay10us();}while(ECHO_PIN==0&&count<25);if (count>25) return 0;count=0;do{count++;Delay10us();}while(ECHO_PIN==1);count*=10;*distance = (float)count* 34/1000/2; //(time*340M/S) /2return 1;}
main.c
#include "RTX51TNY.h"
#include "GPIO.h"
#include "NVIC.h"
#include "UART.h"
#include "Switch.h"
#include "LED.h"
#include "Key.h"
#include "Battery.h"
#include "Sonic.h"#define TASK_MAIN 0
#define TASK_LED 1
#define TASK_KEY 2
#define TASK_VOLTAGE 3void UART_config(void) {// >>> 记得添加 NVIC.c, UART.c, UART_Isr.c <<<COMx_InitDefine COMx_InitStructure; //结构定义COMx_InitStructure.UART_Mode = UART_8bit_BRTx; //模式, UART_ShiftRight,UART_8bit_BRTx,UART_9bit,UART_9bit_BRTxCOMx_InitStructure.UART_BRT_Use = BRT_Timer1; //选择波特率发生器, BRT_Timer1, BRT_Timer2 (注意: 串口2固定使用BRT_Timer2)COMx_InitStructure.UART_BaudRate = 115200ul; //波特率, 一般 110 ~ 115200COMx_InitStructure.UART_RxEnable = ENABLE; //接收允许, ENABLE或DISABLECOMx_InitStructure.BaudRateDouble = DISABLE; //波特率加倍, ENABLE或DISABLEUART_Configuration(UART1, &COMx_InitStructure); //初始化串口1 UART1,UART2,UART3,UART4NVIC_UART1_Init(ENABLE,Priority_1); //中断使能, ENABLE/DISABLE; 优先级(低到高) Priority_0,Priority_1,Priority_2,Priority_3UART1_SW(UART1_SW_P30_P31); // 引脚选择, UART1_SW_P30_P31,UART1_SW_P36_P37,UART1_SW_P16_P17,UART1_SW_P43_P44
}void task_led() _task_ TASK_LED{while(1){// leftLED_ON(left);os_wait2(K_TMO, 100);LED_OFF(left);os_wait2(K_TMO, 100);// rightLED_ON(right);os_wait2(K_TMO, 100);LED_OFF(right);os_wait2(K_TMO, 100);// Hazard lightsLED_ON(all);os_wait2(K_TMO, 100);// all offLED_OFF(all);os_wait2(K_TMO, 100);}
}void keydown(){ float distance;u8 result;printf("key down\n");result = Ultrasonic_Get_Distance(&distance);if(result){printf("distance=%.2f",distance);}}void keyup(){printf("key up");
}void task_key() _task_ TASK_KEY{KEY_init();while(1){Key_Get_State(keydown,keyup);os_wait2(K_TMO, 4);}
}void task_voltage() _task_ TASK_VOLTAGE{float vol;while(1){Get_Voltage(&vol);printf("vol %.2f",vol);os_wait2(K_TMO, 200);}}void task_main() _task_ TASK_MAIN{EA=1;//LED_init();UART_config();//VOL_GPIO_init();//VOL_ADC_init();Ultrasonic_init();// os_create_task(TASK_LED);os_create_task(TASK_KEY);//os_create_task(TASK_VOLTAGE);os_delete_task(0);
}