蓝桥杯单片机超声波模块

程序设计流程

  • 综述
    • 模板搭建
    • 程序设计
      • 原理图
      • 系统设计

综述

CT107D单片机的超声波模块需要熟练掌握定时器部分。

纯作分享,若有不足,望在评论区进行指正!

模板搭建

基础的功能:
1、独立按键
2、数码管显示

可以独立于赛题,提前写好,适用于各类赛题,仅做修改即可。

模板部分代码与解释在第三届赛题分享中 模板代码

程序设计

原理图

官方提供的CT107D原理图部分有超声波板块的描述。
蓝桥杯单片机超声波模块_第1张图片
1-3 2-4 相连时代表超声波模块,而在该图的左侧可以找到对应的A1与B1口:
蓝桥杯单片机超声波模块_第2张图片
A1口对应的是发射模块,可以看到JS2下面有一个T,即发射。也就是与A1相连的P10即为发射口。
蓝桥杯单片机超声波模块_第3张图片
对应的,B1口就是接收模块,下面有一个R。P11就是接收口。

系统设计

具体流程:
启动超声波模块,发出超声波->同步开启计时->接收到返回的信号 / 或者规定时间内没有接收到返回的信号 -> 计算相应的超声波运动距离,显示测距结果

代码:

#include 
#include 
#include 

#define uchar unsigned char
#define somenop {_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_(); _nop_();}

uchar keyPressFlag[4] = {0, 0, 0, 0};
uchar keyPress[4] = {0, 0, 0, 0};

uchar code shapeOfNum[11] = {0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x90, 0xbf};
uchar numGrp[8] = {11, 11, 11, 11, 11, 11, 11, 11};

int count = 0, flag = 1;

sbit TX = P1^0;
sbit RX = P1^1;

void Delay5ms(){
	unsigned char i, j;

	i = 54;
	j = 199;
	do
	{
		while (--j);
	} while (--i);
}

void Delay1ms(){
	unsigned char i, j;

	_nop_();
	_nop_();
	_nop_();
	i = 11;
	j = 190;
	do
	{
		while (--j);
	} while (--i);
}
void Delay12us(){
	unsigned char i;

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

void keyScan(){
	uchar i;
	for(i = 0; i < 4; i ++) keyPress[i] = 0;
	if((P3 & 0x0f) != 0x0f){
		Delay5ms();
		if((P3 & 0x0f) != 0x0f){
			switch(P3 & 0x0f){
				case 0x0e:keyPressFlag[0] = 1;break;
				case 0x0d:keyPressFlag[1] = 1;break;
				case 0x0b:keyPressFlag[2] = 1;break;
				case 0x07:keyPressFlag[3] = 1;break;
			}
		}
	}
	for(i = 0; i < 4; i ++){
		if(keyPressFlag[i] != 0){
			if((P3 & 0x0f) == 0x0f){
				keyPress[i] = 1;
				keyPressFlag[i] = 0;
			}
		}
	}
}

void showNum(){
	uchar i;
	for(i = 0; i < 8; i ++){
		if(numGrp[i] != 11){	
			XBYTE[0xc000] = (0x01 << i);
			XBYTE[0xe000] = shapeOfNum[numGrp[i]];
			Delay1ms();		
		}
		else Delay1ms();
	}
	XBYTE[0xc000] = 0x00;
}


void Timer0Init(void){
	AUXR |= 0x80;		//定时器时钟1T模式
	TMOD &= 0xF0;		//设置定时器模式
	TL0 = 0x00;		//设置定时初值
	TH0 = 0x00;		//设置定时初值
}
void Timer1Init(void){
	AUXR |= 0x40;		//定时器时钟1T模式
	TMOD &= 0x0F;		//设置定时器模式
	TL1 = 0x00;		//设置定时初值
	TH1 = 0x28;		//设置定时初值
	TF1 = 0;		//清除TF1标志
	TR1 = 1;		//定时器1开始计时
}



//TX引脚发送40KHz方波信号驱动超声波发送探头
void sendWave(){
	unsigned char i = 8;  //发送8个脉冲
	do
	{
		TX = 1;
		somenop;somenop;somenop;somenop;somenop;somenop;somenop;somenop;somenop;somenop;		
		TX = 0;
		somenop;somenop;somenop;somenop;somenop;somenop;somenop;somenop;somenop;somenop;		
	}
	while(i--);
}

void timer1() interrupt 3{
	if(count == 39){
		count = 0;
		flag = 1;
	}
	else count ++;
}

void main(){
	
	unsigned int dis;//定义距离变量(单位为厘米cm)
	unsigned int t;//定义时间变量
	//最高计算距离 5.9259ms * 340 / 1000 * 100 / 2 = 100.7403cm

	XBYTE[0xa000] = 0x00;
	XBYTE[0x8000] = 0xff;
	
	Timer1Init();//5ms 定时器初始化
	EA = 1;ET0 = 0;ET1 = 1;
	while(1){
		//keyScan();
		if(flag == 0){
			showNum();
			continue;
		}
		else{
			flag = 0;
		}
		
		Timer0Init();
		sendWave();//启动超声波模块
		TR0 = 1;//开启计时器
		
		while((RX == 1) && (TF0 == 0));
		//当接收到超声波时,RX为0,退出循环进入下一步
		//当计时器溢出时,代表规定时间2ms内没有收到返回的超声波,测距超过范围
		
		TR0 = 0;//关闭计时器
		
		if(TF0 == 1){
			//如果情况为计时器溢出,则清空溢出位,dis记为999
			TF0 = 0;
			dis = 999;
		}
		else{
			t = TH0;t <<= 8;t |= TL0;
			//如果接收到了信号,则记录计时器的计时
			dis = (unsigned int)(t * 0.0184);
			dis = (unsigned int)(dis / 12);
			//11.0596MHz晶振频率 -> 机器频率为晶振的时钟频率 / 12
			//一个机器周期即为 -> 12 / (11.0596 * 1000000)
			//所以t此时存储的是定时器的计数个数,每一个计数个数相当于一个机器周期,所以时长为: t * 12 / (11.0596 * 1000000)
			//超声波的速度为34000cm/s 然后一去一回,所以要除以二,所以距离计算公式为
			//dis = t * 3.4 * 10000 / 2 * 12 / (11.0596 * 1000000) = (t * 1.7 * 12 / 11.0596) / 100 = t * 0.0184
			//由于15的定时器比52的快12倍,因此dis还需要除以12。
		}
		numGrp[5] = (dis / 100) % 10;
		numGrp[6] = (dis / 10) % 10;
		numGrp[7] = dis % 10;
		
		showNum();
	}
}

你可能感兴趣的:(蓝桥杯单片机,蓝桥杯,单片机,超声波测距)