超声波测距在我们日常生活中很常见,比如说车在倒退的时候,为了防止车撞到障碍物,会在车尾加上一个超声波测距模块。在智能车比赛中,也有超声波测距模块等等。可见超声波非常的重要,接下来,我们上代码研究一下如何编写这个程序:

main.c

#include <reg51.h>
#include <intrins.h>
#include "lcd.h"

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 =0;
	   unsigned char disbuff[4]	   ={0,0,0,0};

void Conut(void) ;
void  StartModule(); 		         //启动模块
void init_51(void);

void  main(void)
{
	BELL = 0 ;
	Delay400Ms();
	LCMInit();
	init_51();
	while(1)
	{
	  	 StartModule();
	     while(!RX);		//当RX为零时等待
	     TR0=1;			    //开启计数
	     while(RX);			//当RX为1计数并等待
	     TR0=0;				//关闭计数
         Conut();			//计算
		 if(S > 100){
		 	BELL = 1 ;
			Delay400Ms();
			BELL = 0 ;
			Delay400Ms();
		 }
		 delayms(80);		//80MS
	}
}

void Conut(void)
{
	 time=TH0*256+TL0;
	 TH0=0;
	 TL0=0;

	 S=(time*1.7)/100;     //算出来是CM
	 if((S>=700)||flag==1) //超出测量范围显示“-”
	 {
	  flag=0;
	  DisplayOneChar(0, 1, ASCII[11]);
	  DisplayOneChar(1, 1, ASCII[10]);	//显示点
	  DisplayOneChar(2, 1, ASCII[11]);
	  DisplayOneChar(3, 1, ASCII[11]);
	  DisplayOneChar(4, 1, ASCII[12]);	//显示M
	 }
	 else
	 {
	  disbuff[0]=S%1000/100;
	  disbuff[1]=S%1000%100/10;
	  disbuff[2]=S%1000%10 %10;
	  DisplayOneChar(0, 1, ASCII[disbuff[0]]);
	  DisplayOneChar(1, 1, ASCII[10]);	//显示点
	  DisplayOneChar(2, 1, ASCII[disbuff[1]]);
	  DisplayOneChar(3, 1, ASCII[disbuff[2]]);
	  DisplayOneChar(4, 1, ASCII[12]);	//显示M
	 }
}

void zd0() interrupt 1 		 //T0中断用来计数器溢出,超过测距范围
{
    flag=1;							 //中断溢出标志
}
/********************************************************/
void  StartModule() 		         //启动模块
{
	  TX = 1;			                     //启动一次模块
	  _nop_();
	  _nop_();
	  _nop_();
	  _nop_();
	  _nop_();
	  _nop_();
	  _nop_();
	  _nop_();
	  _nop_();
	  _nop_();
	  _nop_();
	  _nop_();
	  _nop_();
	  _nop_();
	  _nop_();
	  _nop_();
	  _nop_();
	  _nop_();
	  _nop_();
	  _nop_();
	  _nop_();
	  TX=0;
}

void init_51(void)
{
	TMOD=0x01;		   //设T0为方式1,GATE=1;
	TH0=0;
	TL0=0;
	ET0=1;             //允许T0中断
	EA=1;			   //开启总中断 

}

lcd.c

#include"lcd.h"
//写数据
void WriteDataLCM(unsigned char WDLCM)
{
	ReadStatusLCM(); //检测忙
	LCM_Data = WDLCM;
	LCM_RS = 1;
	LCM_RW = 0;
	LCM_E = 0; //若晶振速度太高可以在这后加小的延时
	LCM_E = 0; //延时
	LCM_E = 1;
}

//写指令
void WriteCommandLCM(unsigned char WCLCM,BuysC) //BuysC为0时忽略忙检测
{
	if (BuysC) ReadStatusLCM(); //根据需要检测忙
	LCM_Data = WCLCM;
	LCM_RS = 0;
	LCM_RW = 0;
	LCM_E = 0;
	LCM_E = 0;
	LCM_E = 1;
}

//读数据
unsigned char ReadDataLCM(void)
{
	LCM_RS = 1;
	LCM_RW = 1;
	LCM_E = 0;
	LCM_E = 0;
	LCM_E = 1;
	return(LCM_Data);
}

//读状态
unsigned char ReadStatusLCM(void)
{
	LCM_Data = 0xFF;
	LCM_RS = 0;
	LCM_RW = 1;
	LCM_E = 0;
	LCM_E = 0;
	LCM_E = 1;
	while (LCM_Data & Busy); //检测忙信号
	return(LCM_Data);
}

void LCMInit(void) //LCM初始化
{
	LCM_Data = 0;
	WriteCommandLCM(0x38,0); //三次显示模式设置,不检测忙信号
	Delay5Ms();
	WriteCommandLCM(0x38,0);
	Delay5Ms();
	WriteCommandLCM(0x38,0);
	Delay5Ms(); 

	WriteCommandLCM(0x38,1); //显示模式设置,开始要求每次检测忙信号
	WriteCommandLCM(0x08,1); //关闭显示
	WriteCommandLCM(0x01,1); //显示清屏
	WriteCommandLCM(0x06,1); // 显示光标移动设置
	WriteCommandLCM(0x0C,1); // 显示开及光标设置
}

//按指定位置显示一个字符
void DisplayOneChar(unsigned char X, unsigned char Y, unsigned char DData)
{
	Y &= 0x1;
	X &= 0xF; //限制X不能大于15,Y不能大于1
	if (Y) X |= 0x40; //当要显示第二行时地址码+0x40;
	X |= 0x80; //算出指令码
	WriteCommandLCM(X, 1); //发命令字
	WriteDataLCM(DData); //发数据
}

//按指定位置显示一串字符
void DisplayListChar(unsigned char X, unsigned char Y, unsigned char code *DData)
{
	unsigned char ListLength;

  ListLength = 0;
	Y &= 0x1;
	X &= 0xF; //限制X不能大于15,Y不能大于1
	while (DData[ListLength]>0x19) //若到达字串尾则退出
		{
			if (X <= 0xF) //X坐标应小于0xF
				{
					DisplayOneChar(X, Y, DData[ListLength]); //显示单个字符
					ListLength++;
					X++;
				}
		}
}

//5ms延时
void Delay5Ms(void)
{
	unsigned int TempCyc = 5552;
	while(TempCyc--);
}

//400ms延时
void Delay400Ms(void)
{
	unsigned char TempCycA = 5;
	unsigned int TempCycB;
	while(TempCycA--)
		{
			TempCycB=7269;
			while(TempCycB--);
		};
}

lcd.h

#ifndef __LCD_H_
#define __LCD_H_
/**********************************
当使用的是4位数据传输的时候定义,
使用8位取消这个定义
**********************************/
#define LCD1602_4PINS

/**********************************
包含头文件
**********************************/
#include<reg51.h>
#ifndef uchar
#define uchar unsigned char
#endif

#ifndef uint
#define uint unsigned int
#endif

sbit  RX = P1^0 ;
sbit  TX = P1^1 ;
sbit LCM_RW = P2^5 ;
sbit LCM_RS = P2^6 ;
sbit LCM_E = P2^7 ;
#define LCM_Data  P0

#define Busy    0x80 //用于检测LCM状态字中的Busy标识
sbit  BELL = P2^1 ;	

void delayms(unsigned int ms);
void Delay400Ms(void);

/*LCD1602初始化子程序*/
void LCMInit(void);
unsigned char ReadDataLCM(void);
//读状态
unsigned char ReadStatusLCM(void);
//5ms延时
void Delay5Ms(void);
//写数据
void WriteDataLCM(unsigned char WDLCM) ;
void WriteCommandLCM(unsigned char WCLCM,BuysC); //BuysC为0时忽略忙检测
//按指定位置显示一串字符
void DisplayListChar(unsigned char X, unsigned char Y, unsigned char code *DData);
//按指定位置显示一个字符
void DisplayOneChar(unsigned char X, unsigned char Y, unsigned char DData);

#endif

烧写到开发板上,现象如下:

没超出1m的情况下,不会报警。



超出1m后,蜂鸣器报警:

如何编写51单片机超声波测距SR04_lcd1602显示程序的更多相关文章

  1. #51单片机#超声波测距(HC-SR04)的使用方法

    #51单片机#超声波测距(HC-SR04)的使用方法

  2. c语言编写51单片机中断程序,执行过程是怎样的?

    Q:c语言编写51单片机中断程序,执行过程是怎样的? 例如程序:#include<reg52.h>  void main(void)  {   EA=1;      //开放总中断   E ...

  3. 基于51单片机个LCD1602的万年历程序

    小白 第一次跟新博客 基于51单片机和LCD1602的万年历程序 可实现走时和调时功能 有简单的1602菜单制作 欢迎大家交流 LCD1602和51单片机的连接方法 RS = P3^5; //数据/命 ...

  4. 3.7 基于51单片机+MC20的路径显示【使用STC15W内核】

    需要准备的硬件 MC20开发板 1个 https://item.taobao.com/item.htm?id=562661881042 GSM/GPRS天线 1根 https://item.taoba ...

  5. [51单片机] SPI nRF24L01 无线简单程序 1

    main.c #include <reg51.h> #include <api.h> #define uchar unsigned char /**************** ...

  6. [51单片机] HC-SR04超声波测距仪 基础代码

    >_<:超声波测距仪模块: >_<:51单片机,11.0592MHz晶振,将采集数据发送到串口的基础例子: >_<:代码: /******************* ...

  7. 51单片机实现对24C02进行页写、顺序读取并显示验证

    //************************************************************************************* //**程序名称:51单 ...

  8. [自娱自乐] 4、超声波测距模块DIY笔记(四)——终结篇·基于C#上位机软件开发

    前言 上一节我们已经基本上把超声波硬件的发射和接收模块全部做好了,接下来我们着手开发一个软硬结合的基于C#的平面定位软件! 目录 一.整体思路 二.效果提前展示 2-1.软件部分展示 2-2.硬件部分 ...

  9. 传感器之超声波测距HC-SR04

    一.前言 HC-SR04超声波测距模块可提供2cm-400cm的非接触式距离感测功能,测距精度可达高到3mm:模块包括超声波发射器.接收器与控制电路.像智能小车的测距以及转向,或是一些项目中,常常会用 ...

随机推荐

  1. iOS 中捕获截屏操作

    转自:iOS知识小集 在iOS 7后,苹果提供了UIApplicationUserDidTakeScreenshotNotification通知来告诉App用户做了截屏操作.苹果的描述如下: // T ...

  2. Python 好用得让人发指的函数参数语法糖

    是吗? def f(x,y,z): return x+y+z t=(200,300) print(f(1,2,3)) print(f(1,*t)) 结果: >>> 6 501 这是我 ...

  3. Scikit-learn:模型评估Model evaluation

    http://blog.csdn.net/pipisorry/article/details/52250760 模型评估Model evaluation: quantifying the qualit ...

  4. openJdk和sun Jdk区别和安装

    openJdk和sun jdk的区别 使用过LINUX的人都应该知道,在大多数LINUX发行版本里,内置或者通过软件源安装JDK的话,都是安装的OpenJDK, 那么到底什么是OpenJDK,它与SU ...

  5. SQLite Where 子句(http://www.w3cschool.cc/sqlite/sqlite-where-clause.html)

    SQLite Where 子句 SQLite的 WHERE 子句用于指定从一个表或多个表中获取数据的条件. 如果满足给定的条件,即为真(true)时,则从表中返回特定的值.您可以使用 WHERE 子句 ...

  6. JAVA面向对象-----接口与类、接口之间的关系

    接口与类.接口之间的关系 大家之前都知道类与类之间的关系继承,那么接口与类之间又是怎样子的关系呢? 接口与类之间是实现关系.非抽象类实现接口时,必须把接口里面的所有方法实现.类实现接口用关键字impl ...

  7. 剑指Offer——丑数

    剑指Offer--丑数 前言     参照<剑指Offer>,通过洞悉其思想并消化吸收,改为java实现,供自己以后巩固. package cn.edu.ujn.offersword; i ...

  8. JAVA之旅(三十二)——JAVA网络请求,IP地址,TCP/UDP通讯协议概述,Socket,UDP传输,多线程UDP聊天应用

    JAVA之旅(三十二)--JAVA网络请求,IP地址,TCP/UDP通讯协议概述,Socket,UDP传输,多线程UDP聊天应用 GUI写到一半电脑系统挂了,也就算了,最多GUI还有一个提示框和实例, ...

  9. 01基于配置文件方式的SpringMVC,三种HandlerMapping,三种控制器

     1 添加Spring MVC所需的jar包. 2 创建一个以下项目结构的springmvc项目 3 web.xml的配置如下: <?xmlversion="1.0"en ...

  10. Dynamics CRM2013 注释中的内容无法正常显示问题

    CRM2013中在表单中插入注释,并把注释设置成默认选项卡后 打开一个已经挂了附件的表单,但却显示找不到记录 必须要再点击下注释,内容才会出来 查了半天不得其解,终于在ur1 for CRM2013  ...