蓝桥杯单片机开发及应用-基础模块19-超声波测距

本文详细介绍了如何利用STM15F2K60S2单片机配合超声波模块实现测距功能,并通过数码管动态显示测量结果。涉及了超声波发送、接收、计时以及数码管显示的相关代码和原理。
摘要由CSDN通过智能技术生成

目录

一、相关知识

        1.关于超声波模块

        2.注意事项

二、所要实现的功能

三、代码实现

        1.  参数定义

        2.138译码器通道选择函数

        3.初始化系统

        4.延时函数

        5.单个数码管显示函数

        6.数码管动态显示

        7.定时器初始化函数

        8.定时器0执行函数

        9.12us延时产生40KHz频率

        10.发送超声波信号函数

        11.计算测得距离函数

        12.完整代码

四、运行图片


        蓝桥杯板子上的基础模块到这里也就告一段落了,基本上就是这些模块,比赛的时候就是各种模块和定时器之间的配合使用。

一、相关知识

        1.关于超声波模块

                CX20106A是一款红外线检波接收的专用芯片,常用于电视机红外遥控接收器。当CX20106A接收到40KHz的信号时(第五脚200K的电阻决定了其频率为40KHz),会在OUT脚输出一个低电平下降脉冲。这个信号甚至可以接到单片机的外部中断引脚,作为中断信号的输入。

        2.注意事项

                ①需要先发送超声波信号,那么我们产生8个40KHz的信号(40KHz周期就是25us,由于是个奇数,所以取周期为24us,半个周期12us);

                ②超声波测距公式为:x = 340 *  t / 2 (m/s)。声音在空气中传播速度大约为340m/s,具体数值会随温度变化。注意单位,并且除以2是因为包括往返两次距离;

                ③满足测距的条件为接收端收到信号,并且定时器计数没有溢出。

二、所要实现的功能

        用超声波测距测出距离并且在数码管上进行显示。

三、代码实现

        1.  参数定义

#include <STC15F2K60S2.H>
#include "Delay_ms.h"
#include "intrins.h"


sbit TX = P1^0;				// 超声波发送端
sbit RX = P1^1;				// 超声波接收端
unsigned int distance = 0;	// 超声波测得距离

unsigned char code SMG_Duanma[19] = 
{
	0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,
	0x88,0x80,0xc6,0xc0,0x86,0x8e,0xbf,0x7f,0x00
};	// 0~F - . 全部

        2.138译码器通道选择函数

// 通道选择函数
void HC138_Init( unsigned char channel )
{
	switch( channel )
	{
		case 0:
			P2 = (P2 & 0x1f) | 0x00;	// 0
		break;
		case 4:
			P2 = (P2 & 0x1f) | 0x80;	// Y4C
		break;
		case 5:
			P2 = (P2 & 0x1f) | 0xa0;	// Y5C
		break;
		case 6:
			P2 = (P2 & 0x1f) | 0xc0;	// Y6C
		break;
		case 7:
			P2 = (P2 & 0x1f) | 0xe0;	// Y7C
		break;
	}
}

        3.初始化系统

// 初始化系统
void System_Init(void)
{
    // 关闭LED灯
	HC138_Init( 4 );
	P0 = 0xff;
 
    // 关闭蜂鸣器和继电器
	HC138_Init( 5 );
	P0 = 0xaf;		    // 1010 1111
	
    // 关闭通道选择
	HC138_Init( 0 );
}

        4.延时函数

void Delay_tms( unsigned int t )
{
	int i;
	while( t-- )
	{
		for( i=115 ; i>0 ; i-- )
		{}
	}
}

        5.单个数码管显示函数

// 数码管显示
void SMG_Light( unsigned char pos , unsigned char dat)
{
	HC138_Init( 6 );
	P0 = 0x01 << pos;
	HC138_Init( 7 );
	P0 = dat;
}

        6.数码管动态显示

// 数码管显示
void SMG_Show(void)
{
	SMG_Light( 0 , 0xff );
	Delay_tms( 5 );
	SMG_Light( 1 , 0xff );
	Delay_tms( 5 );
	SMG_Light( 2 , 0xff );
	Delay_tms( 5 );
	SMG_Light( 3 , 0xff );
	Delay_tms( 5 );
	SMG_Light( 4 , 0xff );
	Delay_tms( 5 );
	SMG_Light( 5 , SMG_Duanma[ distance / 100 ] );
	Delay_tms( 5 );
	SMG_Light( 6 , SMG_Duanma[ distance / 10 % 10 ] );
	Delay_tms( 5 );
	SMG_Light( 7 , SMG_Duanma[ distance % 10 ] );
	Delay_tms( 5 );
}

        7.定时器初始化函数

// 定时器0初始化
void Timer0_Init(void)
{
	TMOD = 0x00;
	ET0 = 1;
	TR0 = 0;
	EA = 1;
	
	TH0 = 0;
	TL0 = 0;
	
	TF0 = 0;	// 清除溢出标志位,当定时器0溢出时,TF0 = 1
}

        8.定时器0执行函数

// 定时器0执行函数
void Timer0() interrupt 1
{
	TH0 = 0;
	TL0 = 0;
}

        9.12us延时产生40KHz频率

// 12us延时,产生40KHz频率
void Delay12us()		//@11.0592MHz
{
	unsigned char i;

	_nop_();
	_nop_();
	_nop_();
	i = 30;
	while (--i);
}

        10.发送超声波信号函数

// 发送超声波信号,产生8个40KHz的信号(那么周期就是25us,由于是个奇数,所以取周期为24us,半个周期12us)
void Send_Wave(void)
{
	int i;
	for( i=0 ; i<8 ; i++ )
	{
		TX = 1;
		Delay12us();
		TX = 0;
		Delay12us();
	}
}

        11.计算测得距离函数

// 超声波测距-公式为:x = 340 *  t / 2 (m/s)。注意单位,并且除以2是因为往返距离
void Get_Distance(void)
{
	Send_Wave();	// 发送超声波信号
	
	TR0 = 1;		// 定时器0启动,开始测距
	while( ( RX == 1 ) && ( TF0 == 0 ) );	// 接收端收到信号,并且定时器计数没溢出
	TR0 = 0;		// 关闭定时器,计算时间
	
	if( TF0 == 0 )
	{
//		time = TH0;
//		time <<= 8;
//		time |= TL0;	// 获取时间t
//		distance = 340 * ( ( TH0 << 8 ) | TL0 ) / 1000000 / 2 * 100;	// 计算距离,乘以100是把米换算为厘米
		distance = ( ( TH0 << 8 ) | TL0 ) * 0.017;
		SMG_Show();
	}
	else
	{
		TF0 = 0;
		distance = 999;
		SMG_Show();
	}
	TH0 = 0;	// 时间清零
	TL0 = 0;
}

        12.完整代码

#include <STC15F2K60S2.H>
#include "Delay_ms.h"
#include "intrins.h"


sbit TX = P1^0;				// 超声波发送端
sbit RX = P1^1;				// 超声波接收端
unsigned int distance = 0;	// 超声波测得距离

unsigned char code SMG_Duanma[19] = 
{
	0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,
	0x88,0x80,0xc6,0xc0,0x86,0x8e,0xbf,0x7f,0x00
};	// 0~F - . 全部


// 通道选择函数
void HC138_Init( unsigned char channel )
{
	switch( channel )
	{
		case 0:
			P2 = (P2 & 0x1f) | 0x00;	// 0
		break;
		case 4:
			P2 = (P2 & 0x1f) | 0x80;	// Y4C
		break;
		case 5:
			P2 = (P2 & 0x1f) | 0xa0;	// Y5C
		break;
		case 6:
			P2 = (P2 & 0x1f) | 0xc0;	// Y6C
		break;
		case 7:
			P2 = (P2 & 0x1f) | 0xe0;	// Y7C
		break;
	}
}


// 初始化系统
void System_Init(void)
{
    // 关闭LED灯
	HC138_Init( 4 );
	P0 = 0xff;
 
    // 关闭蜂鸣器和继电器
	HC138_Init( 5 );
	P0 = 0xaf;		    // 1010 1111
	
    // 关闭通道选择
	HC138_Init( 0 );
}


// 12us延时
void Delay12us()		//@11.0592MHz
{
	unsigned char i;

	_nop_();
	_nop_();
	_nop_();
	i = 30;
	while (--i);
}


// 数码管显示
void SMG_Light( unsigned char pos , unsigned char dat)
{
	HC138_Init( 6 );
	P0 = 0x01 << pos;
	HC138_Init( 7 );
	P0 = dat;
}


// 数码管显示
void SMG_Show(void)
{
	SMG_Light( 0 , 0xff );
	Delay_tms( 5 );
	SMG_Light( 1 , 0xff );
	Delay_tms( 5 );
	SMG_Light( 2 , 0xff );
	Delay_tms( 5 );
	SMG_Light( 3 , 0xff );
	Delay_tms( 5 );
	SMG_Light( 4 , 0xff );
	Delay_tms( 5 );
	SMG_Light( 5 , SMG_Duanma[ distance / 100 ] );
	Delay_tms( 5 );
	SMG_Light( 6 , SMG_Duanma[ distance / 10 % 10 ] );
	Delay_tms( 5 );
	SMG_Light( 7 , SMG_Duanma[ distance % 10 ] );
	Delay_tms( 5 );
}


// 定时器0初始化
void Timer0_Init(void)
{
	TMOD = 0x00;
	ET0 = 1;
	TR0 = 0;
	EA = 1;
	
	TH0 = 0;
	TL0 = 0;
	
	TF0 = 0;	// 清除溢出标志位,当定时器0溢出时,TF0 = 1
}


// 定时器0执行函数
void Timer0() interrupt 1
{
	TH0 = 0;
	TL0 = 0;
}


// 发送超声波信号,产生8个40KHz的信号(那么周期就是25us,由于是个奇数,所以取周期为24us,半个周期12us)
void Send_Wave(void)
{
	int i;
	for( i=0 ; i<8 ; i++ )
	{
		TX = 1;
		Delay12us();
		TX = 0;
		Delay12us();
	}
}


// 超声波测距-公式为:x = 340 *  t / 2 (m/s)。注意单位,并且除以2是因为往返距离
void Get_Distance(void)
{
	Send_Wave();	// 发送超声波信号
	
	TR0 = 1;		// 定时器0启动,开始测距
	while( ( RX == 1 ) && ( TF0 == 0 ) );	// 接收端收到信号,并且定时器计数没溢出
	TR0 = 0;		// 关闭定时器,计算时间
	
	if( TF0 == 0 )
	{
//		time = TH0;
//		time <<= 8;
//		time |= TL0;	// 获取时间t
//		distance = 340 * ( ( TH0 << 8 ) | TL0 ) / 1000000 / 2 * 100;	// 计算距离,乘以100是把米换算为厘米
		distance = ( ( TH0 << 8 ) | TL0 ) * 0.017;
		SMG_Show();
	}
	else
	{
		TF0 = 0;
		distance = 999;
		SMG_Show();
	}
	TH0 = 0;	// 计算一次距离,时间清零一次
	TL0 = 0;
}




int main(void)
{
	System_Init();
	Timer0_Init();
	while(1)
	{
		Get_Distance();
	}
}

四、运行图片

  • 16
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

汽小迪

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值