目录

简介

一.系统的功能分析及体系结构设计

二.STC89C52单片机最小系统

三.5V电源电路设计

四.LCD1602液晶显示模块电路设计

五.按键电路设计

六.PCF8591 A/D采样电路设计

七.GP2Y0A21YK0F红外测距传感器模块电路设计

八.系统源程序(包含原理图,实物图焊接,源代码)

      简介

由于红外测距是一种非接触检测技术,不受光线、被测对象颜色等的影响,较其它仪器更卫生,更耐潮湿、粉尘、高温、腐蚀气体等恶劣环境,具有少维护、不污染、高可靠、长寿命等特点。因此可广泛应用于纸业、矿业、电厂、化工业、水处理厂、污水处理厂、农业用水、环保检测、食品(酒业、饮料业、添加剂、食用油、奶制品)、防汛、水文、明渠、空间定位、公路限高等行业中。可在不同环境中进行距离准确度在线标定,可直接用于水、酒、糖、饮料等液位控制,可进行差值设定,直接显示各种液位罐的液位、料位高度。

因此,红外在空气中测距在特殊环境下有较广泛的应用。利用红外检测往往比较迅速、方便、计算简单、易于实现实时控制,并且在测量精度方面能达到工业实用的指标要求,因此为了使移动机器人能够自动躲避障碍物行走,就必须装备测距系统,以使其及时获取距障碍物的位置信息(距离和方向)。因此红外测距在移动机器人的研究上得到了广泛的应用。同时由于红外测距系统具有以上的这些优点,因此在汽车倒车雷达的研制方面也得到了广泛的应用。

一.系统的功能分析及体系结构设计

系统功能分析

本设计由STC89C52单片机+红外测距模块(发射与接收一体)+1602液晶显示电路+A/D采样电路-PCF8591电路+按键电路+蜂鸣器报警电路+电源电路组成。

1、通过红外测距模块检测距离(测距范围10-80cm),通过PCF8591将红外模块的模拟数值转化为数字数值,然后传给单片机处理。

2、通过1602液晶第一行实时显示距离,第二行显示设置的阈值。

3、阈值可以通过2个按键调节。

4、超过阈值后,蜂鸣器鸣叫报警。

3.1.2系统总体结构

本系统具体框图如下图所示:

二.STC89C52单片机最小系统说明:

STC89C52单片机最小系统电路由复位电路、时钟电路和电源电路。拥有这三部分电路后,单片机即可正常工作。单片机最小系统原理图如下图所示。

三.5V电源电路设计

本系统选择5V直流电源作为系统总电源,为整个系统供电,电路简单、稳定。DC为电源的DC插座,可以直接接USB电源线,一端插在DC插座上,另外一端可以插在5V电源上,如电脑USB、充电宝、手机充电器等等。LED为红色LED灯,作为系统是否有点的指示灯,电阻为1K电阻,起到限流作用,保护LED灯,以防电流过大烧坏LED灯。SW为自锁开关,开关按下后,红灯亮,此时系统电源5V直流输出。开关再次按下后,红灯灭,此时系统电源无5V电源输出。

四.LCD1602液晶显示模块电路设计

LCD显示器分为字段显示和字符显示两种。其中字段显示与LED显示相似,只要送对应的信号到相应的管脚就能显示。字符显示是根据需要显示基本字符。本设计采用的是字符型显示。系统中采用LCD1602作为显示器件输出信息。与传统的LED数码管显示器件相比,液晶显示模块具有体积小、功耗低、显示内容丰富等优点,而且不需要外加驱动电路,现在液晶显示模块已经是单片机应用设计中最常用的显示器件了。LCD1602可以显示2行16个汉字。

LCD1602液晶模块内部的控制器共有11条控制指令,说明下表所示:

序号

指令

RS

R/W

D7

D6

D5

D4

D3

D2

D1

D0

1

清显示

0

0

0

0

0

0

0

0

0

1

2

光标返回

0

0

0

0

0

0

0

0

1

*

3

置输入模式

0

0

0

0

0

0

0

1

I/D

S

4

显示开/关控制

0

0

0

0

0

0

1

D

C

B

5

光标或字符移位

0

0

0

0

0

1

S/C

R/L

*

*

6

置功能

0

0

0

0

1

DL

N

F

*

*

7

置字符发生存贮器地址

0

0

0

1

字符发生存贮器地址

8

置数据存贮器地址

0

0

1

显示数据存贮器地址

9

读忙标志或地址

0

1

BF

计数器地址

10

写数到CGRA或DDRAM)

1

0

要写的数据内容

11

从CGRAM或DDRAM读数

1

1

读出的数据内容

系统中采用LCD1602作为显示器件输出信息。在本电路中电位器可以调节液晶显示的对比度即清晰度。其具体电路原理图如下图所示。

五.按键电路设计

轻触按键是按键产品下属的一款分类产品,它其实相当于是一种电子开关,只要轻轻的按下按键就可以是开关接通,松开时是开关就断开连接,实现原理主要是通过轻触按键内部的金属弹片受力弹动来实现接通和断开的。在本系统中,按键作为系统的输入,起到了人机交互的枢纽作用。按键的单片机控制引脚默认为高电平,当按键按下后,单片机的相关引脚则变成低电平。进而实现对系统的手动输入。其电路原理图如下图所示。

按键电路原理图

六.PCF8591 A/D采样电路设计

本系统选择PCF8591作为A/D采样芯片。PCF8591是一个单片集成、单独供电、低功耗、8-bit CMOS数据获取器件。PCF8591具有4个模拟输入、1个模拟输出和1个串行I²C总线接口。PCF8591的3个地址引脚A0, A1和A2可用于硬件地址编程,允许在同个I2C总线上接入8个PCF8591器件,而无需额外的硬件。在PCF8591器件上输入输出的地址、控制和数据信号都是通过双线双向I2C总线以串行的方式进行传输。

  • 芯片特性

(1)单独供电

(2)PCF8591的操作电压范围2.5V-6V

(3)低待机电流

(4)通过I2C总线串行输入/输出

(5)PCF8591通过3个硬件地址引脚寻址

(6)PCF8591的采样率由I2C总线速率决定

(7)个模拟输入可编程为单端型或差分输入

(8)自动增量频道选择

(9)PCF8591的模拟电压范围从VSS到VDD

(10)PCF8591内置跟踪保持电路

(11)8-bit逐次逼近A/D转换器

其具体原理图如下图所示。两个电阻为上拉电阻,让数字信号的读取更稳定。

七.GP2Y0A21YK0F红外测距传感器模块电路设计

本系统选择GP2Y0A21YK0F红外测距传感器对距离进行检测。GP2Y0A21YK0F是测距传感器单元,是基于PSD的微距传感器,其有效测距距离在10-80cm内,有效测量角度大于40度,输出的信号为模拟电压,在0-8cm内于Juin成正比非线性关系,在10-80cm范围内成反比非线性关系,平均工号约为30mA,反应时间约为5ms,并对背景光和温度的适应性较强,由于输出信号为模拟电压,且价格低廉,因此在工程测量等方面有巨大的应用前景。由于采用三角测量方法,这个装置输出对应于电压检测输出,所以这种传感器还可用来作为接近传感器

  • 模块参数
  1. 测量距离10-80cm。
  2. 测距分辨率为1mm
  3. 电源电压为4.5V-5.5V
  4. 模拟量输出型
  5. 功耗:30mA
  6. 工作温度:-10-+60℃
  7. 存储温度:-40-+70℃
  • 使用范围
  1. 触摸式开关(卫浴设备、照明等)
  2. 节能传感器(ATM取款机、复印机、自动售货机等)
  3. 机器人、吸尘器
  4. 游乐设备(机器人、游戏机)
  5. 智能家居等等。
  • 模块接口说明
  1. 红线 接4.5V-5.5V
  2. 黑线 接GND
  3. 黄线 信号线,接单片机引脚

模块接口原理图如下图所示。

传感器接口电路原理图

模块实物图如下图所示。

传感器传感器实物图

八.系统源程序(包含原理图,实物图焊接,源代码)

程序原理图

实物图实现

以下为源代码:

1602.h


------------------------------------------------*/
#include<reg52.h> //包含头文件,一般情况不需要改动,头文件包含特殊功能寄存器的定义
#include<intrins.h>#ifndef __1602_H__
#define __1602_H__void DispStr(unsigned char x,unsigned char y,unsigned char *ptr);
void DispNChar(unsigned char x,unsigned char y, unsigned char n,unsigned char *ptr);
void LocateXY(unsigned char x,unsigned char y);
void Disp1Char(unsigned char x,unsigned char y,unsigned char data1);
void LcdReset(void);
void LcdWriteCommand(unsigned char cmd,unsigned char chk);
void LcdWriteData( unsigned char data1 );
void WaitForEnable(void);
void LcdClear(void);#define LCD_Init          LcdReset
#define LCD_Write_Char    Disp1Char
#define LCD_Write_String  DispStr
#define LCD_Clear         LcdClear#endif

1602.c

#include "1602.h"
#include "delay.h"
#include <intrins.h>#define uchar unsigned char
#define uint unsigned int#define _NOP() _nop_()
sbit RS = P2^4;   //定义端口
sbit RW = P2^5;
sbit EN = P2^6;#define DataPort    P0
#define DataPIN     P0#define CLR_RS (RS=0)
#define SET_RS (RS=1)
#define CLR_RW (RW=0)
#define SET_RW (RW=1)
#define CLR_EN (EN=0)
#define SET_EN (EN=1)  /*LcdReset();               //LCD1602初始化DelayMs(10);    sprintf(temp,"1111111111111111");//更新显示DispStr(0,0,(unsigned char *)temp);//打印显示sprintf(temp,"1111111111111111");//更新显示DispStr(0,1,(unsigned char *)temp);//打印显示
*/
/***********************************************
函数名称:DispStr
功    能:让液晶从某个位置起连续显示一个字符串
参    数:x--位置的列坐标y--位置的行坐标ptr--指向字符串存放位置的指针
返回值  :无
***********************************************/
void DispStr(uchar x,uchar y,uchar *ptr)
{uchar *temp;uchar i,n = 0;temp = ptr;while(*ptr++ != '\0')   n++;    //计算字符串有效字符的个数for (i=0;i<n;i++){Disp1Char(x++,y,temp[i]);if (x == 0x10){break;}}
}/*******************************************
函数名称:DispNchar
功    能:让液晶从某个位置起连续显示N个字符
参    数:x--位置的列坐标y--位置的行坐标n--字符个数ptr--指向字符存放位置的指针
返回值  :无
*******************************************
void DispNChar(uchar x,uchar y, uchar n,uchar *ptr)
{uchar i;for (i=0;i<n;i++){Disp1Char(x++,y,ptr[i]);if (x == 0x10){x = 0; y ^= 1;}}
}
*/
/*******************************************
函数名称:LocateXY
功    能:向液晶输入显示字符位置的坐标信息
参    数:x--位置的列坐标y--位置的行坐标
返回值  :无
********************************************/
void LocateXY(uchar x,uchar y)
{uchar temp;temp = x&0x0f;y &= 0x01;if(y)   temp |= 0x40;  //如果在第2行temp |= 0x80;LcdWriteCommand(temp,1);
}/*******************************************
函数名称:Disp1Char
功    能:在某个位置显示一个字符
参    数:x--位置的列坐标y--位置的行坐标data--显示的字符数据
返回值  :无
********************************************/
void Disp1Char(uchar x,uchar y,uchar data1)
{LocateXY( x, y );          LcdWriteData( data1 );
}/*******************************************
函数名称:LcdReset
功    能:对1602液晶模块进行复位操作
参    数:无
返回值  :无
********************************************/
void LcdReset(void)
{
//    DataDir  = 0xFF;                 //数据端口设为输出状态 LcdWriteCommand(0x38, 0);      //规定的复位操作DelayMs(5);LcdWriteCommand(0x38, 0);       DelayMs(5);LcdWriteCommand(0x38, 0);DelayMs(5);LcdWriteCommand(0x38, 1);        //显示模式设置LcdWriteCommand(0x08, 1);       //显示关闭LcdWriteCommand(0x01, 1);     //显示清屏LcdWriteCommand(0x06, 1);     //写字符时整体不移动LcdWriteCommand(0x0c, 1);        //显示开,不开游标,不闪烁
}/*------------------------------------------------清屏函数
------------------------------------------------*/
void LcdClear(void)
{ LcdWriteCommand(0x01,1); DelayMs(5);
}/*******************************************
函数名称:LcdWriteCommand
功    能:向液晶模块写入命令
参    数:cmd--命令,chk--是否判忙的标志,1:判忙,0:不判
返回值  :无
********************************************/
void LcdWriteCommand(uchar cmd,uchar chk)
{if (chk) WaitForEnable();   // 检测忙信号?CLR_RS;   CLR_RW; _NOP();DataPort = cmd;             //将命令字写入数据端口 _NOP();                    SET_EN;                     //产生使能脉冲信号_NOP();_NOP();CLR_EN;
}/*******************************************
函数名称:LcdWriteData
功    能:向液晶显示的当前地址写入显示数据
参    数:data--显示字符数据
返回值  :无
********************************************/
void LcdWriteData( uchar data1 )
{WaitForEnable();        //等待液晶不忙SET_RS;CLR_RW; SET_EN;_NOP();DataPort = data1;        //将显示数据写入数据端口_NOP();//产生使能脉冲信号_NOP(); _NOP(); CLR_EN;
}/*******************************************
函数名称:WaitForEnable
功    能:等待1602液晶完成内部操作
参    数:无
返回值  :无
********************************************/
void WaitForEnable(void)
{unsigned int later=0;DataPort=0xff;CLR_RS;SET_RW;_NOP();SET_EN; _NOP();_NOP();
//    while((DataPIN&Busy)!=0);    while(((DataPIN&0x80)!=0)&&(later<1000))  //检测忙标志{DelayUs2x(2);later++;        }CLR_EN;
//    DataDir|=0xFF;  //将P4口切换为输出状态
}       

i2c.c

#include "i2c.h"#define  _Nop()  _nop_()  //定义空指令bit ack;                //应答标志位sbit SDA=P2^0;
sbit SCL=P2^1;#define AddWr 0x90   //写数据地址
#define AddRd 0x91   //读数据地址/*------------------------------------------------启动总线
------------------------------------------------*/
void Start_I2c()
{SDA=1;   //发送起始条件的数据信号_Nop();SCL=1;_Nop();    //起始条件建立时间大于4.7us,延时_Nop();_Nop();_Nop();_Nop();    SDA=0;     //发送起始信号_Nop();    //起始条件锁定时间大于4μ_Nop();_Nop();_Nop();_Nop();       SCL=0;    //钳住I2C总线,准备发送或接收数据_Nop();_Nop();
}
/*------------------------------------------------结束总线
------------------------------------------------*/
void Stop_I2c()
{SDA=0;    //发送结束条件的数据信号_Nop();   //发送结束条件的时钟信号SCL=1;    //结束条件建立时间大于4μ_Nop();_Nop();_Nop();_Nop();_Nop();SDA=1;    //发送I2C总线结束信号_Nop();_Nop();_Nop();_Nop();
}/*----------------------------------------------------------------字节数据传送函数
函数原型: void  SendByte(unsigned char c);
功能:  将数据c发送出去,可以是地址,也可以是数据,发完后等待应答,并对此状态位进行操作.(不应答或非应答都使ack=0 假)     发送数据正常,ack=1; ack=0表示被控器无应答或损坏。
------------------------------------------------------------------*/
void  SendByte(unsigned char c)
{unsigned char BitCnt;for(BitCnt=0;BitCnt<8;BitCnt++)  //要传送的数据长度为8位{if((c<<BitCnt)&0x80)SDA=1;   //判断发送位else  SDA=0;                _Nop();SCL=1;               //置时钟线为高,通知被控器开始接收数据位_Nop(); _Nop();             //保证时钟高电平周期大于4μ_Nop();_Nop();_Nop();         SCL=0; }_Nop();_Nop();SDA=1;               //8位发送完后释放数据线,准备接收应答位_Nop();_Nop();   SCL=1;_Nop();_Nop();_Nop();if(SDA==1)ack=0;     else ack=1;        //判断是否接收到应答信号SCL=0;_Nop();_Nop();
}/*----------------------------------------------------------------字节数据传送函数
函数原型: unsigned char  RcvByte();
功能:  用来接收从器件传来的数据,并判断总线错误(不发应答信号),发完后请用应答函数。
------------------------------------------------------------------*/
unsigned char  RcvByte()
{unsigned char retc;unsigned char BitCnt;retc=0; SDA=1;             //置数据线为输入方式for(BitCnt=0;BitCnt<8;BitCnt++){_Nop();           SCL=0;       //置时钟线为低,准备接收数据位_Nop();_Nop();      //时钟低电平周期大于4.7us_Nop();_Nop();_Nop();SCL=1;       //置时钟线为高使数据线上数据有效_Nop();_Nop();retc=retc<<1;if(SDA==1)retc=retc+1; //读数据位,接收的数据位放入retc中_Nop();_Nop(); }SCL=0;    _Nop();_Nop();return(retc);
}/*----------------------------------------------------------------应答子函数
原型:  void Ack_I2c(void);----------------------------------------------------------------*/
/*void Ack_I2c(void)
{SDA=0;     _Nop();_Nop();_Nop();      SCL=1;_Nop();_Nop();              //时钟低电平周期大于4μ_Nop();_Nop();_Nop();  SCL=0;               //清时钟线,钳住I2C总线以便继续接收_Nop();_Nop();
}*/
/*----------------------------------------------------------------非应答子函数
原型:  void NoAck_I2c(void);----------------------------------------------------------------*/
void NoAck_I2c(void)
{SDA=1;_Nop();_Nop();_Nop();      SCL=1;_Nop();_Nop();              //时钟低电平周期大于4μ_Nop();_Nop();_Nop();  SCL=0;                //清时钟线,钳住I2C总线以便继续接收_Nop();_Nop();
}/*------------------------------------------------读AD转值程序
输入参数 Chl 表示需要转换的通道,范围从0-3
返回值范围0-255
------------------------------------------------*/
unsigned char ReadADC(unsigned char Chl){unsigned char Val;Start_I2c();               //启动总线SendByte(AddWr);             //发送器件地址if(ack==0)return(0);SendByte(0x40|Chl);            //发送器件子地址if(ack==0)return(0);Start_I2c();SendByte(AddWr+1);if(ack==0)return(0);Val=RcvByte();NoAck_I2c();                 //发送非应位Stop_I2c();                  //结束总线return(Val);}/*----------------------------------------------------------------向无子地址器件发送字节数据函数
函数原型: bit  ISendByte(unsigned char sla,ucahr c);
功能:     从启动总线到发送地址,数据,结束总线的全过程,从器件地址sla.如果返回1表示操作成功,否则操作有误。
注意:    使用前必须已结束总线。
----------------------------------------------------------------*/
/*bit ISendByte(unsigned char sla,unsigned char c)
{Start_I2c();               //启动总线SendByte(sla);             //发送器件地址if(ack==0)return(0);SendByte(c);               //发送数据if(ack==0)return(0);Stop_I2c();                 //结束总线return(1);
}
*//*----------------------------------------------------------------向有子地址器件发送多字节数据函数
函数原型: bit  ISendStr(unsigned char sla,unsigned char suba,ucahr *s,unsigned char no);
功能:     从启动总线到发送地址,子地址,数据,结束总线的全过程,从器件地址sla,子地址suba,发送内容是s指向的内容,发送no个字节。如果返回1表示操作成功,否则操作有误。
注意:    使用前必须已结束总线。
----------------------------------------------------------------*/
/*bit ISendStr(unsigned char sla,unsigned char suba,unsigned char *s,unsigned char no)
{unsigned char i;for(i=0;i<no;i++){ Start_I2c();               //启动总线SendByte(sla);             //发送器件地址if(ack==0)return(0);SendByte(suba);            //发送器件子地址if(ack==0)return(0); SendByte(*s);            //发送数据if(ack==0)return(0);Stop_I2c();                  //结束总线DelayMs(1);               //必须延时等待芯片内部自动处理数据完毕s++;suba++;} return(1);
}
*/
/*----------------------------------------------------------------向无子地址器件读字节数据函数
函数原型: bit  IRcvByte(unsigned char sla,ucahr *c);
功能:     从启动总线到发送地址,读数据,结束总线的全过程,从器件地址sla,返回值在c.如果返回1表示操作成功,否则操作有误。
注意:    使用前必须已结束总线。
----------------------------------------------------------------*/
/*bit IRcvByte(unsigned char sla,unsigned char *c)
{Start_I2c();                //启动总线SendByte(sla+1);            //发送器件地址if(ack==0)return(0);*c=RcvByte();               //读取数据NoAck_I2c();              //发送非就答位Stop_I2c();               //结束总线return(1);
}*/
/*----------------------------------------------------------------向有子地址器件读取多字节数据函数
函数原型: bit  ISendStr(unsigned char sla,unsigned char suba,ucahr *s,unsigned char no);
功能:     从启动总线到发送地址,子地址,读数据,结束总线的全过程,从器件地址sla,子地址suba,读出的内容放入s指向的存储区,读no个字节。如果返回1表示操作成功,否则操作有误。
注意:    使用前必须已结束总线。
----------------------------------------------------------------*/
/*bit IRcvStr(unsigned char sla,unsigned char suba,unsigned char *s,unsigned char no)
{unsigned char i;Start_I2c();               //启动总线SendByte(sla);             //发送器件地址if(ack==0)return(0);SendByte(suba);            //发送器件子地址if(ack==0)return(0);Start_I2c();SendByte(sla+1);if(ack==0)return(0);for(i=0;i<no-1;i++){ *s=RcvByte();              //发送数据Ack_I2c();                //发送就答位 s++;} *s=RcvByte();NoAck_I2c();                 //发送非应位Stop_I2c();                    //结束总线return(1);
}
*/

i2c.h

 #ifndef __I2C_H__
#define __I2C_H__  #include <reg52.h>          //头文件的包含
#include <intrins.h>#define  _Nop()  _nop_()        //定义空指令void Start_I2c();
void Stop_I2c();
void  SendByte(unsigned char c);
unsigned char  RcvByte();void Ack_I2c(void);
void NoAck_I2c(void);
bit ISendByte(unsigned char sla,unsigned char c);
bit ISendStr(unsigned char sla,unsigned char suba,unsigned char *s,unsigned char no);
bit IRcvByte(unsigned char sla,unsigned char *c);
bit IRcvStr(unsigned char sla,unsigned char suba,unsigned char *s,unsigned char no);unsigned char ReadADC(unsigned char Chl);#endif

main.c

#include<reg52.h> //包含头文件
#include<stdio.h>
#include<math.h>
#include "1602.h"
#include "delay.h"
#include "i2c.h"sbit Buzzer =P1^0;   //引脚定义
sbit Key1 =P1^1;
sbit Key2 =P1^2;char dis0[16];            //打印数组初始化
char dis1[16];
unsigned long time_20ms=0;        //定时器计数float Volt=0.0;          //检测电压
unsigned int BatCap=80;              //容量初始化
float Shijul= 0,midval ;   //实际距离
unsigned int Setjul= 25 ;  //测量距离
unsigned int DisFlag = 0,rekey=0 ;    //更新显示void Init_Timer0(void);          //函数声明
void UART_Init(void);
void uartSendStr(unsigned char *s,unsigned char length);
void uartSendByte(unsigned char dat);void main (void)
{     unsigned char midvolt;Init_Timer0();        //定时器0初始化UART_Init();LCD_Init();           //初始化液晶DelayMs(20);          //延时有助于稳定LCD_Clear(); sprintf(dis0,"Now:Err cm 1-80",Shijul);//打印电池容量值LCD_Write_String(0,0,dis0);//显示第一行sprintf(dis1,"Set:%2d cm     ",Setjul);//打印电压值            LCD_Write_String(0,1,dis1);//显示第二uartSendStr("reday ok!!",10);while (1)         //主循环{if(DisFlag ==1){DisFlag =0 ;midvolt=ReadADC(0);             //ad转换采集Volt=(float)midvolt*5.10/255;      //计算出电压 *5.10为参考电压 手机适配器if((Volt<0.42)||(Volt>3.13))   //超出测量范围{sprintf(dis0,"Now:%4.1f",Volt);//打印显示内容Buzzer = 1;uartSendStr("ddddddd") ;}else  //正常范围{Shijul=26.527*pow(Volt,-1.225)+0.1;      //模拟曲线获取 根据手册来 光电型号GP2Y0A21YK0F  测量范围10-80cm   0.1位匹配midval =  Shijul;sprintf(dis0,"Now:%4.1fcm 1-80",Shijul);//打印实际值if(midval>Setjul)  //实际值和设置值对比{Buzzer = 0;}else{Buzzer = 1;}     }LCD_Write_String(0,0,dis0);//显示第一行//           sprintf(dis1,"Set:%2d cm %4.2f",Setjul,Volt);//打印电压值sprintf(dis1,"Set:%2d cm     ",Setjul);//打印电压值          LCD_Write_String(0,1,dis1);//显示第二行}if((Key1==0)||(Key2==0)) //检测按键是否按下{if(rekey==0)       //防止重复{DelayMs(10);//延时去抖动if(Key1==0)    //按键1{rekey =1;if(Setjul>10)  //设置值--{Setjul--;}}else if(Key2==0)  //按键2{rekey =1;if(Setjul<80)       //设置值++{Setjul++;}}}}else{rekey =0;}    //防止重复}
}void Init_Timer0(void)
{TMOD |= 0x01;   //使用模式1,16位定时器,使用"|"符号可以在使用多个定时器时不受影响          TH0=(65536-20000)/256;          //重新赋值 20msTL0=(65536-20000)%256;EA=1;            //总中断打开ET0=1;           //定时器中断打开TR0=1;           //定时器开关打开
}void Timer0_isr(void) interrupt 1
{TH0=(65536-20000)/256;          //重新赋值 20msTL0=(65536-20000)%256;time_20ms++;if(time_20ms%30==0)   //定时显示{DisFlag = 1;}
}void UART_Init(void)
{SCON  = 0x50;             // SCON: 模式 1, 8-bit UART, 使能接收  TMOD |= 0x20;               // TMOD: timer 1, mode 2, 8-bit 重装TH1   = 0xFD;               // TH1:  重装值 9600 波特率 晶振 11.0592MHzTL1 = TH1;  TR1   = 1;                  // TR1:  timer 1 打开                         EA    = 1;                  //打开总中断ES    = 1;                  //打开串口中断
}void uartSendByte(unsigned char dat)
{unsigned char time_out;time_out=0x00;SBUF = dat;           //将数据放入SBUF中while((!TI)&&(time_out<100))  //检测是否发送出去{time_out++;DelayUs2x(10);}  //未发送出去 进行短暂延时TI = 0;                      //清除ti标志
}void uartSendStr(unsigned char *s,unsigned char length)
{unsigned char NUM;NUM=0x00;while(NUM<length)   //发送长度对比{uartSendByte(*s);  //放松单字节数据s++;       //指针++NUM++;        //下一个++}
}void UART_SER (void) interrupt 4   //串行中断服务程序
{if(RI)                        //判断是接收中断产生{RI=0;                      //标志位清零}if(TI)  //如果是发送标志位,清零TI=0;
} 

最后附上自己总结的一些话~

在这个红外测距仪的实现过程中,我是以各个模块独立化的形式展现出来的,原因在于我想让大家从入门开始就建立起建工程的意识,从硬件原理图再到代码的编译实现,逐步拆开去理解每个模块的代码实现过程。相信大家看完能有一个清晰的认识和对单片机的理解。

~如有不足,请补充,谢谢!

基于51单片机红外测距仪阈值报警仪表设计相关推荐

  1. 基于51单片机的酒精浓度检测仪设计

    本设计仅供参考 基于51单片机的酒精浓度检测仪设计(proteus仿真+程序+原理图+报告) 原理图:Altium Designer 仿真:proteus 8.9 程序编译器:keil 4/keil ...

  2. 基于51单片机的CO浓度报警器设计

    目录 基于51单片机的CO浓度报警器设计 1.原理图 2.protus仿真图 3.PCB图 4.飞线图 5.焊接图 6.程序代码 7.资源获取 基于51单片机的CO浓度报警器设计 注:本毕设资源可在微 ...

  3. 基于51单片机甲醛浓度检测系统仿真设计(仿真+程序+原理图+报告+讲解)

    文章目录 资料下载(可点击) 功能说明 仿真图 复位电路 晶振电路 程序 原理图: 设计报告: 器件清单: 基于51单片机甲醛浓度检测系统仿真设计(仿真+程序+原理图+报告+讲解) 原理图:Altiu ...

  4. 基于51单片机的电子万年历的设计-源代码

    电子万年历的设计目录 电子万年历的设计 电子万年历的系统整体设计框图 所需要的元件 DS18B20模块 DS18B20的特点 DS18B20内部结构 DS18B20管脚排列 DS1302模块 SPI时 ...

  5. S0011基于51单片机DS18B20温控风扇仿真设计

    基于51单片机DS18B20温控风扇仿真设计 (仿真+原理图+源码+设计报告) 原理图:Altium Designer 仿真原版本:proteus 7.8 程序编译器:keil 4/keil 5 编程 ...

  6. 51单片机八位抢答器c语言设计,基于51单片机八路抢答器的设计

    基于51单片机八路抢答器的设计 毕业设计(论文)题 目:基于 51 单片机八路抢答器的设计 系 部: 专 业: 学 号: 学生姓名: 指导教师姓名: 指导教师职称: 2013 年 xx 月 xx 日X ...

  7. 单片机检测电机频率c语言,基于51单片机的电动机测速表的设计.doc

    基于51单片机的电动机测速表的设计 基于51单片机的电动机测速表设计 摘 要 本文介绍了采用光电传感器实施电机转速测量的方法.基本原理,完成了一种基于AT89C51单片机平台的电动机测速表的软硬件设计 ...

  8. 单片机遥控车c语言程序,基于51单片机的无线遥控小车设计[附发射接收程序]

    /***************************************************************/ /*[基于51单片机的无线遥控小车设计] 作者王*茹 */ /*** ...

  9. 基于51单片机的三角波信号发生器设计

    基于51单片机的三角波信号发生器设计 一.任务要求: 设计内容 选择51单片机,晶振采用12MHz. 设计一个能产生50HZ至100HZ的三角波信号.通过0832/A芯片完成数模转换. 频率值由LED ...

最新文章

  1. quartz 分布式_6大分布式定时任务对比
  2. 通过解决“构造包含所有给定子串的最短字符串”问题思考算法优化
  3. Verilog设计实例(6)基于Verilog的各种移位寄存器实现
  4. python操作excel-自动化办公:python 操作Excel
  5. 文巾解题 176. 第二高的薪水
  6. clone远程代码 在不同电脑上git_用树莓派3搭建私有git代码仓库
  7. java 追加写入txt文件_ava如何追加写入txt文件
  8. 实分析royden第四版答案_高价实木变板木掺了“假”的实木家具!搞懂这些名词,买家具不上当...
  9. 自定义Mac睡眠时间,保持运行状态
  10. edius隐藏快捷键_EDIUS快捷键大全
  11. 2022年制造业单项冠军行业研究报告
  12. win10 svn图标不显示
  13. web前端开发面试题(八)
  14. 【无线链路】无线发射功率以及接收灵敏度
  15. Java http响应报文_java中HTTP响应报文是什么意思?详细图解
  16. Java泛型详解:<T>和Class<T>的使用。泛型类,泛型方法的详细使用实例
  17. 短链接如何为短信营销提效
  18. 批处理系统、分时系统、实时操作系统的特点和比较
  19. 什么是WAF?WAF的功能有哪些?
  20. C语言求n的阶乘的方法总结

热门文章

  1. 游戏开发插件整理(亲测可用)
  2. 搜索引擎优化技巧之基础篇
  3. 计算机网络原理第三篇 数据链路层
  4. 3398: [Usaco2009 Feb]Bullcow 牡牛和牝牛
  5. 正则表达式实例:取得普陀区所有的小区名字和地址
  6. 假设某专业有若干个班,每个班有若干学生,每个学生包含姓名和分数,这样构成一棵树,如图1所示。假设树中每个结点的name域均不相同,该树采用孩子兄弟链存储结构,其结点类型定义如下:
  7. 【threejs】可视化大屏酷炫3D地图附源码
  8. 年龄计算机在线计算,年龄计算器在线计算
  9. 作为程序员的你在外行人眼里是一个怎样的群体?
  10. android调用系统拍照、相册