51单片机:HCSR04超声波测距模块及1602显示—C51程序(超详细)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/belous_zxy/article/details/81814748

测试完成于STC89C516单片机,晶振12MHZ。超声波模块Echo=P1^0、Trig=P1^1,1602液晶8位数据口=P0、E=P2^7、RS=P2^6、RW=P2^5.。

程序文件分为4部分,Cprogram.c、Lcd1602.h(Lcd1602函数)、CSBofCM.h(超声波测距模块函数)、STCY1_Delay.h(可能用到的延迟函数)

>>具体实现见注释

 

Cprogram.c

#include<Lcd1602.h>
#include<CSBofCM.h>
//#include<STCY1Delay.h>
#ifndef udata
	typedef unsigned char uchar;
	typedef unsigned int uint;
	typedef unsigned long ulong;
#endif
void main(void)
{
	uchar i;
	code uchar array[]="CSB of CM Test";
	Lcd1602_Init();
	CSB_Init();
	for(i=0;array[i];i++)
		Lcd1602_WriteDC(array[i],1);
	while(1)
	{
		CSB_UseLcd1602Show(CSB_GetOnce());
		Delay100ms();
	}
	return;
}

Lcd1602.h

#include<reg51.h>
#ifndef udata
	#define udata
	typedef unsigned char uchar;
	typedef unsigned int uint;
	typedef unsigned long ulong;
#endif

#define Lcd1602_DATA P0//8位数据口
sbit Lcd1602_E=P2^7;//使能端
sbit Lcd1602_RS=P2^6;//指令or数据
sbit Lcd1602_RW=P2^5;//写入or读出
sbit Lcd1602_Busy=Lcd1602_DATA^7;

/*****************Lcd1602.h**************/
/*****************可用函数***************/
/************编写于2018/08/18************/
/**************作者:Belous**************/
/*******测试应用与STC89C516——12MHZ*******/
void Lcd1602_Init(void);//初始化Lcd1602
void Lcd1602_WriteDC(uchar com,uchar control);
//向Lcd1602写入指令或数据,control=0指令,control=1数据;
//进行数据写入操作后,光标会按预设左移或右移
uchar Lcd1602_ReadDC(uchar control);
//从Lcd1602读出状态或数据,control=0状态,control=1数据
//读取状态,D7是读写检测端、D0-D6为当前数据指针的数值
//读取数据,返回当前数据指针处字节,不会改变数据指针,须自行移位
void Lcd1602_Firstrow(void);//调整位置-第一行
void Lcd1602_Secondrow(void);//调整位置-第二行——!须确保开启两行模式!
void Lcd1602_MoveSP(uchar sp);//改变数据指针为指定数值
/****************************************/

void Lcd1602_Init(void)
{
	//所有指令
	Lcd1602_WriteDC(0x38,0);//2行和5*7矩阵(数据总线8位)
	//Lcd1602_WriteDC(0x30,0);//1行和5*7矩阵(数据总线8位)
	//Lcd1602_WriteDC(0x3C,0);//2行和5*10矩阵(数据总线8位)
	//Lcd1602_WriteDC(0x34,0);//1行和5*10矩阵(数据总线8位)
	Lcd1602_WriteDC(0x01,0);//清除显示屏幕
	//Lcd1602_WriteDC(0x02,0);//归起始位
	//Lcd1602_WriteDC(0x04,0);//光标左移
	Lcd1602_WriteDC(0x06,0);//光标右移
	//Lcd1602_WriteDC(0x05,0);//显示右移
	//Lcd1602_WriteDC(0x07,0);//显示左移
	//Lcd1602_WriteDC(0x08,0);//显示关,光标关
	//Lcd1602_WriteDC(0x0A,0);//显示关,光标开
	Lcd1602_WriteDC(0x0C,0);//显示开,光标关
	//Lcd1602_WriteDC(0x0E,0);//显示开,光标闪
	//Lcd1602_WriteDC(0x10,0);//光标位置左移
	//Lcd1602_WriteDC(0x14,0);//光标位置右移
	//Lcd1602_WriteDC(0x18,0);//整个显示左移
	//Lcd1602_WriteDC(0x1C,0);//整个显示右移
	Lcd1602_WriteDC(0x80,0);//使光标到第一行起点
	//Lcd1602_WriteDC(0xC0,0);//使光标到第二行起点
}
void Lcd1602_Delay(uint c)//1602延迟1us,测试通过于11.0592MHZ
{
	uchar a,b;
	for (; c>0; c--)
	{
		 for (b=199;b>0;b--)
		 {
				for(a=1;a>0;a--);
		 }      
	}
}
void Lcd1602_Ready(void)
{
	Lcd1602_Busy=1;//使输入
	Lcd1602_RS=0;//命令
	Lcd1602_RW=1;//读出
	Lcd1602_E=1;
	while(Lcd1602_Busy)
	{
		Lcd1602_E=0;
		Lcd1602_Delay(1);
		Lcd1602_E=1;
	}
	return;
}
void Lcd1602_WriteDC(uchar com,uchar control)
{
	Lcd1602_Ready();
	if(control)
		Lcd1602_RS=1;//数据
	else
		Lcd1602_RS=0;//命令
	Lcd1602_RW = 0;//写入
	Lcd1602_DATA = com;
	Lcd1602_Delay(1);
	Lcd1602_E = 1;
	Lcd1602_Delay(5);
	Lcd1602_E = 0;//Lcd得到信息
}
uchar Lcd1602_ReadDC(uchar control)
{
	Lcd1602_DATA=0xFF;//I/0口至输入模式
	Lcd1602_Ready();
	if(control)
		Lcd1602_RS = 1;//读取数据
	else
		Lcd1602_RS = 0;//读取状态
	Lcd1602_RW = 1;
	Lcd1602_Delay(1);
	Lcd1602_E = 1;
	return Lcd1602_DATA;
}
void Lcd1602_Firstrow(void)
{
	Lcd1602_WriteDC(0x80,0);//使光标到第一行起点
	return;
}
void Lcd1602_Secondrow(void)
{
	//Lcd1602_WriteDC(0x38,0);//确保可以显示第二行
	Lcd1602_WriteDC(0xC0,0);//使光标到第二行起点
	return;
}
void Lcd1602_MoveSP(uchar sp)
{
	Lcd1602_WriteDC(sp+0x80,0);
	return;
}

CSBofCM.h

#include<reg51.h>
#include<STCY1Delay.h>
//#include<Lcd1602.h>
#ifndef udata
	#define udata
	typedef unsigned char uchar;
	typedef unsigned int uint;
	typedef unsigned long ulong;
#endif

sbit Echo=P1^0;//接受端
sbit Trig=P1^1;//控制端
uchar flag;//中断溢出标志

/*****************CSBofCM.h**************/
/*****************可用函数***************/
/************编写于2018/08/18************/
/**************作者:Belous**************/
/*******测试应用与STC89C516——12MHZ*******/
void CSB_Init(void);//初始化CSB(初始化定时器T0)
float CSB_GetOnce(void);//得到一次超声波测距模块的距离
void CSB_UseLcd1602Show(float distance);//显示距离到Lcd1602的第二行
/****************************************/

void CSB_UseLcd1602Show(float distance)
{
	uchar i,f1,f2,f3,f4;
	code uchar array1[]=" Overflow Show  ";
	code uchar array2[]=" CM             ";
	//Lcd1602_Init();//是否需要初始化?
	Lcd1602_Secondrow();//将在第二行显示
	if((distance>=700)||flag==1) //超出测量范围显示"Overflow Show"
	{	 
		flag=0;//清空中断溢出标志
		for(i=0;array1[i];i++)
			Lcd1602_WriteDC(array1[i],1);
	}
	else
	{
		f1=(uint)distance/100;//百位
		f2=(uint)distance/10%10;//十位
		f3=(uint)distance%10;//个位
		f4=(uint)(distance*10)%10;
		Lcd1602_WriteDC(f1+0x30,1);
		Lcd1602_WriteDC(f2+0x30,1);
		Lcd1602_WriteDC(f3+0x30,1);
		Lcd1602_WriteDC('.',1);
		Lcd1602_WriteDC(f4+0x30,1);
		for(i=0;array2[i];i++)
			Lcd1602_WriteDC(array2[i],1);
	}
}
float CSB_GetDistance(void)
{
	uint time=TH0*256+TL0;//得到总时间,单位us
	float distance=(float)(time*0.017);
	TH0=0;
	TL0=0;//清空定时器
	return distance;
}
void CSB_Time0() interrupt 1 //T0中断用来计数器溢出,超过测距范围
{
    flag=1;
}
void CSB_Rstart()//启动模块
{
	Trig=1;
	Delay20us();
	Trig=0;
	return;
}
void CSB_Init(void)
{
	TMOD=0x01;
	TH0=0;
	TL0=0;
	EA=1;          
	ET0=1;
}
float CSB_GetOnce(void)//得到一次超声波测距模块的距离
{
	CSB_Rstart();
	while(!Echo);//当Echo为零时等待
	TR0=1;//开启计数
	while(Echo);//当Echo为1计数并等待
	TR0=0;//关闭计数
	return CSB_GetDistance();//计算
}



                

STCY1_Delay.h

#include<intrins.h>
#ifndef udata
	#define udata
	typedef unsigned char uchar;
	typedef unsigned int uint;
	typedef unsigned long ulong;
#endif

/****************STCY1Delay.h************/
/*****************可用函数***************/
/************编写于2018/08/18************/
/**************作者:Belous**************/
/*******测试应用与STC89C516——12MHZ*******/
void Delay5us();
void Delay10us();
void Delay20us();
void Delay30us();
void Delay50us();
void Delay100us();
void Delay200us();	
void Delay500us();
void Delay1ms();
void Delay2ms();
void Delay5ms();
void Delay10ms();
void Delay20ms();
void Delay30ms();
void Delay50ms();
void Delay70ms();
void Delay100ms();
void Delay200ms();	
void Delay500ms();
void Delay1s();
void Delay2s();
void Delay5s();
void Delay10s();
/*针对于STC SY1指令集(STC89/STC90)-12MHZ*/
/******!需要用上面哪个定义它的宏!******/
/*********格式 #define D数值单位*********/

#define D20us
#define D100ms

/****************************************/

#ifdef D5us
	void Delay5us()
	{
		_nop_();
	}
#endif
#ifdef D10us
	void Delay10us()
	{
		uchar i;
		_nop_();
		i = 2;
		while (--i);
	}
#endif
#ifdef D20us
	void Delay20us()
	{
		unsigned char i;
		_nop_();
		i = 7;
		while (--i);
	}
#endif
#ifdef D30us
	void Delay30us()
	{
		unsigned char i;
		_nop_();
		i = 12;
		while (--i);
	}
#endif
#ifdef D50us
	void Delay50us() 
	{
		uchar i;

		_nop_();
		i = 22;
		while (--i);
	}
#endif
#ifdef D100us
	void Delay100us() 
	{
		uchar i;
		_nop_();
		i = 47;
		while (--i);
	}
#endif
#ifdef D200us
	void Delay200us() 
	{
		uchar i;
		_nop_();
		i = 97;
		while (--i);
	}
#endif
#ifdef D500us
	void Delay500us() 
	{
		uchar i;
		_nop_();
		i = 247;
		while (--i);
	}
#endif
#ifdef D1ms
	void Delay1ms() 
	{
		uchar i, j;
		i = 2;
		j = 239;
		do
		{
			while (--j);
		} while (--i);
	}
#endif
#ifdef D2ms
	void Delay2ms()	
	{
		unsigned char i, j;
		i = 4;
		j = 225;
		do
		{
			while (--j);
		} while (--i);
	}
#endif
#ifdef D5ms
void Delay5ms()	
{
	unsigned char i, j;
	i = 10;
	j = 183;
	do
	{
		while (--j);
	} while (--i);
}
#endif
#ifdef D10ms
	void Delay10ms() 
	{
		uchar i, j;

		i = 20;
		j = 113;
		do
		{
			while (--j);
		} while (--i);
	}
#endif
#ifdef D20ms
	void Delay20ms()	
	{
		unsigned char i, j;
		i = 39;
		j = 230;
		do
		{
			while (--j);
		} while (--i);
	}
#endif
#ifdef D30ms
	void Delay30ms()
	{
		unsigned char i, j;
		i = 59;
		j = 90;
		do
		{
			while (--j);
		} while (--i);
	}
#endif
#ifdef D50ms
	void Delay50ms() 
	{
		uchar i, j;
		i = 98;
		j = 67;
		do
		{
			while (--j);
		} while (--i);
	}
#endif
#ifdef D70ms
	void Delay70ms()
	{
		unsigned char i, j;
		i = 137;
		j = 44;
		do
		{
			while (--j);
		} while (--i);
	}
#endif
#ifdef D100ms
	void Delay100ms() 
	{
		uchar i, j;
		i = 195;
		j = 138;
		do
		{
			while (--j);
		} while (--i);
	}
#endif
#ifdef D200ms
	void Delay200ms() 
	{
		uchar i, j, k;
		_nop_();
		i = 2;
		j = 134;
		k = 20;
		do
		{
			do
			{
				while (--k);
			} while (--j);
		} while (--i);
	}
#endif
#ifdef D500ms
	void Delay500ms() 
	{
		uchar i, j, k;
		_nop_();
		i = 4;
		j = 205;
		k = 187;
		do
		{
			do
			{
				while (--k);
			} while (--j);
		} while (--i);
	}
#endif
#ifdef D1s
	void Delay1s() 
	{
		uchar i, j, k;
		_nop_();
		i = 8;
		j = 154;
		k = 122;
		do
		{
			do
			{
				while (--k);
			} while (--j);
		} while (--i);
	}
#endif
#ifdef D2s
	void Delay2s() 
	{
		uchar i, j, k;
		_nop_();
		i = 16;
		j = 51;
		k = 249;
		do
		{
			do
			{
				while (--k);
			} while (--j);
		} while (--i);
	}
#endif
#ifdef D5s
	void Delay5s() 
	{
		uchar i, j, k;
		_nop_();
		i = 38;
		j = 0;
		k = 118;
		do
		{
			do
			{
				while (--k);
			} while (--j);
		} while (--i);
	}
#endif
#ifdef D10s
	void Delay10s() 
	{
		uchar i, j, k;
		_nop_();
		i = 76;
		j = 255;
		k = 241;
		do
		{
			do
			{
				while (--k);
			} while (--j);
		} while (--i);
	}
#endif

END

猜你喜欢

转载自blog.csdn.net/belous_zxy/article/details/81814748