液晶显示电冰箱温控器实验报告

更新时间:2024-04-18 02:56:01 阅读量: 综合文库 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

计算机/软件学院项目实践

常州信息职业技术学院

智能电子产品综合项目实践

设计报告

2011 — 2012 学年 第 二 学期

项目: 液晶显示电冰箱温控器的设计 班级: 学号: 11111111 姓名: XXX 授课教师: XXX

制定日期: 年 月 日

1

计算机/软件学院项目实践

摘 要

近些年来,家电领域产品变化、技术发展、更新换代之快简直令人目不暇接,但作为白色家电冰箱的变化似乎不大。

传统的电冰箱的冷藏室温控器旋钮一般有7个数字,这些数字并不表示冰箱内具体的温度值,而是表示所控制的温度档位。数字越小,箱内温度越高。随着人们的生活水平的提高,对冰箱的控制功能要求越来越高,这对电冰箱控制器提出了更高的要求,传统冰箱的温控器也就无法满足人们的需求了。因此,能够实现精确控制温度、方便的设定和修改并且能够实时显示当前温度是非常重要的。

随着技术的发展,目前有些冰箱采用了电脑只能温控及LCD(或LED)箱门外温度显示。所谓智能温控就是通过感温头精确感应,把冰箱内温度的变化传递给中央控制芯片,由芯片控制制冷系统使冰箱内温度达到显示屏上设定值,使用者只需要根据食物的种类不同设定不同的温度即可,以此达到最大的保鲜程度。

这里介绍一种电脑型电冰箱温控器的设计电路,使用128*64字符型带背光的液晶模组作显示,显得豪华、气派,具有时代气息。

2

计算机/软件学院项目实践

摘 要 ............................................ 2 第一章 引 言 ...................................... 4 第二章 总体设计方案 .............................. 5 2.1系统功能描述 ............................... 5 2.2系统总体结构 ............................... 5 图2-1系统整体框图 ............................. 5 第三章 硬件系统的设计 ............................ 6 3.1微处理器(单片机) ......................... 6 3.2 温度传感器DS18B20 ......................... 7 第四章 软件系统的设计 ........................... 10 4.1液晶显示模块(TG12864.c) ................. 10 4.2 测温系统(DS18B20.c) ..................... 11 4.3 定时模块(TIME.c) ........................ 11 第五章 仿真机的调试与运行 ....................... 13 第6章 结束语 ................................... 14 附录: .......................................... 14

3

计算机/软件学院项目实践

第一章 引 言

随着集成电路技术的发展,单片微型计算机的功能也不断增强,许多高性能的新型机种不断涌现出来。单片机以其功能强、体积小、可靠性高、造价低和开发周期短等优点,称为自动化和各个测控领域中广泛应用的器件,在工业生产中称为必不可少的器件,尤其在日常生活中发挥的作用也越来越大。人们对家用电冰箱的控制功能越来越高,这对电冰箱控制器提出了更高的要求。多功能,智能化是其发展方向之一,传统的机器控制,简单的电子控制已经难以满足发展的要求。而采用基于单片机温度控制系统,不仅可大大缩短设计新产品的时间,同时只要增加少许外围器件在软件设计方面就能实现功能的扩展,以及智能化方面的提高,因此可最大限度地节约成本。本文即为基于单片机的电冰箱温度控制系统。

目前市场销售的双门直冷式电冰箱,含有冷冻室和冷藏室,冷冻室通常用于冷冻的温度为-6~-18℃;冷藏室用于在相对冷冻室较高的温度下存放食品,要求有一定的保鲜作用,不能冻伤食品,室温一般为0~10℃.

传统的电冰箱温度一般是由冷藏室控制,冷藏室、冷冻室的不同温度是通过调节蒸发器在两室的面积大小来实现的,温度调节完全依靠压缩机的开停来控制.但是冰箱内的温度受诸多因素的影响,如放入冰箱物品初始温度的高低、存放品的散热特性及热容量、物品在冰箱的充满率、环境温度的高低、开门的频繁程度等.因此对这种受控参数及随机因素很多的温度控制,既难以建立一个标准的数学模型,也无法用传统的PID调节来实现.一台品质优良的电冰箱应该具有较高的温度控制精度,同时又有最优的节能效果,而为了达到这一设计要求采用模糊控制技术无疑是最佳的选择。

传统的电冰箱的冷藏室温控器旋钮一般有7个数字,这些数字并不表示冰箱内具体的温度值,而是表示所控制的温度档位。数字越小,箱内温度越高。随着人们的生活水平的提高,对冰箱的控制功能要求越来越高,这对电冰箱控制器提出了更高的要求,传统冰箱的温控器也就无法满足人们的需求了。因此,能够实现精确控制温度、方便的设定和修改并且能够实时显示当前温度是非常重要的。

随着技术的发展,目前有些冰箱采用了电脑只能温控及LCD(或LED)箱门外温度显示。所谓智能温控就是通过感温头精确感应,把冰箱内温度的变化传递给中央控制芯片,由芯片控制制冷系统使冰箱内温度达到显示屏上设定值,使用者只需要根据食物的种类不同设定不同的温度即可,以此达到最大的保鲜程度。

本设计介绍一种电脑型电冰箱温控器的设计电路,使用128*64字符型带背光的液晶模组作显示,显得豪华、气派,具有时代气息。

4

计算机/软件学院项目实践

第二章 总体设计方案

2.1系统功能描述

随着技术的发展,目前有些冰箱采用了电脑只能温控及LCD(或LED)箱门外温度显示。所谓智能温控就是通过感温头精确感应,把冰箱内温度的变化传递给中央控制芯片,由芯片控制制冷系统使冰箱内温度达到显示屏上设定值,使用者只需要根据食物的种类不同设定不同的温度即可,以此达到最大的保鲜程度。

该系统通过感温头精确感应,把冰箱内部温度的变化传递给中央控制芯片,由芯片控制制冷系统使冰箱内的温度达到显示屏上设定的值,使用者只需要根据食物的种类不同设定不同的温度即可,以此达到最大的保鲜程度。

此外,液晶显示屏上还将显示时间,设定温度,以及当前冰箱内部温度。用户可以利用键盘对冰箱温度进行设定,同时还可以对时间进行调整。

2.2系统总体结构

图2-1为液晶显示电冰箱温控器系统构成框图。AT89S51单片机为控制核心,它既负责读取DS18B20测得的冷藏室温度并输出至液晶模组显示,同时又产生实时时钟供液晶显示,并且还负责键盘输入扫描及输出控制压缩机的运行等。

测试温度 4*键盘输入 单 片 机 128*64点阵液晶显示模块

图2-2 系统整体框图

5

计算机/软件学院项目实践

第三章 硬件系统的设计

3.1微处理器(单片机)

AT89S51是美国ATMEL公司生产的低功耗,高性能CMOS 8位单片机,片内含4k bytes的可系统编程的Flash只读程序存储器,器件采用ATMEL公司的高密度、非易失性存储技术生产,兼容标准8051指令系统及引脚。它集Flash程序存储器既可在线编程(ISP)也可用传统方法进行编程及通用8位微处理器于单片芯片中。

AT89S51提供以下标准功能:4k字节Flash闪速存储器,128字节内部RAM, 32个I/O口线,看门狗(WDT),两个数据指针,两个16位定时/计数器,一个5向量两级中断结构,一个全双工串行通信口,片内振荡器及时钟电路。同时,AT89S51可降至0Hz的静态逻辑操作,并支持两种软件可选的节电工作模式。空闲方式停止CPU的工作,但允许RAM,定时/计数器,串行通信口及中断系统继续工作。掉电方式保存RAM中的内容,但振荡器停止工作并禁止其它所有部件工作直到下一个硬件复位。

AT89S51的引脚图和实物图分别如图3.1.1和图3.1.2所示。

图3.1.1 AT89S51 图3.1.2 AT89S51实物图

6

计算机/软件学院项目实践

3.2 温度传感器DS18B20

(1)适应电压范围宽,电压范围:3.0-5.5V,在寄生电源方式下可以由数据线供电;

(2)独特的单线接口方式,DS18B20在与微处理器连接时仅需要一条口线即可实现微处理器与DS18B20的双向通讯;

(3)DS18B20支持多点组网功能,多个DS18B20可以并联在唯一的三线上,实现组网多点测量。

(4)DS18B20在使用中不需要任何外围元件,全部传感元件及转换电路集成在形如一只三极管的集成电路内;

(5)温度范围-55℃+125℃,在-10~+85℃时精度为±0.5℃;

0.125℃,0.0625℃,可以实现高精度测温;

(7)在9位分辨率时最多在93.75ms内把温度转换为数字,12位分辨率时最多在750ms内把温度值转换为数字,速度更快;

(8)测量结果直接输出数字温度信号,以“一线总线”串行传送给CPU,同时可以传送CRC校验码,具有极强的抗干扰纠错能力;

(9)负压特性:电源极性接反时,芯片不会因为发热而烧毁,但是不能正常工作。

GND

DQ

VDD

DALLAS DS18B20 1 2 3 图3.2.1 DS18B20

(6)可编程的分辨率为9~12位,对应的可分辨温度分别为0.5℃,0.25℃,

图3.2.2 单片机与DS18B20的接口电路

7

计算机/软件学院项目实践

3.3 点阵液晶显示模块TG12864B

TG12864B是128*64点阵的液晶显示模块,由左右两块独立的64*64点阵液晶屏拼接而成,每半屏有一个8*64*8bitDDRAM,左右半屏驱动电路及存储器分别由片选信号CS1和CS2选择。

TG12864B能够显示各种字符(128个8*8点阵字符,或32个16*16点阵的汉字)或图形,具有8位标准数据总线的控制信号,可与单片机接口直接相连。

3.4 按键功能

因本系统使用的按键数目少,故按键采用硬件去抖。按键电路如图2-6 所示。用两个与非门构成一个RS触发器。当按键未按下时输出为1;刚键按下时输出为0。此时即使用按键的机器性能,使按键因弹性抖动而产生瞬时断开(抖动跳开B),只要按键不返回原来状态A,双稳态电路的状态不会改变,输出保持为0,不会产生抖动的波形。也就是说,即使B点的电压波形是抖动的,但经双稳态电路之后,其输出为正规的矩形波。

图3.3 TG12864B原理图

图3.4 按键电路

8

计算机/软件学院项目实践

3.5 整体硬件连接电路图

图3.5 整体硬件连接图

9

计算机/软件学院项目实践

第四章 软件系统的设计

4.1液晶显示模块(TG12864.c)

程序开始,首先定义LCD复位控制脚,可以接受复位信号

定义DI、RW、CS跟EN口,使程序效果可在液晶模块上显示

设置TG12864B液晶模块的七条指令,即开/关显示指令、显示起始行指令、页地址、列地址、读状态、写显示数据跟读显示数据,通过这7条指令,可以对液晶屏进行读写控制。

TG12864B液晶模块内部没有字库,所以下一步必须将ASCII的点阵信息放在程序储存器中,用PCtoLCD2002软件提取汉字点阵,显示时根据ASCII值找到该字符的点阵码送到液晶模块DDRAM中。

用LCD_DispFill(uchar filldata)函数对液晶屏进行充填,用LCD_DispIni函数对液晶模块初始化。

用LCD_DispChar函数在液晶屏的cy(0-7)

行、cx(0-15)列能够显示字符dispdata;用LCD_DispStr函数在液晶屏的cy(0-7)

Y

设置汉字的页、列地址,显示在左半屏显在右半屏显列号<8? N 以filldata充填液晶初始化液晶屏 复位驱动芯片 打开显示 清屏 开始 在液晶屏的cy(0-3)行、cx(0-7)列显示汉字字符dispdata 求出汉字在屏幕上的起始结束 行、cx(0-15)列能够显示字符disp_str;用LCD_DispHZ函数在液晶屏的cy(0-7)行、cx(0-15)列能够显示汉字字符dispdata;用LCD_DispHZStr函数在液晶屏的cy(0-7)行、cx(0-15)列能够显示汉字字符串 disp_str。

液晶模块在主函数中的功能:在第一行显示“冷藏温度: ℃”;第二行显示“冷冻温度: ℃”;第三行显示“压缩机:开/关”;第四行显示时间,并开始计时。

10

计算机/软件学院项目实践

4.2 测温系统(DS18B20.c)

先检测是否有DS18B20, 向总线写入一个字节, 从总线上读取一个字节, 复位DS18B20, 发READ ROM命令, 读取温度低字节、高字节, 保存16位温度值。

用bit reset(void)函数检测是否有DS18B20;用void wrbyte(uchar d)函数向总线写入一个字节; uchar rdbyte(void) 从总线上读取一个字节;err=reset(); 语句复位DS18B20;再根据DS18B20,发READ ROM命令读取和保存温度值。

测温模块在主函数中的功能:设定冷藏室初始温度,跟冷冻室初始温度。 4.3 定时模块(TIME.c)

定时模块,在主程序中起到计时的作用,我们在这段模块中需要用到定时器,定时器有四种工作方式,由T0决定。

而T0的工作方式由M1、M0设定。

M1M0=00,方式0;M1M0=01,方式1;M1M0=10,方式2;M1M0=11,方式3。 方式2是可以自动重装的工作方式,所以我们一般将T0工作于工作方式2。 在该模块中,使用count记录中断次数,一次中断250微秒,4000次即一秒,给秒加一,中断清零,重计;秒满60次,秒清零,给分加1;分满60次,分清零,时加1;时满24次,时清零。

开始 4.2 测温流程图

复位DS18B20 发匹配命令 发送当前传感器的序列号 发读暂存器命令 读取温度值 开始 结束

定时器/计数器T0 中断程序 D3 GATE D2 C/T D1 M1 D0 M0 定义定时器工作方式 判断溢出,若溢出,则清零,下一位加一 结束

11

计算机/软件学院项目实践

4.4 按键模块

扫描程序采用边延时边扫描的方法,当设置键KSET按下一次,进入预制温度界面,按KINC(+)键和KDEC(-)键设置冷藏室温度。当键KDOWN按下一次,按KINC(+)键和KDEC(-)键设置冷冻室温度。当长按键KSET,设置完成,进入原始设置界面。

开始 Y 是否按键 Y 是否加减 N dbuf值自减1 dbuf值自增1 返回dbuf值

图4.4 按键模块流程图

12

计算机/软件学院项目实践

第五章 仿真机的调试与运行

5.1 调测试方法

将程序放在Keil uVision2软件中运行,如有错误,Output window栏可以显示大概错误位置及错误原因,然后依据这些修改错误程序(如果自己实在解决不了,可以请教老师、同学,或者上网查阅)。 当编译无错误、基本没警告时,然后通过USB型单片机仿真实验仪将程序效果显示出来,这里需注意,在Keil uVision2中要设置与USB型单片机仿真实验仪相关联,以及口位置要一致(比如程序中DI=P1^6,RW=P1^5,CS=P1^3,EN=P1^4,仿真实验仪上对应的DI口要连接P1.6口,RW口连接P1.5口,CS口连接P1.3口,E口连接P1.4口),不然无法在液晶屏上显示。

当仿真实验仪的液晶模块上显示数据时,查看实际效果是不是与自己要做的效果一样,如果不一样,具体看哪一模块出错了,哪一段程序错了。然后回到函数,在Keil uVision2中,该模块中,可以使用“//”或者“/**/”把不相关的程序先给注解掉,然后修改解决问题;如果,主函数中某一段程序引起所有显示不正确,可以使用显示的内容,找到错误位置。

按钮,对应液晶屏上

5.2 调试过程中出现的问题及解决办法

问题一:TG12864B中,左半屏内容显示到右半屏,右半屏显示到左半屏。 解决方法:显示问题,明显是模块TG12864.c中的问题,在定义中发现左半屏跟右半屏选择时,定义错误。

问题二:将temp[1]直接右移4位,温度显示不正常

解决方法:因为temp[1]是特定的一个数,不能左移右移,当把它赋予一个变量时,可以左移右移。

问题三:当按下KSET_LONG键时,设置的温度 与原来的数据显示在一起 解决方法:没有做清屏处理。 问题四:显示的时间不动

解决方法:定时函数中的变量count在主函数里没有申明,导致定时器的值传不过来,所以时间没有动。

问题五:在做压缩机开关时,压缩机无法按照要求开关

解决方法:读取过来的温度值是16位的,它的低四位表示的小数,需要对它进行一些处理才可与给的条件进行比较。

13

计算机/软件学院项目实践

第6章 结束语

实践很快结束了,在这次实践过程中,我要感谢我的老师以及同学,在我遇到问题,不知道怎么做下去的时候,遇到问题迷茫疑惑的时候,耐心的开导我,一步一步运行程序帮我分析问题在哪,然后寻找解决办法。

通过这次实践,我受益匪浅。不仅将以前关于单片机的知识给巩固了,还磨练了语言交流能力跟逻辑思维能力,不会的时候,不是干坐着,而是要勇于跟老师同学交流,由点到线,分析问题所在。老师让我们独立完成程序,不仅是一种学习方法,还是一种人生态度,生活是自己的,不能老是依赖于别人,要通过自己的努力缔造未来,然后像调试程序那样,不断的完善自己。

这次实践,我也意识到自身学习知识的许多问题,主要有以下几点: 1、专业知识掌握的不够全面。尽管在学校认真学习了专业知识,但是当前所掌握的知识面不够广。

2、专业实践阅历远不够丰富。由于专业实践时间较少,因此很难将所学知识运用与实践中去,通过实践所获取的阅历更是很短缺。

3、专业知识在实践中运用不够灵活。通过这次实践,我切实感受到以前所学的专业知识运用欠灵活。这主要是对所学的知识没有形成一套完整的体系,这些零散的知识点运用起来很困难。

4、对理论知识的掌握不够扎实,实践时用到了才知道自己没学好。 这次实践给我的总体感受就是我懂得了怎么去动手了,很多的现实情况就是这样。只要你去实践过了,实践过了,你就知道是怎么回事了,要不你就永远是门外汉,什么都不懂。我对自己专业将来的发展很有信心,所以我相信自己会在今后的工作中可以做的更好的。只要自己一直去实践就可以,在实践懂得了之后,运用到实际中之后,我就可以做好了,相信自己一定能够在将来取得成功!

14

计算机/软件学院项目实践

附录:TG12864.C

#include #include #include

#define uchar unsigned char #define uint unsigned int

sbit LCD_RST = P3^7; // 定义LCD复位控制脚 sbit DI=P3^4; sbit RW=P3^5; sbit EN=P3^6; sbit CS=P3^3; sbit RDY=P3^7; sfr LCD=0x80;

#define LCD_DISPON 0x3f // 打开LCM显示命令

#define LCD_STARTROW 0xc0 // 设置起始行命令,用LCD_STARTROW+x设置起始行(x<64)

#define LCD_ADDRSTRY 0xb8 // 设置页地址命令,用LCD_ADDRSTRX+x设置当前页(x<8)

#define LCD_ADDRSTRX 0x40 // 设置列地址命令,用LCD_ADDRSTRY+x设置当前列(x<64)

#define CS1 0 //左半屏选择 #define CS2 1 //右半屏选择

/***************************************************************** 功能:命令字cmd送液晶屏命令口 入口参数port:左右半屏选择? 出口参数cmd:命令字

******************************************************************/ void LCD_WrCmd(bit port, uchar cmd) { EN=0; CS=port; DI=0; RW=0; EN=1; LCD=cmd; EN=0; }

/*****************************************************************

15

计算机/软件学院项目实践

功能:数据wrdata送液晶屏数据 入口参数port:左右半屏选择 出口参数wrdata:数据

*****************************************************************/ void LCD_WrDat(bit port, uchar wrdata) { EN=0; CS=port; DI=1; RW=0; EN=1;

LCD=wrdata; EN=0; }

uchar code HZTAB[]={??};

uchar code ASCII_TAB[480] ={??};//0x20~0x7F之间 ASCII码对应的点阵数据表

/***************************************************************** 功能:以filldata充填液晶屏

入口参数filldata:充填液晶屏数据 出口参数:无

******************************************************************/ void LCD_DispFill(uchar filldata) //以filldata充填液晶屏 { uchar x, y;

LCD_WrCmd(CS1,LCD_STARTROW); LCD_WrCmd(CS2,LCD_STARTROW); for(y=0; y<8; y++)

{ LCD_WrCmd(CS1,LCD_ADDRSTRY+y);

LCD_WrCmd(CS1,LCD_ADDRSTRX); LCD_WrCmd(CS2,LCD_ADDRSTRY+y); LCD_WrCmd(CS2,LCD_ADDRSTRX); for(x=0; x<64; x++)

{ LCD_WrDat(CS1,filldata); LCD_WrDat(CS2,filldata); } } }

/***************************************************************** 功能:液晶模块初始化 入口参数:无 出口参数:无

******************************************************************/ void LCD_DispIni(void) //液晶模块初始化

16

计算机/软件学院项目实践

{ uint i; LCD_RST = 0;

for(i=0; i<500; i++); LCD_RST = 1;

LCD_WrCmd(CS1,LCD_DISPON); LCD_WrCmd(CS1,LCD_STARTROW); LCD_WrCmd(CS2,LCD_DISPON); LCD_WrCmd(CS2,LCD_STARTROW); LCD_DispFill(00);

LCD_WrCmd(CS1,LCD_ADDRSTRY+0); LCD_WrCmd(CS1,LCD_ADDRSTRX+0); LCD_WrCmd(CS2,LCD_ADDRSTRY+0); LCD_WrCmd(CS2,LCD_ADDRSTRX+0); }

/******************************************************************* 功能:在液晶屏显示字符 入口参数cy:坐标行0-7 入口参数cx:坐标列0-15

出口参数dispdata:在cy,cx位置显示的字符

*******************************************************************/

void LCD_DispChar(uchar cy, uchar cx, char dispdata) //在液晶屏的cy(0-7)行、cx(0-15)列显示字符dispdata { uchar code *pch; uchar i; bit port; cy = cy&0x07; cx = cx&0x0f;

pch = &ASCII_TAB[(dispdata-0X20)*5]; if( (cx&0x08) == 0 ) { port=CS1; i=cx<<3; } else

{ port=CS2;

i = (cx&0x07)<<3; }

LCD_WrCmd(port,LCD_ADDRSTRX+i); LCD_WrCmd(port,LCD_ADDRSTRY+cy); for(i=0; i<5; i++); LCD_WrDat(port,0x00); for(i=0; i<5; i++) {

LCD_WrDat(port,*pch);

17

计算机/软件学院项目实践

pch++; }

LCD_WrDat(port,0x00); for(i=0; i<5; i++); LCD_WrDat(port,0x00); }

/***************************************************************** 功能:在液晶屏孟允咀址? 入口参数cy:坐标行0-7 入口参数cx:坐标列0-15

出口参数disp_str:在cy,cx位置显示的字符串

******************************************************************/

void LCD_DispStr(uchar cy, uchar cx, char *disp_str) //在液晶屏的cy(0-7)行、cx(0-15)列显示字符disp_str { while( *disp_str != '\\0') { cy = cy&0x07;

cx = cx&0x0f;

LCD_DispChar(cy, cx, *disp_str); disp_str++; cx++;

if(cx>15) cy++; } }

void LCD_DispHZ(uchar cy, uchar cx, uchar dispdata) //显示 {

uchar code *pdat; uchar i,s,page; bit port; cy = cy&0x03; cx = cx&0x07;

pdat = &HZTAB[dispdata*32]; if( (cx&0x04) == 0 ) { port=0; s=cx<<4; } else

{ port=1;

s = (cx<<4)-64; }

for(page=0;page<2;page++) {

LCD_WrCmd(port,LCD_ADDRSTRX+s);

18

计算机/软件学院项目实践

LCD_WrCmd(port,LCD_ADDRSTRY+(cy<<1)+page); for(i=0; i<5; i++); for(i=0; i<16; i++)

{ LCD_WrDat(port,*pdat); pdat++; }

for(i=0; i<5; i++); } }

void LCD_DispHZStr(uchar cy, uchar cx, uchar *disp_str) { while( *disp_str != 0xff) { cy = cy&0x03;

cx = cx&0x07;

LCD_DispHZ(cy, cx, *disp_str); disp_str++; cx++; if(cx>7) {

cy++; cx=0; } } }

DS18B20.C

#define uchar unsigned char #define uint unsigned int #include #include

sbit DQ=P1^0; bdata uchar dat; sbit dat0=dat^0; sbit dat7=dat^7;

uchar code id[2][8]={{0x28,0x30,0xc5,0xb8,0x00,0x00,0x00,0x8e}, {0x28,0x31,0xc5,0xb8,0x00,0x00,0x00,0xb9}};

void delay15(uchar n) //15us延时函数 { do {

_nop_(); _nop_();

19

计算机/软件学院项目实践

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

_nop_(); n--;

}while(n); }

void late(void) { uchar i;

for(i=0;i<200;i++) delay15(200); }

bit reset(void) //初始化DS18B20 { bit err;

DQ=0; //在数据线上产生600us的低电平 delay15(40);

DQ=1; //数据线拉高 delay15(4); //延时60us

err=DQ; //读取数据线状态,err=0:复位成功 delay15(18); // err=1:复位失败 return(err); }

void wrbyte(uchar d) //向DS18B20写入一个字节 { uchar i; dat=d;

for(i=8;i>0;i--) //循环写8位(先低位,后高位) { DQ=0; //产生15us的负脉冲 delay15(1);

DQ=dat0; //将当前数据位送数据线

dat=dat>>1; //将下一位要写入的数据移到最低位 delay15(1); //延时15us

DQ=1; //数据线拉高,为写入下一位做准备 } }

uchar rdbyte(void) //从DS18B20 读取一个字节 { uchar i;

dat=0; //读出数据初值为0

20

计算机/软件学院项目实践

for(i=8;i>0;i--) //循环读8位(先低位,后高位) { dat=dat>>1; //读出数据先右移一位 DQ=0; //产生1us的负脉冲 _nop_();

DQ=1; //数据总线拉高 delay15(1); //延时15us dat7=DQ; //读取数据

delay15(4); //延时,为读下一位做准备 }

return(dat); }

void readid(uchar id[]) { uchar n;

reset(); //复位DS18B20 wrbyte(0x33); //发READ ROM命令

for(n=0;n<=8;n++) //读取8个字节的序列号 id[n]=rdbyte(); }

void gettemp(int temp[]) { uchar m,n; uchar h,l; reset();

wrbyte(0xcc); wrbyte(0x44); late();

for(m=0;m<2;m++) { reset();

wrbyte(0x55); for(n=0;n<8;n++) wrbyte(id[m][n]); wrbyte(0xbe); l=rdbyte(); h=rdbyte();

temp[m]=h*256+l; }

TIME.C

#include #include #include #include

extern unsigned char time[]; //时间:时、分、秒缓存 extern unsigned int count;

21

计算机/软件学院项目实践

void InitTimer0(void) {

TMOD = 0x01; //定时器工作在方式2 TH0 = -25000/256; //定时时间为 250us TL0 = -25000%6;

EA = 1; //单片机中断 ET0 = 1; //允许T0中断 TR0=1 ; }

void TimeOff(void) {

EA = 0; //单片机中断 禁止 ET0 = 0; //允许T0中断 禁止 TR0=0 ; }

void time0(void) interrupt 1

{ TH0 = -25000/256; //定时时间为 250us TL0 = -25000%6; count++;

if(count==40) { count=0; time[2]++;

if(time[2]==60) { time[2]=0; time[1]++;

if(time[1]==60) { time[1]=0; time[0]++;

if(time[0]==24) time[0]=0; } } } }

main.c

#include

#define uchar unsigned char

22

计算机/软件学院项目实践

#define uint unsigned int

extern void LCD_DispIni(void);

extern void LCD_DispFill(uchar filldata);

extern void LCD_DispChar(uchar cy,uchar cx,char dispdata); extern void LCD_DispStr(uchar cy,uchar cx,char*disp_str); extern void LCD_DispHZ(uchar cy,uchar cx,uchar dispdata); extern void LCD_DispHZStr(uchar cy,uchar cx,uchar*disp_str); extern void gettemp(int temp[]); extern void InitTimer0(void);

uchar dp[16]={0,0,1,1,2,3,3,4,5,5,6,6,7,8,8,9}; //#define KSET 0xe0 #define KSET_LONG 0xe1 #define KINC 0xd0 #define KDEC 0xb0 #define KDOWN 0x70

uint count;

char dbuf[2]={5,-5};

uchar str[6]={0,0,0,0,0,0}; char cang=5; char dong=-5;

uchar time[3]={12,34,56};

void delay(uchar t) {uchar i; while(t--)

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

void LCD_DispDat(uchar cy,uchar cx,char dat) {uchar str[4]; bit zf=0; if(dat<0) { zf=1; dat=-dat; }

str[1]=dat/10+0x30; str[2]=dat+0x30; str[3]=0; if(zf==1)

{ if(str[1]=='0') { str[0]=' '; str[1]='-'; }

23

小数部分转换 计算机/软件学院项目实践

else

str[0]='-'; } else

{ if(str[0]=='0') str[1]=' '; str[0]=' '; }

LCD_DispStr(cy,cx,str); }

uchar GetKey(void) {uchar key; uchar t;

if((key=P2&0xf0)==0xf0) return 0xff; for(t=0;t<5;t++) delay(5);

if((key=P2&0xf0)==0xf0) return 0xff; while((P2&0xf0)!=0xf0) {delay(5);

if(t<250) t++; }

if((t>100)&&(key==0xE0)) return 0xE1; return key; }

void DispTime(void) {

LCD_DispDat(7,5,time[0]); LCD_DispChar(7,8,':'); LCD_DispDat(7,9,time[1]); LCD_DispChar(7,12,':'); LCD_DispDat(7,13,time[2]); }

void EditWD(void) {uchar no=0; uchar key;

LCD_DispDat(no*2+1,9,dbuf[no]); while(1)

{key=GetKey();

if(key==KINC) //+ {dbuf[no]++;

LCD_DispDat(no*2+1,9,dbuf[no]);

24

计算机/软件学院项目实践

}

else if(key==KDEC) //- {dbuf[no]--;

LCD_DispDat(no*2+1,9,dbuf[no]); }

else if(key==KDOWN)

{LCD_DispDat(no*2+1,9,dbuf[no]); no=(no+1)&0x01;

LCD_DispDat(no*2+1,9,dbuf[no]); }

else if(key==KSET_LONG) {

cang=dbuf[0]; dong=dbuf[1]; LCD_DispIni(); break; } } }

void main(void) {

uchar str[6]={0,0,0,0,0,0}; uchar i,key; int temp[2]; bit zf;

uchar buf[5]={0,1,3,4,0xff}; //冷藏温度 uchar buf1[5]={0,6,3,4,0xff}; // 冷冻温度 uchar buf2[5]={8,9,10,5,0xff}; // 压缩机 uchar buf3[5]={0,1,13,14,0xff}; // 冷藏设置 uchar buf4[5]={0,6,13,14,0xff}; // 冷冻设置 LCD_DispIni();

InitTimer0(); while(1) {

DispTime(); //显示当前时? LCD_DispHZStr(0,0,buf); LCD_DispStr(1,8,\ LCD_DispHZ(0,7,7);

LCD_DispHZStr(1,0,buf1); LCD_DispStr(3,8,\ LCD_DispHZ(1,7,7);

LCD_DispHZStr(2,0,buf2);

25

计算机/软件学院项目实践

key=GetKey(); if(key==KSET) {

LCD_DispIni();

LCD_DispHZStr(0,0,buf3); LCD_DispStr(1,8,\ LCD_DispHZ(0,7,7);

LCD_DispHZStr(1,0,buf4); LCD_DispStr(3,8,\ LCD_DispHZ(1,7,7); EditWD(); }

gettemp(temp);

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

temp[i]=temp[i]>>4;

if((temp[0]

LCD_DispHZ(2,5,11); temp[i]=temp[i]<<4;

zf=0;

if(temp[i]<0) { zf=1;

temp[i]=-temp[i]; }

str[4]=dp[temp[i]&0x0f]+0x30; temp[i]=temp[i]>>4;

str[0]=temp[i]/100+0x30; temp[i]=temp[i]0; str[1]=temp[i]/10+0x30; str[2]=temp[i]+0x30; str[3]='.'; if(zf==1)

{ if(str[1]=='0') { str[0]=' '; str[1]='-'; } else

str[0]='-';

26

计算机/软件学院项目实践

} else

{ if(str[0]=='0')

{ if(str[1]=='0') str[1]=' '; str[0]=' '; } }

LCD_DispStr(i*2+1,9,str); }

}

}

27

本文来源:https://www.bwwdw.com/article/16ip.html

Top