蓝桥杯电子类单片机组模块——超声波测距

本文介绍了一种在蓝桥杯比赛中可能使用的超声波测距模块的使用方法,包括硬件连接和软件编程。文章详细解释了如何通过单片机控制超声波模块进行距离测量。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一般而言,在单片机组的比赛中只有在国赛的时候才会出现超声波测距模块。但是在第十届蓝桥杯比赛的时候却意外出现了频率计模块,导致很多选手因为没有充分准备相应的模块而摔跟头。所以我认为,超声波模块还是有可能出现在省赛当中的,毕竟蓝桥杯的题目正在变得越来越灵活多变了。下面我来介绍一下超声波模块的代码编写!

  • 超声波模块硬件电路

超声波原理图我们看到有2个电路分别控制JS1和JS2,就是接收和发射模块JS1由N B1控制JS2由N A1控制
然后这2个口由JUMP6跳线组控制,所以要把跳线帽接到13&24所以我们只要控制P1^0 P1^1。

  • 代码设计

由单片机产生12个40KHZ的脉冲信号,加到超声波探头的引脚上,使内部的压电晶片产生共振,向外发射超声波。 因此程序方面,需要有超声波发生程序。
接收原理:当接收到38k的发射信号后,接收引脚将由高电平变为低电平,因此程序的设计可以启用一个定时器,在发射的时候清空定时器的初值,然后开始发送超声波并且开启计时,当引脚电平变为低电平的时候则结束计时,并通过定时器来计算发射到接收的时间,用测试距离=(高电平时间*声速(340M/S))/2;即可计算出距离!
大家可以先参考一下标准程序模板(独立按键)的代码块:
http://blog.csdn.net/qq_44629819/article/details/107937826
接下来以上述代码块为蓝本,写下超声波模块的实现程序。

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

#define u8 unsigned char
#define u16 unsigned int

#define NO_KEY 0xF0
#define KEY_STATE0 0
#define KEY_STATE1 1
#define KEY_STATE2 2

#define LED0 0x00
#define LED1 0x01
#define LED2 0x01<<1
#define LED3 0x01<<2
#define LED4 0x01<<3
#define LED5 0x01<<4
#define LED6 0x01<<5
#define LED7 0x01<<6
#define LED8 0x01<<7

#define NO_THING 0x00
#define BUZZER 0x40
#define RELAY 0x10
#define BU_RE 0x50

/*********added*********/
sbit TX=P1^0;//定义反射脚
sbit RX=P1^1;//定义接收脚
/*********added*********/

/***************************************本地常量声明**********************************/
u8 code smg_du[]={//标准字库
//   0    1    2    3    4    5    6    7    8    9    A    B    C    D    E    F
    0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71,
//black  -     H    J    K    L    N    o   P    U     t    G    Q    r   M    y
    0x00,0x40,0x76,0x1E,0x70,0x38,0x37,0x5C,0x73,0x3E,0x78,0x3d,0x67,0x50,0x37,0x6e};
u8 code smg_point[]={0xBF,0x86,0xDB,0xCF,0xE6,0xED,0xFD,0x87,0xFF,0xEF,0x46};//0. 1. 2. 3. 4. 5. 6. 7. 8. 9. -1
u8 code smg_wei[]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};//位码
u8 code led_du[]={LED0,LED1,LED2,LED3,LED4,LED5,LED6,LED7,LED8};
u8 code bure_du[]={NO_THING,RELAY,BUZZER,BU_RE};

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

/*********added*********/
//定时器1;16位自动重装载;12T模式;12.000MHz//
void Timer1Init(void)		//该定时器用来记录时间,没有进入中断
{
	AUXR &= 0xBF;		//12T
	TMOD |= 0x00;		//设置定时器模式//特别注意,需要自己写TMOD |= 0x00;
	TL1 = 0;		//设置定时初值//特别注意,需要自己写0
	TH1 = 0;		//设置定时初值//特别注意,需要自己写0
	TF1 = 0;		//清除TF1标志
	TR1 = 0;		//定时器1开始计时//特别注意,需要自己写0
}
/*********added*********/


unsigned char key_scan()
{
	static u8 key_state=KEY_STATE0;//设置按键状态为全局变量,方便函数外读取。
	u8 key1,key_temp,key_val;
	P30=1;P31=1;P32=1;P33=1;P44=0;
	if(P30==0) key1=0x10;
	if(P31==0) key1=0x20;
	if(P32==0) key1=0x30;
	if(P33==0) key1=0x40;
	if((P30==1)&&(P31==1)&&(P32==1)&&(P33==1)) key1=0xf0;
	key_temp=key1;
	
	switch(key_state)
	{
		case KEY_STATE0:
			if(key_temp!=NO_KEY)
			{	
				key_state=KEY_STATE1;
			}
		break;
		
		case KEY_STATE1:
			if(key_temp==NO_KEY)
			{	
				key_state=KEY_STATE0;
			}
			else
			{
				key_state=KEY_STATE2;
				switch(key_temp)
				{
					case 0x10:key_val=7;break;
					case 0x20:key_val=6;break;
					case 0x30:key_val=5;break;
					case 0x40:key_val=4;break;
				}
			}
		break;
		case KEY_STATE2:
			if(key_temp==NO_KEY)
			{	
				key_state=KEY_STATE0;
			}
		break;
	}
	
	return key_val;
}

/*********added*********/
void Delay12us()		//@12.0MHz(进行一个12微秒的延时)
{
	unsigned char i;

	_nop_();
	_nop_();
	i = 33;
	while (--i);
}
/*********added*********/

/*********added*********/
void send_wave(void)//发射2个方波
{
	u8 i;
	for(i=0;i<2;i++)
	{
		TX=1;
		Delay12us();
		TX=0;
		Delay12us();
	}
}
/*********added*********/

bit key_flag=0;//按键读取标志位
u8 key_value;//按键键值
u8 led_choose=0;//LED1灯选择
u8 bure_choose=0;//ULN2003选择

/*********added*********/
bit sonic_flag=0;//超声波发送标志位
unsigned int distance;//存储超声波检测到的距离数值
u8 smg_sonic[8];//数码管显示距离
/*********added*********/

void main()
{

	Timer0Init();
	Timer1Init();
	while(1)
	{

		if(key_flag)
		{
			key_flag=0;
			key_value=key_scan();
			switch(key_value)
			{
				case 4:  break;
				case 5:  break;
				case 6:  break;
				case 7:	 break;
			}
		}
		
	/*********added*********/	
		if(sonic_flag)
		{
			sonic_flag=0;
			send_wave();
			TR1=1;//定时器1打开
			while((TF1==0)&&(RX==1));//满足接收到了信号并且定时器1计数值未溢出
			TR1=0;//定时器1关闭
			
			if(TF1==1)//若程序是因为定时器1计数值溢出,那么将对应标志位置为0
			{
				TF1=0;
				distance=999;
			}
			else//正常情况下
			{
				distance=(unsigned int)(((TH1<<8)|TL1)*0.017);//将定时器1中的计数值转换为十进制的距离数值
			}
			
			TH1=0;//清空寄存器数值
			TL1=0;//清空寄存器数值
		}
		
				smg_sonic[0]=smg_du[distance/100];
				smg_sonic[1]=smg_du[distance/10%10];
				smg_sonic[2]=smg_du[distance%10];
		/*********added*********/
		
	}
}

void timer0() interrupt 1 using 1
{
	static u16 key_count=0,display_count=0,i=0,sonic_count=0;	
/***************************************按键定时器中断**********************************/
	key_count++;
	if(key_count==10)
	{
		key_count=0;
		key_flag=1;
	}
/***************************************显示定时器中断**********************************/
	display_count++;
	if(display_count==1)
	{
		P0=~led_du[led_choose];P2=0x80;P2=0x00;
	}
	
	if(display_count==2)
	{
		P0=bure_du[bure_choose];P2=0xA0;P2=0x00;
	}
	
	if(display_count==3)
	{
		display_count=0;
		P2=0XE0;P0=~0X00;P2=0X00;
		P2=0XC0;P0=smg_wei[i];P2=0X00;
		P2=0XE0;P0=~smg_sonic[i];P2=0X00;//显示距离
		i++;
		if(i==8) i=0;
	}
	
/*********added*********/
	sonic_count++;
	if(sonic_count==50)//每50ms进行一次超声波发送·
	{
		sonic_count=0;
		sonic_flag=1;
	}
/*********added*********/
	
}


定时器0:定时器0的作用是为固定的时间间隔进行超声波测量;因为如果两次间隔时间太短会影响测量的;定时器1:定时器寄存器TMOD 的复位值为0x00;所以定时器1工作在计时 方式0(16位自动重装)而且 TCON的复位值也是0x00;即TH1==TL1=0;所以定时1不用配置也能用;因为我的代码没有配置定时器1;所以我啰嗦的写了这一条;当然自己可以配置定时器1的完全不影响使用的;

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Elec Liu

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

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

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

打赏作者

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

抵扣说明:

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

余额充值