蓝桥杯之单片机设计与开发(21)——超声波测距

版权声明:让结局不留遗憾,让过程更加完美。 https://blog.csdn.net/Xiaomo_haa/article/details/88081708

关于超声波这一部分,在省赛阶段是不会考的,在国赛可能会考。

关于超声波这一块,具体原理就是,使用单片机发送8个40KHz的脉冲,然后开启定时器计时,计算从发送到接收的时间,然后当接受管脚接收到回波之后就会被拉低,这时候关闭定时器,就可以算出距离。

所以我们在超声波这一块,还涉及定时器。

但是定时器的程序很简单。

下面是发送脉冲的程序

#define sonic_nop {_nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_();};

void SendSonic(void)
{
	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;
	}
}

然后检测是否接收到的程序

#include "sys.h"

bit flag_125ms = 0;

void main(void)
{
	uint t, distance = 0;
	
	All_Init();
	Time0_Init();
	Timer1Init();
	EA = 1;
	while(1)
	{
		if(flag_125ms)
		{
			flag_125ms = 0;
			SendSonic();			//发送50KHz的超声波	
			TR1 = 1;					//开启定时器1计时
			while((RX == 1) && (TF1 == 0));	//如果接收到回波或者定时器1溢出
			TR1 = 0;					//关闭定时器1
			if(TF1 == 1)
			{
				TF1 = 0;
				distance = 999;	//距离999
			}
			else
			{
				t = TH1;
				t <<= 8;
				t |= TL1;
				distance = (uint)(t * 0.017);
			}
			Deal_distance(distance);
			TH1 = 0;
			TL1 = 0;
		}
	}
}

定时器程序

#include "sys.h"

//关闭所有外设
void All_Init(void)
{
	P2 = (P2 & 0x1f) | 0x80;	//打开Y4C(LED)
	P0 = 0xff;					//关闭LED
	P2 = (P2 & 0x1f) | 0xe0;	//打开Y7C(数码管)
	P0 = 0xff;					//关闭数码管
	P2 = (P2 & 0x1f) | 0xa0;	//打开Y5C
	P0 = 0x00;					//关闭蜂鸣器、继电器
	P2 = P2 & 0x1f;
}

//定时器0初始化
void Time0_Init(void)
{
	AUXR |= 0x80;	//定时器时钟1T模式
	TMOD &= 0xF0;	//设置定时器模式
	TL0 = 0xcd;		//设置定时初值1ms
	TH0 = 0xd4;		//设置定时初值1ms
	TF0 = 0;		//清除TF0标志
	ET0 = 1;		//允许定时器0中断
	TR0 = 1;		//定时器0开始计时
}

//定时器0中断程序
void Time0(void) interrupt 1
{
	static uint t0 = 0;
	static uchar index = 0;

	t0 ++;

	if(t0 == 125)
	{
		t0 = 0;
		flag_125ms = 1;
		Led_illume(0xfe << index);
		
		index ++;
		index &= 0x07;
	}
	
	Nixie_Show();
	Nixie_Scan();
}

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


在这里说一下我刚刚调试程序时遇到的问题,我在定义定时器1时是这样写的

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

在这里我允许了定时器1中断,但是我并没有写定时器1中断服务程序,然后在正常接收到回波时正常,一旦定时器1溢出,程序就会卡死,后来就发现不需要允许定时器1中断,即如下面这样写就可以了。。

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

坑爹啊坑爹!

猜你喜欢

转载自blog.csdn.net/Xiaomo_haa/article/details/88081708
今日推荐