STC8H8K蓝牙智能巡线小车——5.超声波测距(超声波检测障碍物)

超声波测距原理

所选超声波测距模组:HC-SR04

官方解释

HC-SR04 超声波测距模块可供 2cm提-400cm 的非接触式距离感测功能,测距精度可达高到 3mm;模块包括超声波发射器、接收器与控制电路。

基本工作原理
  1. 采用 IO 口 TRIG 触发测距,给最少 10us 的高电平信号。
  2. 模块自动发送 8 个 40khz 的方波,自动检测是否有信号返回;
  3. 有信号返回,通过 IO 口 ECHO 输出一个高电平,高电平持续的时间就是超声波从发射到返回的时间。
  4. 测试距离=(高电平时间*声速(340M/S))/2
 超声波时序图 STC8H8K蓝牙智能巡线小车——5.超声波测距(超声波检测障碍物)_第1张图片

 以上时序图表明你只需要提供一个 10uS 以上脉冲触发信号,该模块内部将 发出 8 个 40kHz 周期电平并检测回波。一旦检测到有回波信号则输出回响信号。 回响信号的脉冲宽度与所测的距离成正比。由此通过发射信号到收到的回响信号 时间间隔可以计算得到距离。公式:uS/58=厘米或者 uS/148=英寸;或是:距离= 高电平时间*声速(340M/S)/2;建议测量周期为 60ms 以上,以防止发射信号对 回响信号的影响

电路分析

STC8H8K蓝牙智能巡线小车——5.超声波测距(超声波检测障碍物)_第2张图片

  • 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 P40

void 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 woring
	Delay10us();// at least 10us 
	Delay10us();
	TRIG_PIN=0;//set trig is low power
	
	do{
		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) /2
	return 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 3

void 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_BRTx
    COMx_InitStructure.UART_BRT_Use   = BRT_Timer1;			//选择波特率发生器, BRT_Timer1, BRT_Timer2 (注意: 串口2固定使用BRT_Timer2)
    COMx_InitStructure.UART_BaudRate  = 115200ul;			//波特率, 一般 110 ~ 115200
    COMx_InitStructure.UART_RxEnable  = ENABLE;				//接收允许,   ENABLE或DISABLE
    COMx_InitStructure.BaudRateDouble = DISABLE;			//波特率加倍, ENABLE或DISABLE
    UART_Configuration(UART1, &COMx_InitStructure);		//初始化串口1 UART1,UART2,UART3,UART4

  	NVIC_UART1_Init(ENABLE,Priority_1);		//中断使能, ENABLE/DISABLE; 优先级(低到高) Priority_0,Priority_1,Priority_2,Priority_3
    UART1_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){
		
		// left
		LED_ON(left);
		os_wait2(K_TMO, 100);
		
		LED_OFF(left);
		os_wait2(K_TMO, 100);
		
		// right
		LED_ON(right);
		os_wait2(K_TMO, 100);
		
		LED_OFF(right);
		os_wait2(K_TMO, 100);
		
		// Hazard lights
		LED_ON(all);
		os_wait2(K_TMO, 100);
		
		// all off
		LED_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);
}



你可能感兴趣的:(单片机开发(IC,Development),嵌入式硬件,单片机,51单片机)