09 蓝桥杯单片机设计与开发_基础模块_超声波测距

一、前言

08 蓝桥杯单片机设计与开发_基础模块_NE555-CSDN博客,承接上文,本文将介绍最后一个蓝桥杯模块(超声波测距),为大家做出详细编程指导。

二、超声波测距

超声波指的是频率超过人类可听范围(20千赫兹)的声波。超声波的产生和接收主要依靠超声波传感器,其通常由一个发射器和一个接收器组成。
通过 距离 = 声速 × 时间 / 2 可计算得到测距值。

1、超声波原理剖析

超声波的距离计算原理为:超声波发射和接收所需时间乘以声速即为距离(声速为 340m/s)

 distance = t*0.000001(1us)*340/2(往返)*100(换算成厘米) = t * 0.017

2、核心代码

超声波计时初始化函数 可借助 STC-ISP 软件生成,选择 定时器计算器,配置好所需参数,如 定时器0 、 定时器时钟12T,即可自动生成串口初始化程序。

![[Pasted image 20231125221334.png]]

//定时器0、12T时钟,用于超声波测距
void Timer0Init(void) // 12us@12.000MHz    频率:40KHZ,1/40000 = 25us,其中高电平12.5us,低电平12.5us,约12us
{ 
	AUXR &= 0x7F;    // 定时器时钟12T模式 △
	TMOD &= 0xF0;    // 设置定时器模式
	TL0 = 0xF4;      // 设置定时初值
	TH0 = 0xFF;      // 设置定时初值
	TF0 = 0;         // 清除TF0溢出标志位
	TR0 = 0;         // 关闭定时器0  △
} 

超声波接收函数 具体代码功能均已注释,在此不再赘述。

// 超声波接收函数
u8 Wave_recv(void) 
{
	 u8 distance,count = 10; 
	 
	 TX = 0;           // 发射引脚置0
	 TL0 = 0xF4;       // 设置定时初值
	 TH0 = 0xFF;       // 设置定时初值
	 TR0 = 1;          // 打开定时器 0
	
	 // TX 引脚发送 40kHz 方波信号驱动超声波发送探头
	 while(count--) 
	 {
		 while(!TF0);    // TF0溢出标志位为0是卡死,直至TF0满12us溢出,跳出循环
		 TX ^= 1;        // 发送信号翻转
		 TF0 = 0;        // 溢出标志位清零
	 }
	 
	 TR0 = 0;          // 关闭定时器0,将其再次赋初值
	 TL0 = 0;          // 设置定时初值
	 TH0 = 0;          // 设置定时初值
	 TR0 = 1;          // 打开定时器0
	 
	 while(RX && !TF0);  // 等待收到脉冲,收到脉冲时RX将产生低电平,将跳出循环。并开始计时,1us计数加一
	 TR0 = 0;            // 关闭定时器0,此时TL0、TH0被记录下来
	 
	 if(TF0)           // 测距大于1m时,发生溢出
	 { 
		 TF0 = 0;        // 标志位清零
		 distance = 255;   // 即0xff,表示超出测量范围
	 } 
	 else              // 计算距离
		distance = ((TH0<<8)+TL0)*0.017;   // t*0.000001(1us)*340/2(往返)*100(换算成厘米) = t * 0.017

	 return distance; 
}

3、整体代码

由于考虑初学者基础较为薄弱,因此将完整的 main.cpp 代码贴出来,包含中断函数、矩阵键盘、数码管显示等,并且在关键处进行了注释,希望对大家有所帮助。

// 包含头文件
#include "STC15F2K60S2.h" 
// 数据类型定义
#define u8 unsigned char
#define u16 unsigned int
// 8位数码管状态
u8 dspbuf[8] = {10,10,10,10,10,10,10,10};  
u8 code tab[] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xff,0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10};
	             // 0     1    2    3    4    5    6    7    8    9    10   11   12   13   14   15   16  17   18   19   20       
u8 dspcom = 0;
bit key_flag = 0;
	
//
sbit TX = P1^0;    // 超声波发射引脚
sbit RX = P1^1;    // 超声波接收引脚
//

// 573锁存器封装成函数
void door(u8 choose,input)
{
	P2 = (P2 & 0x1f) | choose;
	P0 = input;
	P2 &= 0x1f;	
}
// 数码管关闭函数
void clo_num()
{
	dspbuf[0] = 10;
	dspbuf[1] = 10;
	dspbuf[2] = 10;
	dspbuf[3] = 10;
	dspbuf[4] = 10;
	dspbuf[5] = 10;
	dspbuf[6] = 10;
	dspbuf[7] = 10;
}
// 关灯、蜂鸣器
void all_init()
{
 	door(0x80,0xff);
	door(0xa0,0xaf);
	clo_num();
}
// 数码管显示函数
void display()
{			  
	door(0xe0,0xff);

	door(0xc0,0x01<<dspcom);
	door(0xe0,tab[dspbuf[dspcom++]]);
	
	if(dspcom >= 8)
		dspcom = 0;
}

// 定时器1初始化,用于按键、数码管显示等
void Timer1Init(void)		//2毫秒@12.000MHz
{
	AUXR |= 0x40;		//定时器时钟1T模式
	TMOD &= 0x0F;		//设置定时器模式
	TL1 = 0x40;		//设置定时初值
	TH1 = 0xA2;		//设置定时初值
	TF1 = 0;		//清除TF1标志
	TR1 = 1;		//定时器1开始计时
	
	ET1 = 1;
	EA = 1;
}

//定时器0、12T时钟,用于超声波测距
void Timer0Init(void) // 12us@12.000MHz    频率:40KHZ,1/40000 = 25us,其中高电平12.5us,低电平12.5us,约12us
{ 
	AUXR &= 0x7F;    // 定时器时钟12T模式 △
	TMOD &= 0xF0;    // 设置定时器模式
	TL0 = 0xF4;      // 设置定时初值
	TH0 = 0xFF;      // 设置定时初值
	TF0 = 0;         // 清除TF0溢出标志位
	TR0 = 0;         // 关闭定时器0  △
} 

// 超声波接收函数
u8 Wave_recv(void) 
{
	 u8 distance,count = 10; 
	 
	 TX = 0;           // 发射引脚置0
	 TL0 = 0xF4;       // 设置定时初值
	 TH0 = 0xFF;       // 设置定时初值
	 TR0 = 1;          // 打开定时器 0
	
	 // TX 引脚发送 40kHz 方波信号驱动超声波发送探头
	 while(count--) 
	 {
		 while(!TF0);    // TF0溢出标志位为0是卡死,直至TF0满12us溢出,跳出循环
		 TX ^= 1;        // 发送信号翻转
		 TF0 = 0;        // 溢出标志位清零
	 }
	 
	 TR0 = 0;          // 关闭定时器0,将其再次赋初值
	 TL0 = 0;          // 设置定时初值
	 TH0 = 0;          // 设置定时初值
	 TR0 = 1;          // 打开定时器0
	 
	 while(RX && !TF0);  // 等待收到脉冲,收到脉冲时RX将产生低电平,将跳出循环。并开始计时,1us计数加一
	 TR0 = 0;            // 关闭定时器0,此时TL0、TH0被记录下来
	 
	 if(TF0)           // 测距大于1m时,发生溢出
	 { 
		 TF0 = 0;        // 标志位清零
		 distance = 255;   // 即0xff,表示超出测量范围
	 } 
	 else              // 计算距离
		distance = ((TH0<<8)+TL0)*0.017;   // t*0.000001(1us)*340/2(往返)*100(换算成厘米) = t * 0.017

	 return distance; 
}

// 主函数
void main()
{
	u8 distance;
	// 初始化
	all_init();
	Timer1Init();
	Timer0Init();
	
	while(1)
	{
		// 20ms接收一次超声波,并进行数码管显示测距值
		if(key_flag)
		{
			key_flag = 0;
			// 超声波接收
			distance = Wave_recv();
			// 数码管显示测距值
			dspbuf[5] = distance/100;
			dspbuf[6] = distance%100/10;
			dspbuf[7] = distance%10;
		}
	}
}

// 定时器1中断服务函数
void timer1() interrupt 3
{
	static u8 t_20ms = 0;
	
	display();
	
	t_20ms++;
	// 20ms键盘扫描
	if(t_20ms >= 10)
	{
		t_20ms = 0;
		key_flag = 1;
	}
}

至此,本次 蓝桥杯所有模块 均已介绍完毕,由于笔者最近学业比较忙,后面几期内容撰写过于仓促,大家如果阅读有任何疑问均可提问,希望对大家有所帮助!

  • 12
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

_小猪沉塘

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

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

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

打赏作者

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

抵扣说明:

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

余额充值