您的当前位置:首页基于DS18B20的51单片机LCD1602液晶显示测温系统

基于DS18B20的51单片机LCD1602液晶显示测温系统

2021-01-26 来源:爱问旅游网


JINGCHU UNIVERSITY OF TECHNOLOGY

《单片机原理及应用》

课程设计报告

LCD1602液晶显示18b20温控实验

专 业 : 电气工程及其自动化 班 级 : 10电工(3)班 **** : ** **** : *** 提交日期 : 2013-06-21

1

目 录

第一部分 设计任务

1.1设计题目及求要求……………………………………………………………………3

1.2.1 方案一…………………………………………………………………3 1.2.4 方案分析………………………………………………………………3 第二部分 设计方案

2.1 总体设计方案说明……………………………………………………3 2.2 实物电路图………………………………………………………………4 第三部分 电路设计与器件选择

3.1 DS18B20工作原理和功能说明······························……4 3.2 LCD1602工作原理和功能说明……………………………………………16 第四部分 4.1实验程序………………………………………………………28 第五部分 5.1课程设计总结 (心得体会)…………………………………34 第六部分 6.1参考文献………………………………………………………34

2

1.1设计题目及求要求

用电子元器件和单片机通过编写程序做成能实时显示温度的仪器。

1.2.1 方案

用通用型1602液晶显示器和DS18B20温度传感器组成温度显示仪,并编写程序用51单片机来控制和连接1602液晶显示器和DS18B20温度传感器。

1.2.2 方案分析

1602液晶显示器能显示ASCII码字符,数字、大小写字母、和各种符号。而且其体积小、功耗低、显示操作简单,显示值清晰,正常温度范围为-20~+60。 DS18B20温度传感器采用单总线协议,与单片机接口仅需用一个I/O接口无需任何外部元件,直接将环境温度转化成数字信号,从而大大简化了传感器于微LCD1LM016L处理机的接口。DS18B20温度传感器支持多点组网功能,多个DS18B20可以并联在唯一的三线上,其测试范围在-50~+125.C。测试结果直接输出数字温度信号,VSSVDDVEERSRWE123456纠错能力。电源板极性接反时,芯片不会因发热而烧毁。且它具有微型化、低功RSRWEC1d0d1d2d3d4d5d6d77891011121314以“一位总线”串行传送给CPU,同时可传送CRC效验码,具有极强的抗干扰耗、高新能、抗干扰能力强、一赔微处理器等优点。 U122PFD0D1D2D3D4D5D6D7RP11d02d3d4d5d6d7XTAL1P0.0/AD0d1338d112M考虑到1602C2液晶显示器和DS18B20温度传感器有诸多优点,顾用二者来完P0.1/AD1d2437d2P0.2/AD2X11939d0成实验。 22PFR19RST 10k21RSRESPACK-8P2.0/A8C322RW P2.1/A923EP2.2/A102924PSENP2.3/A1110uF3025 ALEP2.4/A123126EAP2.5/A1327P2.6/A14 28P2.7/A15110P1.0P3.0/RXD 211P1.1P3.1/TXD312P1.2P3.2/INT0413R2 P1.3P3.3/INT15144.7kP1.4P3.4/T0U2615P1.5P3.5/T12.1总体设计方案说明 7163P1.6P3.6/WRVCC-15.58172P1.7P3.7/RDDQ1GND AT89C51DS18B20分别用DS18B20温度传感器和1602液晶显示器来测试温度和现实数据。编写本例中将温度上下限预设为 70 至 -20度程序和利用51单片机来控制电路。

3

18XTAL2P0.3/AD3P0.4/AD4P0.5/AD5P0.6/AD6P0.7/AD73635343332d3d4d5d6d756789

2.2实物电路图

LCD1LM016LSDSDEES01234567VVVRRWEDDDDDDDD1234567890123411111SRRWE01234567ddddddddC1RP1122PFU1X119XTAL1P0.0/AD039d0d02C212MP0.1/AD138d1d1337d2d2418P0.2/AD2XTAL2P0.3/AD336d3d35P0.4/AD435d4d4622PFP0.5/AD534d5d57R1P0.6/AD633d6d689RSTP0.7/AD732d7d7910kC3P2.0/A821RSRESPACK-8P2.1/A922RWP2.2/A1023E2910uF30PSENP2.3/A112431ALEP2.4/A1225EAP2.5/A1326P2.6/A1427P2.7/A152812P1.0P3.0/RXD103P1.1P3.1/TXD114P1.2P3.2/INT0125P1.3P3.3/INT113R26P1.4P3.4/T0144.7kP3.5/T115U27P1.58P1.6P3.6/WR163VCCP1.7P3.7/RD1721DQ-15.5AT89C51GNDDS18B20本例中将温度上下限预设为 70 至 -20度

3.1DS18B20的工作原理 ① DS18B20数字温度传感器概述

DS18B20数字温度传感器是DALLAS公司生产的1-Wire,即单总线器件,具有线路简单,体积小的特点。因此用它来组成一个测温系统,具有 线路简单,在一根通信线,可以挂很多这样的数字温度计,十分方便。

DS18B20产品的特点

 只要求一个端口即可实现通信。

 在DS18B20中的每个器件上都有独一无二的序列号。  实际应用中不需要外部任何元器件即可实现测温。

4

 测量温度范围在-55.C到+125.C之间。

 数字温度计的分辨率用户可以从9位到12位选择。  内部有温度上、下限告警设置。

TO-92封装的DS18B20的引脚排列见右图,其引脚功能描述见表 序号 1 2 名称 GND DQ 引脚功能描述 地信号 数字输入输出引脚,开漏单总线接口引脚,当使用寄生电源时,可向电源提供电源 3 VDD 可选择的VDD引脚,当工作于寄生电源时,该引脚必须接地 表3-2 DS18B20详细引脚功能描述

② DS18B20的内部结构

DS18B20的内部框图下图所示,DS18B20 的内部有64 位的ROM 单元,和9 字节的暂存器单元。64位ROM存储器件独一无二的序列号。暂存器包含两字节(0和1字节)的温度寄存器,用于存储温度传感器的数字输出。暂存器还提供一字节的上线警报触发(TH)和下线警报触发(TL)寄存器(2和3字节),和一字节的配置寄存器(4字节),使用者可以通过配置寄存器来设置温度转换的精度。暂存器的5、6和7字节器件内部保留使用。第八字节含有循环冗余码(CRC )。使用寄生电源时,DS18B20不需额外的供电电源;当总线为高电平时,功率由单总线上的上拉电阻通过DQ引脚提供;高电平总线信号同时也向内部电容CPP充电,CPP在总线低电平时为器件供电。(字节5~8 就不用看了)。

5

图为 暂存器 暂存器介绍

A. 温度寄存器(0和1字节)

DS18B20中的温度传感器可完成对温度的测量,以12位转化为例:用16位符号扩展的二进制补码读数形式提供,以0.0625℃/LSB形式表达,其中S为符号位。 这是12位转化后得到的12位数据,存储在18B20的两个8比特的RAM中,二进制中的前面5位是符号位,如果测得的温度大于0,这5位为0,只要将测到的数值乘于0.0625即可得到实际温度;如果温度小于0,这5位为1,测到的数值需要取反加1再乘于0.0625即可得到实际温度。

DS18B20 的温度操作是使用16 位,也就是说分辨率是0.0625。BIT15~BIT11 是符号位,为了就是表示转换的值是正数还是负数。

█要求出正数的十进制值,必须将读取到的LSB 字节,MSB 字节进行整合处理,然后乘以0.0625 即可。

6

Eg:假设从,字节0 读取到0xD0 赋值于Temp1,而字节1 读取到0x07 赋值于Temp2,然后求出十进制值。

unsigned int Temp1,Temp2,Temperature; Temp1=0xD0; //低八位 Temp2=0x07; //高八位

Temperature = ((Temp2<<8 ) | Temp1 ) * 0.0625;//又或者

Temperature = (Temp1 + Temp2 *256) * 0.0625; //Temperature=125

█在这里我们遇见了一个问题,就是如何求出负数的值呢?我们必须判断BIT11~15 是否是1,然后人为置一负数标志。

Eg. 假设从,字节0 读取到0x90 赋值于Temp1,而字节1 读取到0xFC 赋值于Temp2,然后求出该值是不是负数,和转换成十进制值。 unsigned int Temp1,Temp2,Temperature; unsigned char Minus_Flag=0; Temp1=0x90; //低八位 Temp2=0xFC; //高八位

//Temperature = (Temp1 + Temp2 *256) * 0.0625; //Temperature=64656 //很明显不是我们想要的答案

if(Temp2&0xFC) //判断符号位是否为1 {

Minus_Flag=1; //负数标志置一

Temperature = ((Temp2<<8 ) | Temp1 ) //高八位第八位进行整合 Temperature= ((~Temperature)+1); //求反,补一 Temperature*= 0.0625; //求出十进制 } //Temperature=55; else {

Minus_Flag=0;

Temperature = ((Temp2<<8 ) | Temp1 ) * 0.0625; }

█如果我要求出小数点的值的话,那么我应该这样做。 Eg:假设从,字节0 读取到0xA2 赋值于Temp1,而字节1 读取到0x00 赋值于Temp2, 然后求出十进制值,要求连同小数点也求出。 unsigned int Temp1,Temp2,Temperature; Temp1=0x90; //低八位 Temp2=0xFC; //高八位 //实际值为10.125

//Temperature = ((Temp2<<8 ) | Temp1 ) * 0.0625; //10,无小数点

Temperature = ((Temp2<<8 ) | Temp1 ) * (0.0625 * 10) ; //101 ,一位小数点

//Temperature = ((Temp2<<8 ) | Temp1 ) * (0.0625 * 100) ; //1012,二位小数点

█ 如以上的例题,我们可以先将0.0625 乘以10,然后再乘以整合后的

Temperature 变量,就可以求出后面一个小数点的值(求出更多的小数点,方法都是以此类推)。得出的结果是101,然后再利用简单的算法,求出每一位的值。

7

unsinged char Ten,One,Dot1 Ten=Temperature/100; //1 One=Temperature%100/10; //0 Dot1=%10; //1

求出负数的思路也一样,只不过多出人为置一负数标志,求反补一的动作而已。自己发挥想象力吧。

B .字节2~3:TH 和TL配置

TH 与TL 就是所谓的温度最高界限,和温度最低界限的配置。可以使用软件来试验。

C 字节4:配置寄存器

BIT7 出厂的时候就已经设置为0,用户不建议去更改。而R1 与R0 位组合了四个不同的转换精度,00 为9 位转换精度而转换时间是93.75ms,01 为10 位转换精度而转换时间是187.5ms,10 为11 位转换精度而转换时间是375ms,11 为12 位转换精度而转换时间是750ms(默认)。该寄存器还是留默认的好,毕竟转换精度表示了转换的质量。

低五位一直都是\"1\",TM是测试模式位,用于设置DS18B20在工作模式还是在测试模式。在DS18B20出厂时该位被设置为0,用户不要去改动。R1和R0用来设置分辨率,如下表所示:(DS18B20出厂时被设置为12位)

表3-6R1与R0确定传感器分辨率设置表

R1 0 0 1 1 R0 0 1 0 1 传感器精度/bit 9 10 11 12 转换时间/ms 93.75 187.5 375 750

D.字节5~7,保留位,8:CRC 光刻ROM介绍

光刻ROM中的64位序列号是出厂前被光刻好的,它可以看作是该DS18B20的地址序列码。64位光刻ROM的排列是:开始8位(28H)是产品类型标号,接着的48位是该DS18B20自身的序列号,最后8位是前面56位的循环冗余校验码(CRC=X8+X5+X4+1)。光刻ROM的作用是使每一个DS18B20都各不相同,这样就可以实现一根总线上挂接多个DS18B20的目的。 DS18B20温度传感器的存储器介绍

DS18B20温度传感器的内部存储器包括一个高速暂存RAM和一个非易失性的可电擦除的EEPRAM,后者存放高温度和低温度触发器TH、TL和结构寄存器。 2 DS18B20的工作过程

DS18B20 一般都是充当从机的角色,而单片机就是主机。单片机通过一线总

8

线访问DS18B20的话,需要经过以下几个步骤: ① DS18B20 复位(初始化),DS18B20 复位。在某种意义上就是一次访问DS18B20 的开始,或者可说成是开始信号。

②执行ROM 指令(ROM命令跟随着需要交换的数据);ROM 指令,也就是访问,搜索,匹配,DS18B20 个别的64 位序列号的动作。在单点情况下,可以直接跳过ROM 指令。(而跳过ROM 指令的字节是0xCC,后面介绍)

③执行DS18B20 功能指令(RAM 指令),功能命令跟随着需要交换的数据。

DS18B20 复位(初始化)

在初始化过程中,主机通过拉低单总线至少480µs,以产生复位脉冲(TX)。然后主机释放总线并进入接收(RX)模式。当总线被释放后,5kΩ的上拉电阻将单总线拉高。DS18B20检测到这个上升沿后,延时15µs~60µs,通过拉低总线60µs~240µs产生应答脉冲。

DS18B20 功能指令有很多种,数据手册里有更详细的介绍。这里仅列出比较常用的几个DS18B20 功能指令。

0x44:开始转换温度。转换好的温度会储存到暂存器字节0 和1。

0xEE:读暂存指令。读暂存指令,会从暂存器0 到9,一个一个字节读取,如果要停止的话,必须写下DS18B20 复位。

访问DS18B20必须严格遵守这一命令序列,如果丢失任何一步或序列混乱,DS18B20都不会响应主机(除了Search ROM 和Alarm Search这两个命令,在这两个命令后,主机都必须返回到第一步)。 一般上我们都是使用单点,也就是说单线总线上仅有一个DS18B20 存在而已。所以我们无需刻意读取ROM 里边的序列号来,然后匹配那个DS18B20?而是更直接的,跳过ROM 指令,然后直接执行DS18B20 功能指令。

ROM命令: ROM命令通过每个器件64-bit的ROM码,使主机指定某一特定器件(如果有多个器件挂在总线上)与之进行通信。DS18B20的ROM如表3-4所示,每个ROM命令都是8 bit长。

功能命令:

主机通过功能命令对DS18B20进行读/写Scratchpad存储器,或者启动温度转换。DS18B20的功能命令如表3-7所示。 指令 读ROM 符合ROM 搜索ROM 跳过ROM 报警搜索命9

协议 功能 33H 读DS18B20中的编码(即64位地址) 发出此命令后,接着发出64位ROM编码,访问单总线上与55H 该编码相对应的DS18B20,使之作出响应,为下一步对该DS18B20的读写作准备 0F0H 用于确定挂接在同一总线上DS18B20的个数和识别64位ROM地址,为操作各器件作好准备 0CCH 忽略64位ROM地址,直接向DS18B20V 温度转换命令,适用于单个DS18B20工作 0ECH 执行后,只有温度超过庙宇值上限或下限的片子才做出响令 温度转换 读暂存器 写暂存器 44H BEH 4EH 复制暂存器 48H 重调E2PROM 0B8H 读供电方式 0B4H 应 启动DS18B20进行温度转换,转换时间最长为500ms(典型为200ms),结果丰入内部9字节RAM中 读内部RAM中9字节的内容 发出向内部RAM的第3、4字节写上、下温度数据命令,紧该温度命令之后,传达两字节的数据 将RAM中第3、4字内容复制到E2PROM中 将E2PROM中内容恢复到RAM中的第3、4字节 读DS18B20的供电模式,寄生供电时DS18B20发送“0”,外部供电时DS18B20发送“1” 表3-7 DS18B20的信号方式

DS18B20采用严格的单总线通信协议,以保证数据的完整性。该协议定义了几种信号类型:复位脉冲、应答脉冲、写和读。除了应答脉冲所有这些信号都由主机发出同步信号。总线上传输的所有数据和命令都是以字节的低位在前。 a.初始化序列:复位脉冲和应答脉冲 初始化波形如图3-8所示。

DS18B20 的复位时序如下:

1.单片机拉低总线480us~950us, 然后释放总线(拉高电平)。这时DS18B20 会拉低信号,大约60~240us 表示应答。 2.DS18B20 拉低电平的60~240us 之间,单片机读取总线的电平,如果是低电平,那么表示复位成功,DS18B20 拉低电平60~240us 之后,会释放总线。 C程序举例

//DS1820 C51 子程序

//这里以11.0592M晶体为例,不同的晶体速度可能需要调整延时的时间 //sbit DQ =P2^1;//根据实际情况定义端口 void dsreset()//18B20复位,初始化函数 { uint i; ds=0; i=103; while(i>0)i--; ds=1;

10

i=4;

while(i>0)i--;

} DS18B20所有的数据交换都由一个初始化序列开始。由主机发出的复位脉冲和跟在其后的由DS18B20发出的应答脉冲构成。当DS18B20发出响应主机的应答脉冲时,即向主机表明它已处在总线上并且准备工作。

b.读和写时序

在写时序期间,主机向DS18B20写入指令;而在读时序期间,主机读入来自DS18B20的指令。在每一个时序,总线只能传输一位数据。读/写时序如图3-9所示。

 写时序 存在两种写时序:“写1”和“写0”。主机在写1时序向DS18B20写入逻辑1,而在写0时序向DS18B20写入逻辑0。所有写时序至少需要60µs,且在两次写时序之间至少需要1µs的恢复时间。两种写时序均以主机拉低总线开始。 在写时序开始后的15µs~60µs期间,DS18B20采样总线的状态。如果总线为高电平,则逻辑1被写入DS18B20;如果总线为低电平,则逻辑0被写入DS18B20。

 写时序

DS18B20 写步骤如下:

1.单片机拉低电平大约10~15us,。

2.单片机持续送指定电平大约20~45us 的时间。 3.释放总线

如果要读或者写一个字节,就要重复以上的步骤八次。使用for 循环,和数据变量的左移和或运算,实现一个字节读与写。函数延迟的时间,必须模拟非常准确,因为单线总线对时序的要求敏感点。 //向 1-WIRE 总线上写一个字节

void tempwritebyte(BYTE dat) //向18B20写一个字节数据 {

uint i; BYTE j; bit testb;

for(j=1;j<=8;j++) {

11

testb=dat&0x01; dat=dat>>1;

if(testb) //写 1 {

ds=0; i++;i++; ds=1;

i=8;while(i>0)i--; } else {

ds=0; //写 0 i=8;while(i>0)i--; ds=1; i++;i++; } } } }

 读时序

DS18B20 读步骤如下:

1.在读取的时候单片机拉低电平大约1us

2.单片机释放总线,然后读取总线电平。这时候DS18B20 会送出电平。 3.读取电平过后,延迟大约40~45 微妙 //从 1-wire 总线上读取一个字节

bit tempreadbit(void) //读1位函数 {

uint i; bit dat;

ds=0;i++; //i++ 起延时作用 ds=1;i++;i++; dat=ds;

i=8;while(i>0)i--; return (dat); }

12

BYTE tempread(void) //读1个字节 {

BYTE i,j,dat; dat=0;

for(i=1;i<=8;i++) {

j=tempreadbit();

dat=(j<<7)|(dat>>1); //读出的数据最低位在最前面,这样刚好一个字节在DAT里 }

return(dat);

} A . DS18B20 开始转换: 1.DS18B20 复位。

2.写入跳过ROM 的字节命令,0xCC。 3.写入开始转换的功能命令,0x44。 4.延迟大约750~900 毫秒 B . DS18B20 读暂存数据: 1.DS18B20 复位。

2.写入跳过ROM 的字节命令,0xCC。 3.写入读暂存的功能命令,0xee。

4.读入第0 个字节LS Byte,转换结果的低八位。 5.读入第1 个字节MS Byte,转换结果的高八位。 6.DS18B20 复位,表示读取暂存结束。

//读取温度

void tempchange(void) //DS18B20 开始获取温度并转换 {

dsreset(); delay(1);

tempwritebyte(0xcc); // 写跳过读ROM指令 tempwritebyte(0x44); // 写温度转换指令 }

uint get_temp() //读取寄存器中存储的温度数据 {

BYTE a,b;

dsreset(); delay(1);

tempwritebyte(0xcc); tempwritebyte(0xbe);

a=tempread(); //读低8位 b=tempread(); //读高8位 temp=b;

temp<<=8; //两个字节组合为1个字

13

temp=temp|a;

temp = temp *(0.625);//温度值扩大10倍,精确到1位小数

return temp; //temp是整型 }

void ds1820disp(uint temp1)//温度值显示 {

disdata[0]= temp1 /1000+0x30;//百位数

disdata[1]= temp1 %1000/100+0x30;//十位数 disdata[2]= temp1%100/10+0x30;//个位数 disdata[3]=0x2e;

disdata[4]= temp1 %10+0x30;//小数位 }

简单归纳

单线总线高电平为闲置状态。单片机访问DS18B20必须遵守,DS18B20 复位-->执行ROM 指令-->执行DS18B20 功能指令。而在单点上,可以直接跳过ROM 指令。DS18B20 的转换精度默认为12 位,而分辨率是0.0625。 DS18B20 温度读取函数参考步骤: A . DS18B20 开始转换: 1.DS18B20 复位。

2.写入跳过ROM 的字节命令,0xCC。 3.写入开始转换的功能命令,0x44。 4.延迟大约750~900 毫秒 B . DS18B20 读暂存数据: 1.DS18B20 复位。

2.写入跳过ROM 的字节命令,0xCC。 3.写入读暂存的功能命令,0xee。

4.读入第0 个字节LS Byte,转换结果的低八位。 5.读入第1 个字节MS Byte,转换结果的高八位。 6.DS18B20 复位,表示读取暂存结束。

C . 数据求出十进制:

1.整合LS Byte 和MS Byte 的数据 2.判断是否为正负数(可选) 3.求得十进制值。正数乘以0.0625,一位小数点乘以0.625,二位小数点乘以6.25。 4.十进制的“个位”求出。

DS18B20的应用电路

DS18B20测温系统具有测温系统简单、测温精度高、连接方便、占用口线少等优点。下面就是DS18B20几个不同应用方式下的测温电路图: 1 .DS18B20寄生电源供电方式电路图

14

如下图所示,在寄生电源供电方式下,DS18B20从单线信号线上汲取能量:在信号线DQ处于高电平期间把能量储存在内部 电容里,在信号线处于低电平期间消耗电容上的电能工作,直到高电平到来再给寄生电源(电容)充电。

独特的寄生电源方式有三个好处:

1)进行远距离测温时,无需本地电源 2)可以在没有常规电源的条件下读取ROM 3)电路更加简洁,仅用一根I/O口实现测温

要想使DS18B20进行精确的温度转换,I/O线必须保证在温度转换期间提供足够的能量,由 于每个DS18B20在温度转换期间工作电流达到1mA,当几个温度传感器挂在同一根I/O线上进行多点测温时,只靠4.7K上拉电阻就无法提供足够的 能量,会造成无法转换温度或温度误差极大。

因此,此电路只适应于单一温度传感器测温情况下使用,不适宜采用电池供电系统中。并且工作电源VCC必须保证在5V,当电源电压下降时,寄生电源能够汲取的能量也降低,会使温度误差变大。

2.DS18B20的外部电源供电方式

在外部电源供电方式下,DS18B20工作电源由VDD引脚接入,此时I/O线不需要强上拉,不存在电源电流不足的问题,可以保证 转换精度,同时在总线上理论可以挂接任意多个DS18B20传感器,组成多点测温系统。注意:在外部供电的方式下,DS18B20的GND引脚不能悬空 ,否则不能转换温度,读取的温度总是85℃。

外部供电方式单点测温电路

外部供电方式的多点测温电路图

15

图7

外部电源供电方式是DS18B20最佳的工作方式,工作稳定可靠,抗干扰能力强,而且电路也比较简单,可以开发出稳定可靠的多点温度 监控系统。站长推荐大家在开发中使用外部电源供电方式,毕竟比寄生电源方式只多接一根VCC引线。在外接电源方式下, 可以充分发挥DS18B20宽电源电压范围的优点,即使电源电压VCC降到3V时,依然能够保证温度量精度。

DS1820使用中注意事项

DS1820虽然具有测温系统简单、测温精度高、连接方便、占用口线少等优点,但在实际应用中也应注意以下几方面的问题:

1、较小的硬件开销需要相对复杂的软件进行补偿,由于DS1820与微处理器间采用串行数据传送,因此 ,在对DS1820进行读写编程时,必须严格的保证读写时序,否则将无法读取测温结果。在使用PL/M、C等高级语言进行系统程序设计时,对 DS1820操作部分最好采用汇编语言实现。

2、在DS1820的有关资料中均未提及单总线上所挂DS1820数量问题,容易使人误认为可以挂任意多个 DS1820,在实际应用中并非如此。当单总线上所挂DS1820超过8个时,就需要解决微处理器的总线驱动问题,这一点在进行多点测温系统设计时 要加以注意。

3、连接DS1820的总线电缆是有长度限制的。试验中,当采用普通信号电缆传输长度超过50m时,读取的 测温数据将发生错误。当将总线电缆改为双绞线带屏蔽电缆时,正常通讯距离可达150m,当采用每米绞合次数更多的双绞线带屏蔽电缆时,正 常通讯距离进一步加长。这种情况主要是由总线分布电容使信号波形产生畸变造成的。因此,在用DS1820进行长距离测温系统设计时要充分考 虑总线分布电容和阻抗匹配问题。

4、 在DS1820测温程序设计中,向DS1820发出温度转换命令后,程序总要等待DS1820的返回信号,一旦 某个DS1820接触不好或断线,当程序读该DS1820时,将没有返回信号,程序进入死循环。这一点在进行DS1820硬件连接和软件设计时也要给予 一定的重视。 测温电缆线建议采用屏蔽4芯双绞线,其中一对线接地线与信号线,另一组接VCC和地线,屏蔽层在源端单点接地。

3.2LCD1602液晶显示简介

①液晶显示原理

液晶显示的原理是利用液晶的物理特性,通过电压对其显示区域进行控制,有电就有显示,这样即可以显示出图形。液晶显示器具有厚度薄、适用于大规模集成电路直现全彩色显示的特点,目前已经被广泛应用在便携式电脑、数字摄像机、PDA移动通信工具等众多领域。

16

②液晶显示器的分类

液晶显示的分类方法有很多种,通常可按其显示方式分为段式、字符式、点阵式等。除了黑白显示外,液晶显示器还有多灰度有彩色显示等。如果根据驱动方式来分,可以分为静态驱动(Static)、单纯矩阵驱动(Simple Matrix)和主动矩阵驱动(Active Matrix)三种。 ③液晶显示器各种图形的显示原理: 线段的显示

点阵图形式液晶由M×N个显示单元组成,假设LCD显示屏有64行,每行有128列,每8列对应1字节的8位,即每行由16字节,共16×8=128个点组成,屏上64×16个显示单元与显示RAM区1024字节相对应,每一字节的内容和显示屏上相应位置的亮暗对应。例如屏的第一行的亮暗由RAM区的000H——00FH的16字节的内容决定,当(000H)=FFH时,则屏幕的左上角显示一条短亮线,长度为8个点;当(3FFH)=FFH时,则屏幕的右下角显示一条短亮线;当(000H)=FFH,(001H)=00H,(002H)=00H,……(00EH)=00H,(00FH)=00H时,则在屏幕的顶部显示一条由8段亮线和8条暗线组成的虚线。这就是LCD显示的基本原理。 字符的显示

用LCD显示一个字符时比较复杂,因为一个字符由6×8或8×8点阵组成,既要找到和显示屏幕上某几个位置对应的显示RAM区的8字节,还要使每字节的不同位为“1”,其它的为“0”,为“1”的点亮,为“0”的不亮。这样一来就组成某个字符。但由于内带字符发生器的控制器来说,显示字符就比较简单了,可以让控制器工作在文本方式,根据在LCD上开始显示的行列号及每行的列数找出显示RAM对应的地址,设立光标,在此送上该字符对应的代码即可。 汉字的显示

汉字的显示一般采用图形的方式,事先从微机中提取要显示的汉字的点阵码(一般用字模提取软件),每个汉字占32B,分左右两半,各占16B,左边为1、3、5……右边为2、4、6……根据在LCD上开始显示的行列号及每行的列数可找出显示RAM对应的地址,设立光标,送上要显示的汉字的第一字节,光标位置加1,送第二个字节,换行按列对齐,送第三个字节……直到32B显示完就可以LCD上得到一个完整汉字。 2 1602字符型LCD简介

字符型液晶显示模块是一种专门用于显示字母、数字、符号等点阵式LCD,目前常用16*1,16*2,20*2和40*2行等的模块。下面以长沙太阳人电子有限公司的1602字符型液晶显示器为例,介绍其用法。一般1602字符型液晶显示器实物如图:

17

图1602字符型液晶显示器实物图 10.8.2.1 1602LCD的基本参数及引脚功能 1602LCD主要技术参数: 显示容量:16×2个字符 芯片工作电压:4.5—5.5V 工作电流:2.0mA(5.0V) 模块最佳工作电压:5.0V 字符尺寸:2.95×4.35(W×H)mm 引脚功能说明 1602LCD采用标准的14脚(无背光)或16脚(带背光)接口,各引脚接口说明如表10-13所示: 编号 符号 引脚说明 编号 符号 引脚说明 18

1 2 3 4 5 6 7 8 VSS VDD VL RS R/W E D0 D1 电源地 电源正极 液晶显示偏压 数据/命令选择 读/写选择 使能信号 数据 数据 9 10 11 12 13 14 15 16 D2 D3 D4 D5 D6 D7 BLA BLK 数据 数据 数据 数据 数据 数据 背光源正极 背光源负极 表10-13:引脚接口说明表 第1脚:VSS为地电源。 第2脚:VDD接5V正电源。 第3脚:VL为液晶显示器对比度调整端,接正电源时对比度最弱,接地时对比度最高,对比度过高时会产生“鬼影”,使用时可以通过一个10K的电位器调整对比度。 第4脚:RS为寄存器选择,高电平时选择数据寄存器、低电平时选择指令寄存器。 第5脚:R/W为读写信号线,高电平时进行读操作,低电平时进行写操作。当RS和R/W共同为低电平时可以写入指令或者显示地址,当RS为低电平R/W为高电平时可以读忙信号,当RS为高电平R/W为低电平时可以写入数据。 第6脚:E端为使能端,当E端由高电平跳变成低电平时,液晶模块执行命令。 第7~14脚:D0~D7为8位双向数据线。 第15脚:背光源正极。 第16脚:背光源负极 。 1602LCD的指令说明及时序 1602液晶模块内部的控制器共有11条控制指令,如表所示: 序号 指令 1 清显示(01H) RS R/W D7 D6 D5 D4 D3 D2 D1 0 0 0 0 0 0 0 0 0 D0 1 19

2() 光标返回(02H) 3 4 5 6 7 8 9 10 置输入模式(04H-07H) 显示开/关控制(08H-0FH) 光标或字符移位(10H-1FH) 置功能(20H-3FH) 置字符发生存贮器地址(40H-7FH) 置数据存贮器地址(80H-) 读忙标志或地址 写数到CGRAM或DDRAM) 从CGRAM或DDRAM读数 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 1 DL 0 0 1 0 1 D 1 I/D C * * * S B * * S/C R/L N F 字符发生存贮器地址 1 显示数据存贮器地址 BF 计数器地址 要写的数据内容 11 1 1 读出的数据内容 控制命令表 1602液晶模块的读写操作、屏幕和光标的操作都是通过指令编程来实现的。(说明:1为高电平、0为低电平) 指令1:清显示,指令码01H,光标复位到地址00H位置。 指令2:光标复位,光标返回到地址00H。 指令3:光标和显示模式设置 I/D:光标移动方向,高电平右移,低电平左移 S:屏幕上所有文字是否左移或者右移。高电平表示有效,低电平则无效。 指令4:显示开关控制。 D:控制整体显示的开与关,高电平表示开显示,低电平表示关显示 C:控制光标的开与关,高电平表示有光标,低电平表示无光标 B:控制光标是否闪烁,高电平闪烁,低电平不闪烁。 指令5:光标或显示移位 S/C:高电平时移动显示的文字,低电平时移动光标。 指令6:功能设置命令 DL:高电平时为4位总线,低电平时为8位总线 N:低电平时为单行显示,高电平时双行显示 F: 低电平时显示5x7的点阵字符,高电平时显示5x10的点阵字符。 指令7:字符发生器RAM地址设置。 20

指令8:DDRAM地址设置。 指令9:读忙信号和光标地址 BF:为忙标志位,高电平表示忙,此时模块不能接收命令或者数据,如果为低电平表示不忙。 指令10:写数据。 指令11:读数据。 与HD44780相兼容的芯片时序表如下: 读状态 写指令 输入 输入 RS=L,R/W=H,E=H 输出 D0—D7=状态字 无 RS=L,R/W=L,D0—D7=指令码,E=高脉输出 冲 RS=H,R/W=H,E=H 输出 读数据 写数据 输入 输入 D0—D7=数据 无 RS=H,R/W=L,D0—D7=数据,E=高脉冲 输出 基本操作时序表 1602LCD的RAM地址映射及标准字库表 液晶显示模块是一个慢显示器件,所以在执行每条指令之前一定要确认模块的忙标志为低电平,表示不忙,否则此指令失效。要显示字符时要先输入显示字符地址,也就是告诉模块在哪里显示字符,下图是1602的内部显示地址。 1602LCD内部显示地址 例如第二行第一个字符的地址是40H,那么是否直接写入40H就可以将光标定位在第二行第一个字符的位置呢?这样不行,因为写入显示地址时要求最高位D7恒定为高电平1所以实际写入的数据应该是01000000B(40H)+10000000B(80H)=11000000B(C0H)。 21

在对液晶模块的初始化中要先设置其显示模式,在液晶模块显示字符时光标是自动右移的,无需人工干预。每次输入指令前都要判断液晶模块是否处于忙的状态。

1602液晶模块内部的字符发生存储器(CGROM)已经存储了160个不同的点阵字符图形,如下图所示,这些字符有:阿拉伯数字、英文字母的大小写、常用的符号、和日文假名等,每一个字符都有一个固定的代码,比如大写的英文字母“A”的代码是01000001B(41H),显示时模块把地址41H中的点阵字符图形显示出来,我们就能看到字母“A”

图10-58 字符代码与图形对应图

1602LCD的一般初始化(复位)过程 延时15mS

写指令38H(不检测忙信号) 延时5mS

写指令38H(不检测忙信号) 延时5mS

写指令38H(不检测忙信号)

以后每次写指令、读/写数据操作均需要检测忙信号

22

序号 指令 6 置功能 RS R/W D7 D6 D5 D4 D3 D2 D1 0 0 0 0 1 DL N F * D0 * 指令6:功能设置命令 DL:高电平时为4位总线,低电平时为8位总线 N:低电平时为单行显示,高电平时双行显示 F: 低电平时显示5x7的点阵字符,高电平时显示5x10的点阵字符。 写指令38H:显示模式设置 4 显示开/关控制 0 0 0 0 0 0 1 D C B 指令4:显示开关控制。 D:控制整体显示的开与关,高电平表示开显示,低电平表示关显示 C:控制光标的开与关,高电平表示有光标,低电平表示无光标 B:控制光标是否闪烁,高电平闪烁,低电平不闪烁。 写指令08H:显示关闭 写指令01H:显示清屏 写指令06H:显示光标移动设置 写指令0CH:显示开及光标设置 1602LCD的软硬件设计实例 1 硬件原理图 1602液晶显示模块可以和单片机AT89C51直接接口,电路如图10-60所示。 23

硬件原理图 2 程序流程图

软件流程图

24

3 软件代码

#include #include

sbit ds=P3^3;//温度传感器信号线 typedef unsigned char BYTE; typedef bit BOOL;

typedef unsigned int uint;

sbit LCD_RS = P2^0; sbit LCD_RW = P2^1; sbit LCD_EP = P2^2; uint temp;

BYTE code dis1[] = {\" temperature \BYTE data disdata[5]; delay(int ms)

{ // 延时子程序 int i;

while(ms--) {

for(i = 0; i< 250; i++) {

_nop_(); _nop_(); _nop_(); _nop_(); } } }

BOOL lcd_bz()

{ // 测试LCD忙碌状态 BOOL result; LCD_RS = 0; LCD_RW = 1; LCD_EP = 1; _nop_(); _nop_(); _nop_(); _nop_();

result = (BOOL)(P0 & 0x80); LCD_EP = 0; return result; }

lcd_wcmd(BYTE cmd)

25

{ // 写入指令数据到LCD while(lcd_bz()); LCD_RS = 0; LCD_RW = 0; LCD_EP = 0; _nop_(); _nop_(); P0 = cmd; _nop_(); _nop_(); _nop_(); _nop_();

LCD_EP = 1; _nop_(); _nop_(); _nop_(); _nop_();

LCD_EP = 0; }

lcd_pos(BYTE pos)

{ lcd_wcmd(pos | 0x80); }

lcd_wdat(BYTE dat)

{ while(lcd_bz()); LCD_RS = 1; LCD_RW = 0; LCD_EP = 0; P0 = dat; _nop_(); _nop_(); _nop_(); _nop_();

LCD_EP = 1; _nop_(); _nop_(); _nop_(); _nop_();

LCD_EP = 0; }

26

//设定显示位置 //写入字符显示数据到LCD lcd_init()

{ //LCD初始化设定

lcd_wcmd(0x38); //16*2显示,5*7点阵,8位数据 delay(1);

lcd_wcmd(0x0c); //显示开,关光标 delay(1);

lcd_wcmd(0x06); //移动光标 delay(1);

lcd_wcmd(0x01); //清除LCD的显示内容 delay(1); }

void display( ) { BYTE i;

lcd_wcmd(0x06); lcd_pos(0); i = 0;

while(dis1[ i ] != '\\0')

{ lcd_wdat(dis1[ i ]); i++;

delay(5); }

lcd_pos(0x40); i = 0;

while(disdata [ i ] != '\\0') {

lcd_wdat(disdata [ i ]); i++;

delay(5); }

delay(5); }

27

//向右移动光标

//设置显示位置为第一行的第1个字符 //显示字符\"temperature\" //控制两字之间显示速度 //设置显示位置为第二行第1个字符 //控制两字之间显示速度 //控制停留时间 4.1实验程序

#include #include

sbit ds=P3^3;//温度传感器信号线 typedef unsigned char BYTE; typedef bit BOOL; typedef unsigned int uint; sbit LCD_RS = P2^0; sbit LCD_RW = P2^1; sbit LCD_EP = P2^2; uint temp;

BYTE code dis1[] = {\" temperature \BYTE data disdata[5]; delay(int ms)

{ // 延时子程序 int i; while(ms--) {

for(i = 0; i< 250; i++) {

_nop_(); _nop_(); _nop_(); _nop_(); } } }

BOOL lcd_bz()

{ // 测试LCD忙碌状态 BOOL result; LCD_RS = 0; LCD_RW = 1; LCD_EP = 1; _nop_(); _nop_();

28

_nop_(); _nop_();

result = (BOOL)(P0 & 0x80); LCD_EP = 0; return result; }

lcd_wcmd(BYTE cmd)

{ // while(lcd_bz()); LCD_RS = 0; LCD_RW = 0; LCD_EP = 0; _nop_(); _nop_(); P0 = cmd; _nop_(); _nop_(); _nop_(); _nop_(); LCD_EP = 1; _nop_(); _nop_(); _nop_(); _nop_(); LCD_EP = 0; }

lcd_pos(BYTE pos)

{ //lcd_wcmd(pos | 0x80); }

lcd_wdat(BYTE dat)

{ //while(lcd_bz()); LCD_RS = 1;

29

写入指令数据到LCD 设定显示位置 写入字符显示数据到LCD LCD_RW = 0; LCD_EP = 0; P0 = dat; _nop_(); _nop_(); _nop_(); _nop_(); LCD_EP = 1; _nop_(); _nop_(); _nop_(); _nop_(); LCD_EP = 0; }

lcd_init()

{ //LCDlcd_wcmd(0x38); //16*2delay(1);

lcd_wcmd(0x0c); //delay(1);

lcd_wcmd(0x06); //delay(1);

lcd_wcmd(0x01); //delay(1); }

void display( ) { BYTE i;

lcd_wcmd(0x06); // lcd_pos(0); // i = 0;

while(dis1[ i ] != '\\0')

{ //30

初始化设定

显示,5*7点阵,8位数据 显示开,关光标 移动光标 清除LCD的显示内容 向右移动光标

设置显示位置为第一行的第1个字符显示字符\"temperature\"

lcd_wdat(dis1[ i ]); i++;

delay(5); //控制两字之间显示速度 }

lcd_pos(0x40); //设置显示位置为第二行第1个字符 i = 0;

while(disdata [ i ] != '\\0') {

lcd_wdat(disdata [ i ]); //显示字符\" WWW.PRECHIN.COM \" i++;

delay(5); //控制两字之间显示速度 }

delay(5); //控制停留时间 }

/**************************DS18B20

程***************************************/ void dsreset()//18B20复位,初始化函数 { uint i; ds=0; i=103; while(i>0)i--; ds=1; i=4;

while(i>0)i--; }

bit tempreadbit(void) //读1位函数 {

uint i; bit dat;

ds=0;i++; //i++ 起延时作用 ds=1;i++;i++; dat=ds;

i=8;while(i>0)i--; return (dat);

31

}

BYTE tempread(void) //读1个字节 {

BYTE i,j,dat; dat=0;

for(i=1;i<=8;i++) {

j=tempreadbit();

dat=(j<<7)|(dat>>1); //读出的数据最低位在最前面,这样刚好一个字节在DAT里 }

return(dat); }

void tempwritebyte(BYTE dat) //向18B20写一个字节数据 { uint i; BYTE j; bit testb; for(j=1;j<=8;j++) {

testb=dat&0x01; dat=dat>>1;

if(testb) //写 1 { ds=0; i++;i++; ds=1;

i=8;while(i>0)i--; } else {

ds=0; //写 0 i=8;while(i>0)i--; ds=1; i++;i++;

32

} } }

void tempchange(void) //DS18B20 开始获取温度并转换 {

dsreset(); delay(1);

tempwritebyte(0xcc); // 写跳过读ROM指令 tempwritebyte(0x44); // 写温度转换指令 }

uint get_temp() //读取寄存器中存储的温度数据 {

BYTE a,b;

dsreset(); delay(1);

tempwritebyte(0xcc); tempwritebyte(0xbe);

a=tempread(); //读低8位 b=tempread(); //读高8位 temp=b;

temp<<=8; //两个字节组合为1个字 temp=temp|a;

temp = temp *(0.625);//温度值扩大10倍,精确到1位小数 }

void ds1820disp(uint temp1)//温度值显示 {

disdata[0]= temp1 /1000+0x30;//百位数

disdata[1]= temp1 %1000/100+0x30;//十位数 disdata[2]= temp1%100/10+0x30;//个位数 disdata[3]=0x2e;

disdata[4]= temp1 %10+0x30;//小数位

33

return temp; //temp是整型

}

void main() {

lcd_init();//初始化显示 while(1) {

tempchange();

ds1820disp(get_temp());//显示 display(); } }

5.1课程设计总结

通过做本课题,使我了解LCD1602液晶显示器和DS18B20的基本理论知识,更深入的了解单片机的开发应用和C编程控制。为以后从事单片的这方面的工作和以后的学习打下了良好的基础,树立了独立从事设计制作的信心。同时也培养了我认真做事的态度,和独立学习的能力。

从得到题目到查找资料,在这一个充满挑战,充满热情并伴随打击的过程中,我感触颇深,它是对我做事的毅力和耐心的考验。我在这个过程中深刻的感受到了做设计的意义所在,和我一样真正投入了身心去做的人也一定会有同样的感触。

6.1参考文献

郭天祥.51单片机C语言教程.电子工业出版社

34

因篇幅问题不能全部显示,请点此查看更多更全内容