完整程序文件下载:https://cos.mcmxzl.com/%E5%85...
主程序:
/***********************************************************************
超声波测距仪
MCU是STC89C52RC
LCD1602A(16*2)模拟口线接线方式
连接线图:
---------------------------------------------------
|LCM-----51 | LCM-----51 | LCM------51 |
--------------------------------------------------|
|DB0-----P2.0 | DB4-----P2.4 | RS-------P1.4 |
|DB1-----P2.1 | DB5-----P2.5 | RW-------P1.5 |
|DB2-----P2.2 | DB6-----P2.6 | E--------P1.6 |
|DB3-----P2.3 | DB7-----P2.7 | VLCD接1K电阻到GND|
---------------------------------------------------
接线:模块TRIG接 P1.0 ECH0 接P1.1
本程序源码只供学习参考,不得应用于商业用途,如有需要请联系作者。
***********************************************************************/
#include //器件配置文件
#include
#include "LCD1602.h"
#define uchar unsigned char
#define uint unsigned int
sbit RX = P1^1;
sbit TX = P1^0;
unsigned char code mcustudio[] ={"www.mcmxzl.com"};
unsigned char code email[] = {"[email protected] "};
unsigned char code ASCII[15] = {'0','1','2','3','4','5','6','7','8','9','.','-','M'};
static unsigned char DisNum = 0; //显示用指针
unsigned int time=0;
unsigned long S=0;
bit flag=1;
unsigned char disbuff[4] ={ 0,0,0,0,};
void Delay5Ms(void)
{
unsigned char i, j;
i = 10;
j = 183;
do
{
while (--j);
} while (--i);
}
//400ms延时
void Delay400Ms(void)
{
unsigned char i, j, k;
_nop_();
i = 4;
j = 11;
k = 45;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
void delayms(unsigned int ms)
{
for(;ms;ms--)
{
unsigned char i, j;
i = 2;
j = 239;
do
{
while (--j);
} while (--i);
}
}
void InitTimer0(void)
{
TMOD = 0x09;
TH0=0; //设置初值
TL0=0;
EA = 1;
ET0 = 1;
}
void Timer0Interrupt(void) interrupt 1
{
TH0=0; //设置初值
TL0=0;
flag=1;
}
void Conut(void)
{
time=TH0*256+TL0;
TH0=0;
TL0=0;
S=(time*1.7)/100; //算出来是CM
Init_LCD1602(); //LCD初始化
if((S>=500)) //超出测量范围显示“-”
{
displaystring(0, 0,"Error:");
displaystring(0, 1,"Out of range!");
/*displaychar(0, 0, ASCII[11]);
displaychar(1, 0, ASCII[10]); //显示点
displaychar(2, 0, ASCII[11]);
displaychar(3, 0, ASCII[11]);
displaychar(4, 0, ASCII[12]); //显示M*/
}
else
{
displaystring(0, 0,"Distance:");
disbuff[0]=S%1000/100;
disbuff[1]=S%1000%100/10;
disbuff[2]=S%1000%10 %10;
displaychar(10, 0, ASCII[disbuff[0]]);
displaychar(11, 0, ASCII[10]); //显示点
displaychar(12, 0, ASCII[disbuff[1]]);
displaychar(13, 0, ASCII[disbuff[2]]);
displaychar(14, 0, ASCII[12]); //显示M
}
}
/*********************************************************/
void main(void)
{
uchar i=0;
InitTimer0(); //初始化定时器
Delay400Ms(); //启动等待,等LCD讲入工作状态
Init_LCD1602(); //LCD初始化
Delay5Ms(); //延时片刻(可不要)
displaystring(0, 0, mcustudio);//显示网站
displaystring(0, 1, email);//显示电子邮箱
delayms(1000);//延时1s
Init_LCD1602();//LCD清屏
Delay5Ms();
/******************************************
显示 欢迎使用超声波测距仪
******************************************/
displaystring(0, 0,"Welcome to use U");
displaystring(0, 1,"ltrasonic distan");
delayms(2000);
Init_LCD1602();
Delay5Ms();
displaystring(0, 0,"ce measuring ins");
displaystring(0, 1,"trument!");
delayms(2000);
/*******************************************/
Init_LCD1602(); //LCD初始化
delayms(5);
while(1)
{
TX=1;
_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
TX=0;
while(!RX); //当RX为零时等待
TR0=1; //开启计数
while(RX); //当RX为1计数并等待
TR0=0; //关闭计数
Conut(); //计算
delayms(280); //延时,反正发射信号对回响信号的影响
}
}
LCD1602显示程序:
//使用方法: 使用前调用Init_LCD1602()初始化,显示方法displaystring(0, 0, "This is a test.");
#ifndef _LCD1602_
#define _LCD1602_
#define uchar unsigned char
#define uint unsigned int
//#define _PORT_REV_ //如果数据端口高低位交换,请去掉此注释
#include //包含_nop_()指令
sbit LCD1602_RS = P1^4; //控件引脚定义,移植请修改
sbit LCD1602_RW = P1^5;
sbit LCD1602_E = P1^6;
#define LCD_PORT P2 //输出数据总线端口定义,移植请修改
#define LCD_COMMAND 0 // Command
#define LCD_DATA 1 // Data
#define LCD_CLEAR_SCREEN 0x01 // 清屏
#define LCD_HOMING 0x02 // 光标返回原点
#define LCD_SHOW 0x04 //显示开
#define LCD_HIDE 0x00 //显示关
#define LCD_CURSOR 0x02 //显示光标
#define LCD_NO_CURSOR 0x00 //无光标
#define LCD_FLASH 0x01 //光标闪动
#define LCD_NO_FLASH 0x00 //光标不闪动
#define LCD_AC_UP 0x02
#define LCD_AC_DOWN 0x00 // default
#define LCD_MOVE 0x01 // 画面可平移
#define LCD_NO_MOVE 0x00 //default
void delay10us(unsigned char t) //误差 -0.234375us
{
while(--t)
{
unsigned char a,b;
for(b=1;b>0;b--)
/* for(a=1;a>0;a--)*/;}
}
/*********************************************************************************************
函数名:8位数据高低位交叉互换
调 用:uchar = DataReverse(uchar);
参 数:输入的端口(0000 0XXX 其中XXX是设置输入端口号,可用十进制0~7表示,0表示P1.0,7表示P1.7)
返回值:交换后的8位数据
结 果:交换数据高低位D7→D0,D6→D1.....,D0→D7,并返回交换后的结果
备 注:
/**********************************************************************************************/
unsigned char DataReverse(unsigned char datOld)
{
unsigned char datNew=0,i;
for (i=0; i<8; i++)
{
if (datOld & (1<>i);
}
return datNew;
}
/**********************************************************************************************/
/*********************************************************************************************
函数名:LCD1602等待函数
调 用:uchar = LCD_Wait();
参 数:无
返回值:LCD1602数据总线的值
结 果:等待LCD1602内部指令执行完成
备 注:返回结果可不用
/**********************************************************************************************/
unsigned char LCD_Wait(void)
{
LCD1602_RS = 0;
LCD1602_RW = 1; delay10us(1);
LCD1602_E = 1; delay10us(1);
#ifdef _PORT_REV_ //如果数据线高低位交换,则需要处理数据
while(DataReverse(LCD_PORT)&0x80);
LCD1602_E = 0;
return DataReverse(LCD_PORT);
#else //正常情况下不需要交换
while(LCD_PORT&0x80);
LCD1602_E = 0;
return LCD_PORT;
#endif
}
/**********************************************************************************************/
/*********************************************************************************************
函数名:LCD1602数据写函数
调 用:LCD_Wait(bit, uchar);
参 数:数据类型,数据值
返回值:无
结 果:将指定数据类型的数据写入1602
备 注:数据类型:LCD_COMMAND(0)、LCD_DATA(1)
/**********************************************************************************************/
void LCD_Write(bit DataStyle, unsigned char DAT)
{
LCD1602_E = 0;
LCD1602_RS = DataStyle;
LCD1602_RW = 0; delay10us(1);
#ifdef _PORT_REV_
LCD_PORT = DataReverse(DAT);
#else
LCD_PORT = DAT;
#endif
_nop_();
LCD1602_E = 1; delay10us(1);//注意顺序
LCD1602_E = 0; delay10us(1);
LCD_Wait(); //等待1602内部执行完,Proteus仿真时请注释此句
}
/**********************************************************************************************/
/*********************************************************************************************
函数名:LCD1602显示设置函数
调 用:LCD_SetDisplay(uchar);
参 数:显示模式
返回值:无
结 果:正常设置1602显示模式
备 注:内部函数,初始化时调用
/**********************************************************************************************/
void LCD_SetDisplay(unsigned char DisplayMode)
{
LCD_Write(LCD_COMMAND, 0x08|DisplayMode);
}
/**********************************************************************************************/
/*********************************************************************************************
函数名:LCD1602显示设置函数
调 用:LCD_SetInput(uchar);
参 数:显示模式
返回值:无
结 果:正常设置1602显示模式
备 注:内部函数,初始化时调用
/**********************************************************************************************/
void LCD_SetInput(unsigned char InputMode)
{
LCD_Write(LCD_COMMAND, 0x04|InputMode);
}
/**********************************************************************************************/
/*********************************************************************************************
函数名:LCD1602初始化函数
调 用:Init_LCD1602();
参 数:无
返回值:无
结 果:初始化1602函数
备 注:
/**********************************************************************************************/
void Init_LCD1602()
{
LCD_Write(LCD_COMMAND, 0x38); //8位数据端口,2行显示,5*7点阵
LCD_Write(LCD_COMMAND, 0x38);
LCD_Write(LCD_COMMAND, 0x38);
LCD_SetDisplay(LCD_SHOW | LCD_NO_CURSOR); //开启显示, 无光标
LCD_Write(LCD_COMMAND, LCD_CLEAR_SCREEN); //清屏
LCD_SetInput(LCD_AC_UP | LCD_NO_MOVE); //AC递增, 画面不动
}
/**********************************************************************************************/
/*********************************************************************************************
函数名:LCD1602数据写函数
调 用:LCD1602_DispString(uchar, uchar, *uchar);
参 数:x坐标,y坐标,字符串
返回值:无
结 果:在指定坐标显示字符串
备 注:x: 0~15; y:0、1
/**********************************************************************************************/
void displaystring(unsigned char x, unsigned char y, unsigned char *s)
{
if(y == 0)
LCD_Write(LCD_COMMAND, 0x80|x);
if(y == 1)
LCD_Write(LCD_COMMAND, 0x80|(x-0x40));
while(*s != '\0')
{
LCD_Write(LCD_DATA, *s);
s++;
}
}
/**********************************************************************************************/
//字符显示初始地址设置
void LCD_SET_XY(uchar X,uchar Y)
{
if(Y == 0)
LCD_Write(LCD_COMMAND, 0x80|X);
if(Y == 1)
LCD_Write(LCD_COMMAND, 0x80|(X-0x40));
}
//在第X行Y列开始显示Wdata所对应的单个字符
void displaychar(uchar X,uchar Y,uchar Wdata)
{
LCD_SET_XY(X,Y);//写地址
LCD_Write(LCD_DATA, Wdata);//写入当前字符并显示
}
#endif