蓝桥杯单片机设计与开发⑫ ---超声波模块

一、基本原理

超声波发射模块向某一方向发射超声波,在发射时刻的同时开始计时,超声波在空气中传播,途中碰到障碍物就立即返回来,超声波接收器收到反射波就立即停止计时

二、计算公式

距离 = 声速 × 发出超声波到接收返回的时间/2
因为超声波在空气中的传播速度受温度影响。声波在空气中的传播速度与温度的关系是:
在20摄氏度时,声速V = 332 + 0.607t (m/s)
利用超声波进行距离测量,要求精度一般都不高,取20摄氏度时候的声速344M/S进行计算,再进行适当的补偿就可以。所以,其计算公式为:距离L = 344M/S * T / 2 = 172M/S * T 。

三、实现步骤

  1. 产生8个40KHz的超声波信号,通过TX引脚发射出去
  2. 启动定时器,计算计数脉冲。
  3. 等待超声波信号返回,如果接收到反射回来的信号,RX引脚变为低电平
  4. 停止定时器,读取脉冲个数,即获得时间T。
  5. 根据公式,L = V * T /2m进行距离的计算。

四、参考程序

注:超声波测距是一直以来都是国赛中重要的考点,几乎每届必考。虽然省赛还没有考过,但也不能排除以后不考

在蓝桥杯单片机的竞赛综合平台CT107D中,超声波模块的TX引脚接到单片机的P1.0端口,RX引脚接到单片机的P1.1端口。设计程序,进行超声波测距,最大测量范围约140cm。测量结果用cm作为显示单位,显示在数码管的最左边三位。如果测量距离超出范围,则以“F”作为标志,显示在数码管的最右边一位。

sonic.c

#include "sys.h"
#define sonic_nop {_nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_();};

void Send_Sonic(void) //发送8个40khz脉冲信号
{
	unsigned char i = 8;
	
	while(i --)
	{
		TX = 1;
		sonic_nop; sonic_nop; sonic_nop; sonic_nop; sonic_nop;
		sonic_nop; sonic_nop; sonic_nop; sonic_nop; sonic_nop;
		TX = 0;
		sonic_nop; sonic_nop; sonic_nop; sonic_nop; sonic_nop;
		sonic_nop; sonic_nop; sonic_nop; sonic_nop; sonic_nop;
	}
}


unsigned int Mea_Distance()
{
	u16 distance = 0;
	u16 time = 0;
	Send_Sonic();	//发送超声波信号
	TR1 = 1; 		//启动定时器1
	while((RX == 1)&&(TF1 == 0));//等待超声波信号返回,或者等到测量超出范围
	TR1 = 0;		//停止定时器1
	
	if(TF1 == 0) //正常测量范围
	{
		time = TH1;
		time = (time << 8)|TL1;
		distance = time*0.0175;
		
	}else		//超出测量范围
	{
		TF1 = 0;
		distance = 999;	
	}
	TH1 = 0;
	TL1 = 0;
	return distance;
}

main.c

#include "sys.h"
bit MEA_SONIC_FLAG;
void main()
{
	u16 distance = 0;
	ALL_Init();
	Timer0Init();
	Timer1Init();
	while(1)
	{
		if(MEA_SONIC_FLAG) //每125ms测量一次
		{
			MEA_SONIC_FLAG = 0;
			distance = Mea_Distance();
		}
		Nixie_Drive(distance);
	}
}

sys.h

#ifndef __SYS_H__
#define __SYS_H__


//头文件包含
#include <STC15F2K60S2.H>
#include <intrins.h>

//管脚声明
sbit TX = P1^0;//超声波发送
sbit RX = P1^1;//超声波接收
//变量类型声明
typedef unsigned int uint;
typedef unsigned int u16;
typedef unsigned char uchar;
typedef unsigned char u8;


//外部变量声明

//函数声明
void ALL_Init();
void Operate_Delay(unsigned int ms);
void HC138_Set(u8 channel);
void Timer0Init();
void Timer1Init(void);
//nixie.c
void Nixie_Scan();
void Nixie_Show();
void Nixie_Drive(u16 dat);
//sonic.c
void Send_Sonic();
unsigned int Mea_Distance();
#endif

nixie.c

#include "sys.h"

					// 0    1    2    3    4    5    6    7
uchar code nixie[] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,
				    // 8	9    a    b    c    d     e    f	u
					  0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e,0xc1,0xff};	//共阳数码管码字

uchar NixieBuff[] = {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};

uchar smg1,smg2,smg3,smg4,smg5,smg6,smg7,smg8;
uchar code Symbol[] = {0xff,0xbf};	//全灭,-


void Nixie_Scan()
{
	static u8 index;
	HC138_Set(7);
	P0 = 0XFF;
	HC138_Set(6);
	P0 = 0x01<<index;
	HC138_Set(7);
	P0 = NixieBuff[index];
	HC138_Set(0);
	index++;
	index &= 0x07;
}

void Nixie_Show()
{
	NixieBuff[0] = nixie[smg1];
	NixieBuff[1] = nixie[smg2];
	NixieBuff[2] = nixie[smg3];
	NixieBuff[3] = Symbol[smg4];
	NixieBuff[4] = Symbol[smg5];
	NixieBuff[5] = Symbol[smg6];
	NixieBuff[6] = Symbol[smg7];
	NixieBuff[7] = nixie[smg8];
}

void Nixie_Drive(u16 dat)
{
	if(dat == 999)
	{
		smg1 = smg2 = smg3 = 17;
		smg4 = smg5 = smg6 = smg7 = 0;
		smg8 = 15;
	}else
	{
		smg1 = dat/100;
		smg2 = dat%100/10;
		smg3 = dat%10;
		smg4 = smg5 = smg6 = smg7 = 0;
		smg8 = 17;
	}
}

sys.c

#include "sys.h"
extern bit MEA_SONIC_FLAG;
/**
*@brief     外设初始化  
*@param[in] none
*@return    none
**/
void ALL_Init()
{
	P2 = (P2&0x1f)|0xa0;	//打开Y5C
	P0 = 0x00;				//关闭蜂鸣器&继电器
	P2 = (P2&0x1f)|0xe0;	//打开Y7C
	P0 = 0xff;				//关闭数码管
	P2 = (P2&0x1f)|0x80;	//打开Y4C
	P0 = 0xff;				//关闭LED
	P2 = P2&0x1f;			//关闭所用使能
}
/**
*@brief     延时函数
*@param[in] 延时多少ms(0~65535)
*@return    none
**/
void Operate_Delay(u16 ms)
{
	u16 i;
	for(ms;ms>0;ms--)
		for(i=921;i>0;i--);
}
/**
*@brief      74HC138译码器通道选择
*@param[in]  channel (通道)
*@return     none
**/
void HC138_Set(u8 channel)
{
	switch(channel)
	{
		case 0: P2 =  P2 & 0x1f;     break;     //关闭所有通道
		case 4: P2 = (P2&0x1f)|0x80; break;     //选择Y4对应的模块 (LED),		 运算结果为P2高三位 100
		case 5: P2 = (P2&0x1f)|0xa0; break;     //选择Y5对应的模块 (蜂鸣器),	 运算结果为P2高三位 101
		case 6: P2 = (P2&0x1f)|0xc0; break;     //选择Y6对应的模块 (数码管位选), 运算结果为P2高三位 110
		case 7: P2 = (P2&0x1f)|0xe0; break;     //选择Y7对应的模块 (数码管段选), 运算结果为P2高三位 111
	}
}

void Timer0Init(void)		//1毫秒@11.0592MHz
{
	AUXR |= 0x80;		//定时器时钟1T模式
	TMOD &= 0xF0;		//设置定时器模式
	TL0 = 0xCD;		//设置定时初值
	TH0 = 0xD4;		//设置定时初值
	TF0 = 0;		//清除TF0标志
	TR0 = 1;		//定时器0开始计时
	ET0 = 1;
	EA = 1;
}

void Timer1Init(void)		//0微秒@11.0592MHz
{
	AUXR &= 0xBF;		//定时器时钟12T模式
	TMOD &= 0x0F;		//设置定时器模式
	
	TL1 = 0;		//设置定时初值
	TH1 = 0;		//设置定时初值
	TF1 = 0;		//清除TF1标志
	TR1 = 0;
}

void Timer0() interrupt 1
{
	static unsigned char i;
	i++;
	if(i == 125)
	{
		i = 0;
		MEA_SONIC_FLAG = 1;
	}
	Nixie_Show();
	Nixie_Scan();
}

  • 4
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值