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

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. 网站开发进阶(四十四)input type="submit" 和"button"的区别

    网站开发进阶(四十四)input type="submit" 和"button"的区别   在一个页面上画一个按钮,有四种办法: 这就是一个按钮.如果你不写ja ...

  2. syslog(),closelog()与openlog()--日志操作函数

    在典型的 LINUX 安装中,/var/log/messages 包含所有的系统消息,/var/log/mail 包含来自邮件系统的其它日志消息,/var/log/debug 可能包含调试消息.根据你 ...

  3. 使用Intent传递对象

    Intent 的用法相信你已经比较熟悉了,我们可以借助它来启动活动.发送广播.启动服务等.在进行上述操作的时候,我们还可以在Intent 中添加一些附加数据,以达到传值的效果,比如在FirstActi ...

  4. Dynamics CRM 开启图表的3D效果展示

    CRM中的图表在我们的业务场景中用的很多,用户可以根据自己的实际需求来构建图表查看数据.我们平时看到的图表都是平面的,像下图中的这种,那有没有一种方式可以让展示3D效果看起来更立体呢,答案是可以的. ...

  5. Android 深入理解Loader机制 让APP轻装上阵

    本文简书同步发布,谢谢关注. http://blog.csdn.net/sk719887916/article/details/51540610 Android开发者都经历过APP UI开发不当 会造 ...

  6. C++对象模型的那些事儿之二:对象模型(下)

    前言 上一篇博客C++对象模型的那些事儿之一为大家讲解了C++对象模型的一些基本知识,可是C++的继承,多态这些特性如何体现在对象模型上呢?单继承.多重继承和虚继承后内存布局上又有哪些变化呢?多态真正 ...

  7. 安卓自定义日期控件(仿QQ,IOS7)续

    本篇是在原来的基础上修改了界面效果,使其更加接近ios7,qq等日期选择控件,看图: 源码地址:http://download.csdn.net/detail/baiyuliang2013/87601 ...

  8. Swift基础用法(Swift开发之一)

    昨晚苹果发布了新一代编程语言Swift,官方提供了一个iBook的说明文档,有需要的可以看下.地址:https://itunes.apple.com/cn/book/swift-programming ...

  9. UNIX网络编程——分析一帧基于UDP的TFTP协议帧

    下图是UDP的段格式: 相比TCP段格式,UDP要简单得多,也没啥好说的,需要注意的是UDP数据长度指payload加上首部的长度. 下面分析一帧基于UDP的TFTP协议帧: 以太网首部 0000: ...

  10. redhat安装vsftpd

    一个小问题 rpm -qa|ftp 但是出现3个ftp 只安装了一个 关于网卡ip 首先,我们看到 网卡上面有个x 说明网络是有问题的 我们双击,看到 我们先把connected和connect at ...