利用zigbee的无线单片机温度计课程设计2
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
目录
1 课题背景
1.1系统设计
1.2总体方框图
2 设计方案简述
2.2DS18B20数字温度传感器
2.2.1 DS18B20的性能特点
错误!未定义书签。
.2 .2DS18B20的管脚分布
2.2.3 DS18B20的内部结构和工作方式
2.3 AT89C52单片机
2.41602型LCD
2.4.1 1602型LCD的特性
2.4.2 1602型LCD的操作控制
2.5 DS1302模块分析
2.6 zigbee无线发送模块
3.1 温度采集模块
3.2单片机控制系统
3.3温度和时间显示模块
3.4软件设计
3.4.1 DS18B20的温度采集程序
3.5 系统主程序
4 设计结果及分析
4.1测试环境及工具
4.2测试方法和测试结果
5 总结
附录一系统总电路图
附录二实验结果测试图
附录三系统源代码
摘要
本次单片机课程设计本人设计了智能数字温度计,其功能主要有,可以测试温度,精确到小数点后三位;其次还附加了时钟功能,其可以显示秒到年的具体时间;并且本人还利用了zigbee无线传输模块,将采集到的温度值无线发送到电脑上。
具体设计在下面详细分析。
关键词:温度计;ds18b20,zigbee模块,ds1302,89c52
1 课题背景
1.1 系统设计
本课程设计的任务是设计一个数字温度计。
由于在生产生活中都有很多领域需要测量温度,所以温度计的好坏即测量灵敏度,测温范围,稳定度以及实用性和适用性就显得尤为重要。
传统温度计通常利用固体、液体、气体受温度的影响而热胀冷缩等的现象为设计的依据,因此这种方法无论从设计原理还是视觉读数都有很大的误差。
本次课程设计以DS18B20作为数字温度传感器,其具有线性优良、性能稳定、灵敏度高、抗干扰能力强、使用方便等优点,可以大大提高测量温度的精度,并且该设计还具备了无线传输功能,采集到的温度可实时地传送到电脑,有利于对温度设备的远程监控,和远程控制,这是未来智能设备(包括智能家居)的发展方向。
1.2 总体方框图
现将系统模块总体设计框图列于下图1中:
2 设计方案简述
2.1数字温度计设计方案论证
由于本设计是测温电路,可以使用热敏电阻之类的器件利用其感温效应,在将随被测温
度变化的电压或电流采集过来,进行A/D 转换后,就可以用单片机进行数据的处理,在显示
电路上,就可以将被测温度显示出来,这种设计需要用到A/D 转换电路,其中还涉及到电阻
与温度的对应值的计算,感温电路比较麻烦。
而且在对采集的信号进行放大时容易受温度的
影响出现较大的偏差。
2.1.2 方案二
进而考虑到用温度传感器,在单片机电路设计中,大多都是使用传感器,所以这是非常
容易想到的,所以可以采用一只温度传感器DS18B20,此传感器,可以很容易直接读取被测
温度值,进行转换,电路简单,精度高,软硬件都以实现,而且使用单片机的接口便于系统
的再扩展,满足设计要求。
从以上两种方案,很容易看出,采用方案二,电路比较简单,费用较低,可靠性高,软件设
计也比较简单,故采用了方案二。
2.2 DS18B20数字温度传感器
DS18B20温度传感器是美国DALLAS半导体公司生产的DS18B20型单线智能温度传感器,属于新一代适配微处理器的智能温度传感器,与传统的热敏电阻等测温元件相比,它能直接读出被测温度,并且可根据实际要求通过简单的编程实现9-12位的数字值读数方式。
可广泛用于工业、民用、军事等领域的温度测量及控制仪器、测控系统和大型设备中。
它具有体积小,接口方便,传输距离远等特点。
2.2.1 DS18B20的性能特点
DS18B20从功能和技术的角度来说有以下性能特点:
●采用单总线专用技术,既可通过串行口线,也可通过其它I/O口线与微机接口,无
须经过其它变换电路,直接输出被测温度值(9位二进制数,含符号位)
●测温范围为-55℃至+125℃,测量分辨率最小为0.0625℃
●内含64位经过激光修正的只读存储器ROM
●DS18B20在使用中不需要任何外围元件,全部传感元件及转换电路集成在形如一只
三极管的集成电路内
●适配各种单片机或系统机
●测量结果直接输出数字温度信号,以“一线总线”串行传送给CPU,同时可传送
CRC校验码,具有极强的抗干扰纠错能力
●用户可分别设定各路温度的上、下限
●适应电压范围宽,3.0~5.5V,在寄生电源方式下可由数据线供电
2.2.2 DS18B20的管脚分布
独特的一线接口,只需要一条口线通信多点能力,简化了分布式温度传感应用无需外部元件可用数据总线供电,电压范围为3.0 V至5.5 V 无需备用电源测量温度范围为-55℃至+125℃,华氏相当于是-10℉至+85℉范围内精度为±0.5℉。
其引脚排列见图2和表1。
1 2 3
图2 DS18B20的管脚分布图
表1 DS18B20的管脚分布说明
2.3.3 DS18B20的内部结构
和工作方式
DS1820主要包括寄生电源、
温度传感器、64位激光ROM单线接口、存放中间数据的高速暂存器(内含便笺式RAM),用于存储用户设定的温度上下限值的TH和TL触发器存储与控制逻辑、8位循环冗余校验码(CRC)发生器等七部分内部,其内部结构框图如图3所示。
有
门,
成温度测量。
计数门的开启时间由高温度系数振荡器来决定,每次测量前,首先将-55℃所对应的一个基数分别置入减法计数器1、温度寄存器中,计数器1和温度寄存器被预置在-55℃所对应的一个基数值。
减法计数器1对低温度系数晶振产生的脉冲信号进行减法计数,当减法计数器1的预置值减到0时,温度寄存器的值将加1,减法计数器1
的预置将重新被装入,减法计数器1重新开始对低温度系数晶振产生的脉冲信号进行计数,如此循环直到减法计数器计数到0时,停止温度寄存器的累加,此时温度寄存器中的数值就是所测温度值。
其输出用于修正减法计数器的预置值,只要计数器门仍关闭就重复上述过程,直到温度寄存器值大致等于被测温度值。
由于DS18B20的单线通讯功能是分时完成的,它有严格的时隙概念,因此读写时序很重要。
系统对DS18B20的各种操作按协议进行,操作协议为:初始化DS18B20发复位脉冲→写ROM功能指令→发存储器操作命令→处理数据。
DS18B20有六条控制命
2.3 AT89C52
AT89C52是此次课程设计的核心部分。
其管脚图如下:
AT89C52管脚图
AT89C52是低功耗、高性能的CMOS8位单片机。
片内带有8KB的Flash存储器,且允许在系统内改写或用编程器编程。
另外,AT89C52的指令系统和引脚与80C52完全兼容。
AT89C52各管脚功能如下:
VCC:供电电压;GND:接地;P0口:P0口为一个8位漏级开路双向I/O口,每脚可吸收8TTL门电流。
;P1口:P1口是一个内部提供上拉电阻的8位双向I/O口,P1口缓冲器能接收输出4TTL门电流;P2口:P2口为一个内部上拉电阻的8位双向I/O口,P2口缓冲器可接收,输出4个TTL门电流,当P2口被写“1”时,其管脚被内部上拉电阻拉高,且作为输入。
并因此作为输入时,P2口的管脚被外部拉低,将输出电流;P3口:P3口管脚是8个带内部上拉电阻的双向I/O口,可接收输出4个TTL门电流。
当P3口写入“1”后,它们被内部上拉为高电平,并用作输入;P3口管脚功能:P3.0是RXD(串行输入口);P3.1是TXD(串行输出口);P3.2是/INT0(外部中断0);P3.3是/INT1(外部中断1);P3.4是T0(记时器0外部输入);P3.5是T1(记时器1外部输入);P3.6是/WR(外部数据存储器写选通);P3.7是/RD(外部数据存储器读选通);P3口同时为闪烁编程和编程校验接收一些控制信号。
RST:复位输入。
当振荡器复位器件时,要保持RST脚两个机器周期的高电平时间。
ALE/PROG:当访问外部存储器时,地址锁存允许输出电平用于锁存地址的地位字节。
/PSEN:外部程序存储器的选通信号。
在由外部程序存储器取指期间,每个机器周期两次/PSEN有效。
但在访问外部数据存储器时,这两次有效的/PSEN信号将不出现。
/EA/VPP:当/EA保持低电平时,则在此期间外部程序存储器(0000H-FFFFH),不管是否有内部程序存储器。
XTAL1:反向振荡放大器的输入及内部时钟工作电路的输入。
XTAL2:来自反向振荡器的输出。
2.4 1602型LCD
本温度计的读数的显示是通过1602型LCD实现的,其具有微功耗、体积小、显示内容丰富、超薄轻巧的特点,常用在袖珍式仪表和低功耗应用系统中。
2.4.1 1602型LCD的特性
1602型LCD归纳起来有以下6大特点:
●+5V电压,对比度可调
●内含复位电路
●提供各种控制命令,如:清屏、字符闪烁、光标闪烁、显示移位等多种功能
●有80字节显示数据存储器DDRAM
●内建有192个5X7点阵的字型的字符发生器CGROM
●8个可由用户自定义的5X7的字符发生器CGRAM
2.4.2 1602型LCD的操作控制
1602液晶模块内部的字符发生存储器(CGROM)已经存储了160个不同的点阵字符图形,这些字符有:阿拉伯数字、英文字母的大小写、常用的符号、和日文假名等,每一个字符都有一个固定的代码,比如大写的英文字母“A”的代码是01000001B(41H),显示时模块把地址41H中的点阵字符图形显示出来,我们就能看到字母“A”。
因为1602识别的是ASCII码,试验可以用ASCII码直接赋值,在单片机编程中还可以用字符型常量或变量赋值,如'A'。
以下是1602的16进制ASCII码表地址:读的时候,先读左边那列,再读上面那行,如:感叹号'!'的ASCII为0x21,字母B的ASCII 为0x42。
附加功能模块
2.5 DS1302模块分析
DS1302的RST是复位/片选线,通过把RST输入驱动置高电平来启动所有的数据传送。
当RST为高电平时,所有的数据传送被初始化,允许对DS1302进行操作。
如果在传送过程中RST置为低电平,则会终止此次数据传送,I/O引脚变为高阻态。
其管脚图如下:
DS1302管脚图
各引脚功能:Vcc1为后备电源,VCC2为主电源,X1和X2是振荡源,
SCLK为输入端
RST输入有两种功能:首先,RST接通控制逻辑,允许地址/命令序列送入移位寄存器;其次,RST提供终止单字节或多字节数据的传送手
Ds1302部分电路图
2.6 zigbee无线发送模块
Zigbee是基于,ZigBee节点所属类别主要分三种,分别是协调器(Coodinator)、路由器(Router)、终端(End Device)。
统一网络中至少需要一个协调器,也只能有1个协调器,负责各个节点16位地址分配(自动分配)。
理论上可以连上65536个节点,可以实行多方组网。
3 详细设计
3.1 温度采集模块
温度采集模块的核心即是温度传感器DS18B20,其接线方法和引脚排列已在上文详述。
因此可以设计出图5所示温度采集模块电路图。
图5 温度采集模块
本次设计所采用的温度传感器为Dallas半导体公司的数字化温度传感器,它是世界上第一片支持“一线总线”接口的温度传感器。
“一线器件”体积更小、适用电压更宽、更经济。
并且分辨率设定,及用户设定的报警温度存储在EEPROM中,掉电后依然保存。
DSl8B20数字温度计提供9位(二进制)温度读数,指示器件的温度信息经过单线接口送入DSl8B20或从DSl8B20送出,因此从主机CPU到DSl8B20仅需一条线,当DS18B20接收到温度转换命令后,开始启动转换。
转换完成后的温度值就以16位带符号扩展的二进制补码形式存储在高速暂存存储器的第1、2字节。
单片机可以通过单线接口读出该数据,读数据时低位在先,高位在后,数据格式以0.0625℃/LSB形式表示。
当符号位S=0时,表示测得的温度值为正值,可以直接将二进制位转换为十进制;
当符号位S=1时,表示测得的温度值为负值,要先将补码变成原码,再计算十进制数值。
3.2 单片机控制系统
单片机控制系统的电路图如图6所示,这样便实现了对DS18B20的信息采集、反馈以及对LCD的控制。
图6 单片机控制模块
3.3 温度和时间显示模块
温度显示和时间显示都主要是通过1602型LCD实现,1602型LCD采用标准的16脚接口,其中:
第1脚:VSS为电源地
第2脚:VDD接5V电源正极
第3脚:V0为液晶显示器对比度调整端,接正电源时对比度最弱,接地电源时对比度最高(对比度过高时会产生“鬼影”,使用时可以通过一个10K的电位器调整对比度)。
第4脚:RS为寄存器选择,高电平1时选择数据寄存器、低电平0时选择指令寄存器。
第5脚:RW为读写信号线,高电平(1)时进行读操作,低电平(0)时进行写操作。
第6脚:E(或EN)端为使能(enable)端。
第7~14脚:D0~D7为8位双向数据端。
第15~16脚:空脚或背灯电源。
15脚背光正极,16脚背光负极。
显示电路是使用的LCD1602液晶显示,这种显示最大的优点就是使用字符型显示,可以显示两行,第一行显示日期与当前时间,第二行显示当前温度,当DS18B20出现显示错误时第二行温度不显示会出现错误提示,此款液晶功耗低,操作方便,显示相当清晰。
图7 显示模块电路图
3.4 软件设计
本章从设计思路、软件系统框图出发,先介绍整体的思路后,再逐一分析各模块程序算法的实现,最终编写出满足任务需求的程序。
3.4.1 DS18B20的温度采集程序
DS18B20器件要求采用严格的通信协议,以保证数据的完整性。
该协议定义了几种信号类型:复位脉冲,应答脉冲时隙;写0,写1时隙;读0,读1时隙。
与DS18B20的通信,是通过操作时隙完成单总线上的数据传输。
发送所有的命令和数据时,都是字节的低位在前,高位在后。
该模块的系统流程
图8 温度采集模块的系统流程图
DS18B201.2.3.4.延时7505.6.延时等待所返回的低电平“0”7.若CPU 的高电平算起(第8.
3.5系统主程序
首先要根据系统的总体功能和键盘设置选择一种最合适的监控程序结构,然后根据实时性的要求,合理地安排监控软件和各执行模块之间地调度关系。
采用C语言编写代码, 鉴于篇幅限制及DS18B20 的应用已经规范和成熟, 本文仅就主程序流程图和显示子程序流程图及其代码进行说明。
主程序流程图主程序通过调用温度采集子程序完成温度数据采集, 然后调用温度转换子程序转换读取温度数据,调用显示子程序进行温度显示和判断温度数据。
下面给出流程图
4 设计结果及分析
4.1 测试环境及工具
测试温度:20-50摄氏度。
(模拟不同温度值环境)
测试仪器及软件:数字万用表,标准温度计20-100摄氏度。
4.2 测试方法和测试结果
使电路运行,观察系统硬件检测是否正常。
系统自带测试表格数据,观察显示数据是否相符合即可。
采用温度传感器和温度计同时测量水温变化情况,目测显示电路是否正常。
并记录
由此可知该数字温度计的误差在1%左右。
5 总结和心得
经过一个星期的设计和制作,本人制作的多功能温度计也已完成,挺有收获的。
之前虽然运用过52单片机,但多模块功能混合实现还是第一次,本人首先设计了硬件电路,最后写程序实现了软件的设计。
在调试过程中也发现和解决了好些问题。
经过此次课程设计,我真正体会到要理论联系实际,把我们所学的理论知识用到实际当中,通过多动手去提高自己的技能,光靠理论不动手是提高不了的。
还有,程序一定要多看多模仿着写才有提高。
总之,此次课程设计不仅巩固了单片机方面的理论知识,同时也提高的自己的动手能力、分析问题和解决问题的能力。
参考文献
[1]张琳娜,刘武发.传感检测技术及应用.中国计量出版社,1999
[2]马忠梅籍顺心张凯马岩. 单片机的C语言应用程序设计-修订版.北京航空航天大学出版社,1998.10
[3]胡汉才.单片机原理及接口技术.清华大学出版社,1996
[4]阎石.数字电子技术基础.北京航空航天大学出版社,2006.
[5]黄河.基于DS18B20的单总线数字温度计.国防工业出版社,2002
[6] 彭泓. 汪玉凤. 粮仓温湿度智能控制系统[J]. 中国科技信息 , 2006
[7]童诗白,华程英.模拟电子技术基础(第四版)[M].北京:高等教育出版社,2009.
附录一系统总电路图
图附一系统总电路图
附录二实验结果测试图
1.时钟显示
2.温度显示
3.温度通过无线模块发送到电脑
附录三系统源代码
1主函数部分
#include<reg52.h>
#include "stdio.h"
#include "ds1302.h"
#include "18b20.h"
#include "delay.h"
#include "1602.h"
#define overtemp 50
sbit P20=P2^0;//定义锁存使能端口段锁存
sbit P21=P2^1;// 位锁存
sbit P35 = P3^5;//这是为了关闭开发板上的点阵实际应用去掉
sbit S17=P0^4; //独立按键
sbit S18=P0^5;
sbit S19=P0^6;
sbit S20=P0^7;
sbit feng=P2^0;
bit ReadTimeFlag;//定义读时间标志
bit SetFlag; //更新时间标志位
unsigned char time_buf2[16];
unsigned int ReadTemperature(void);
unsigned char KeyScan(void);
void Init_Timer0(void);//定时器初始化
void UART_Init(void);
/*------------------------------------------------
主函数
------------------------------------------------*/
void main (void)
{
unsigned char i,a=1,num,b=0,c=0;
int temp1;
unsigned char temp[16];//定义显示区域临时存储数组
float temperature;
char displaytemp[16];//定义显示区域临时存储数组
CD_Init(); //初始化液晶
DelayMs(20); //延时有助于稳定
LCD_Clear(); //清屏
Init_Timer0(); //定时器0初始化
Ds1302_Init(); //ds1302初始化
UART_Init(); //串口初始化
Ds1302_Read_Time(); //首次读取时间
if((time_buf1[2]+time_buf1[7])==0) //如果所有参数都为0,写入一个初始值Ds1302_Write_Time();
while (1) //主循环
{
num=KeyScan();
switch(num)
{
case 1:a++;if(a==3)a=1;
break; //选择显示
case 2:b++;if(b==7)b=0;
break;//b为1,2,3,4,5,6,时分别对分时日周月年加调
case 3:c++;if(c==7)c=0;
break;//b为1,2,3,4,5,6,时分别对分时日周月年
//case 4:
// break; //分减1
default:break;
}
if(num==4)
{
if(c==0)
{
switch(b)
{
case 2:time_buf1[4]++;if(time_buf1[4]==24)time_buf1[4]=0;
Ds1302_Write_Time();break; //正常时间小时加1 case 1:time_buf1[5]++;if(time_buf1[5]==60)time_buf1[5]=0;
Ds1302_Write_Time();break;//分加1
case 3:time_buf1[3]++;if(time_buf1[3]==32)time_buf1[3]=1;
Ds1302_Write_Time();break; //日加1
case 4:time_buf1[7]++;if(time_buf1[7]==8)time_buf1[7]=1;
Ds1302_Write_Time();break; //周加1
case 5:time_buf1[2]++;if(time_buf1[2]==13)time_buf1[2]=1;
Ds1302_Write_Time();break; //月加
case 6:time_buf1[1]++;if(time_buf1[1]==100)time_buf1[1]=12;
Ds1302_Write_Time();break; //年加
default:break;
}
}
if(b==0)
{
switch(c)
{
case 2:time_buf1[4]--;if(time_buf1[4]==255)time_buf1[4]=23;
Ds1302_Write_Time();break; // 小时减1
case 1:time_buf1[5]--;if(time_buf1[5]==255)time_buf1[5]=59;
Ds1302_Write_Time();break;//分减1
case 3:time_buf1[3]--;if(time_buf1[3]==255)time_buf1[3]=31;
Ds1302_Write_Time();break; //日减1
case 4:time_buf1[7]--;if(time_buf1[7]==255)time_buf1[7]=7;
Ds1302_Write_Time();break; //zhou
case 5:time_buf1[2]--;if(time_buf1[2]==255)time_buf1[2]=12;
Ds1302_Write_Time();break; //yue jian 1
case 6:time_buf1[1]--;
Ds1302_Write_Time();break; //nian jian
default:break;
}
}
}
if(SetFlag) //如果接收到串口信息则更新时钟
{
for(i=0;i<8;i++)
{
time_buf1[i]=time_buf2[2*i]*10+time_buf2[2*i+1];//数据整合,如2个数1和5整合成15
}
Ds1302_Write_Time();//接收更新的时间然后写入ds1302
SetFlag=0; //时钟信息更新后标志位清零
}
if(ReadTimeFlag==1) //定时读取ds1302 定时时间到则标志位置1,处理过时间参数标志位清零{
ReadTimeFlag=0; //标志位清零
if(a==1)
{
LCD_Clear(); //清屏
LCD_Write_Char(13,1,0x01);//写入温度右上角点
LCD_Write_Char(14,1,'C'); //写入字符C
// ReadTempFlag=0;
temp1=ReadTemperature()
}
if (a==2)
{
LCD_Clear(); //清屏
Ds1302_Read_Time();//读取时间参数
if((int)time_buf1[5]==0)
feng=0;
else
feng=1;
sprintf(temp,"DATE %02d-%02d-%02d %d",(int)time_buf1[1],(int)time_buf1[2],(int)time_buf1[3],(int)tim e_buf1[7]);//年月日周
LCD_Write_String(0,0,temp);//显示第一行
sprintf(temp,"TIME %02d:%02d:%02d",(int)time_buf1[4],(int)time_buf1[5],(int)time_buf1[6]);//时分秒LCD_Write_String(0,1,temp);//显示第二行
}
}
}
}
2.ds1302驱动部分
#include "ds1302.h"
unsigned char time_buf1[8] = {20,12,12,10,16,55,00,6};//空年月日时分秒周unsigned char time_buf[8] ; //空年月日时分秒周/*------------------------------------------------
向DS1302写入一字节数据
------------------------------------------------*/
void Ds1302_Write_Byte(unsigned char addr, unsigned char d)
{
unsigned char i;
RST_SET;
//写入目标地址:addr
addr = addr & 0xFE; //最低位置零
for (i = 0; i < 8; i ++)
{
if (addr & 0x01)
{
IO_SET;
}
else
{
IO_CLR;
}
SCK_SET;
SCK_CLR;
addr = addr >> 1;
}
//写入数据:d
for (i = 0; i < 8; i ++)
{
if (d & 0x01)
{
IO_SET;
}
else
{
IO_CLR;
}
SCK_SET;
SCK_CLR;
d = d >> 1;
}
RST_CLR; //停止DS1302总线}
/*------------------------------------------------
从DS1302读出一字节数据
------------------------------------------------*/
unsigned char Ds1302_Read_Byte(unsigned char addr) {
unsigned char i;
unsigned char temp;
RST_SET;
//写入目标地址:addr
addr = addr | 0x01;//最低位置高
for (i = 0; i < 8; i ++)
{
if (addr & 0x01)
{
IO_SET;
}
else
{
IO_CLR;
}
SCK_SET;
SCK_CLR;
addr = addr >> 1;
}
//输出数据:temp
for (i = 0; i < 8; i ++)
{
temp = temp >> 1;
if (IO_R)
{
temp |= 0x80;
}
else
{
temp &= 0x7F;
}
SCK_SET;
SCK_CLR;
}
RST_CLR; //停止DS1302总线
return temp;
}
/*------------------------------------------------
向DS1302写入时钟数据
------------------------------------------------*/
void Ds1302_Write_Time(void)
{
unsigned char i,tmp;
for(i=0;i<8;i++)
{ //BCD处理
tmp=time_buf1[i]/10;
time_buf[i]=time_buf1[i]%10;
time_buf[i]=time_buf[i]+tmp*16;
}
Ds1302_Write_Byte(ds1302_control_add,0x00); //关闭写保护
Ds1302_Write_Byte(ds1302_sec_add,0x80); //暂停
//Ds1302_Write_Byte(ds1302_charger_add,0xa9); //涓流充电Ds1302_Write_Byte(ds1302_year_add,time_buf[1]); //年
Ds1302_Write_Byte(ds1302_month_add,time_buf[2]); //月
Ds1302_Write_Byte(ds1302_date_add,time_buf[3]); //日
Ds1302_Write_Byte(ds1302_day_add,time_buf[7]); //周
Ds1302_Write_Byte(ds1302_hr_add,time_buf[4]); //时
Ds1302_Write_Byte(ds1302_min_add,time_buf[5]); //分
Ds1302_Write_Byte(ds1302_sec_add,time_buf[6]); //秒
Ds1302_Write_Byte(ds1302_day_add,time_buf[7]); //周
Ds1302_Write_Byte(ds1302_control_add,0x80); //打开写保护}
/*------------------------------------------------
从DS1302读出时钟数据
------------------------------------------------*/
void Ds1302_Read_Time(void)
{
unsigned char i,tmp;
time_buf[1]=Ds1302_Read_Byte(ds1302_year_add); //年
time_buf[2]=Ds1302_Read_Byte(ds1302_month_add); //月
time_buf[3]=Ds1302_Read_Byte(ds1302_date_add); //日
time_buf[4]=Ds1302_Read_Byte(ds1302_hr_add); //时
time_buf[5]=Ds1302_Read_Byte(ds1302_min_add); //分
time_buf[6]=(Ds1302_Read_Byte(ds1302_sec_add))&0x7F;//秒
time_buf[7]=Ds1302_Read_Byte(ds1302_day_add); //周
for(i=0;i<8;i++)
{ //BCD处理
tmp=time_buf[i]/16;
time_buf1[i]=time_buf[i]%16;
time_buf1[i]=time_buf1[i]+tmp*10;
}
/*------------------------------------------------
DS1302初始化
------------------------------------------------*/
void Ds1302_Init(void)
{
RST_CLR; //RST脚置低
SCK_CLR; //SCK脚置低
Ds1302_Write_Byte(ds1302_sec_add,0x00);
}
3.1602驱动部分
#include "1602.h"
#include "delay.h"
sbit RS = P2^3; //定义端口
sbit RW = P2^2;
sbit EN = P2^1;
#define RS_CLR RS=0
#define RS_SET RS=1
#define RW_CLR RW=0
#define RW_SET RW=1
#define EN_CLR EN=0
#define EN_SET EN=1
#define DataPort P1
/*------------------------------------------------
判忙函数
------------------------------------------------*/
bit LCD_Check_Busy(void)
{
DataPort= 0xFF;
RS_CLR;
RW_SET;
EN_CLR;
_nop_();
EN_SET;
return (bit)(DataPort & 0x80);
}
/*------------------------------------------------
写入命令函数
------------------------------------------------*/
void LCD_Write_Com(unsigned char com)
{
while(LCD_Check_Busy()); //忙则等待
RW_CLR;
EN_SET;
DataPort= com;
_nop_();
EN_CLR;
}
/*------------------------------------------------
写入数据函数
------------------------------------------------*/
void LCD_Write_Data(unsigned char Data)
{
while(LCD_Check_Busy()); //忙则等待
RS_SET;
RW_CLR;
EN_SET;
DataPort= Data;
_nop_();
EN_CLR;
}
/*------------------------------------------------
清屏函数
------------------------------------------------*/
void LCD_Clear(void)
{
LCD_Write_Com(0x01);
DelayMs(5);
}
/*------------------------------------------------
写入字符串函数
------------------------------------------------*/
void LCD_Write_String(unsigned char x,unsigned char y,unsigned char *s) {
if (y == 0)
{
LCD_Write_Com(0x80 + x); //表示第一行
}
else
{
LCD_Write_Com(0xC0 + x); //表示第二行
}
while (*s)
{
LCD_Write_Data( *s);
}
}
/*------------------------------------------------
写入字符函数
------------------------------------------------*/
void LCD_Write_Char(unsigned char x,unsigned char y,unsigned char Data) {
if (y == 0)
{
LCD_Write_Com(0x80 + x);
}
else
{
LCD_Write_Com(0xC0 + x);
}
LCD_Write_Data( Data);
}
/*------------------------------------------------
初始化函数
------------------------------------------------*/
void LCD_Init(void)
{
LCD_Write_Com(0x38); /*显示模式设置*/
DelayMs(5);
LCD_Write_Com(0x38);
DelayMs(5);
LCD_Write_Com(0x38);
DelayMs(5);
LCD_Write_Com(0x38);
LCD_Write_Com(0x08); /*显示关闭*/
LCD_Write_Com(0x01); /*显示清屏*/
LCD_Write_Com(0x06); /*显示光标移动设置*/
DelayMs(5);
LCD_Write_Com(0x0C); /*显示开及光标设置*/
}
4.ds18b20驱动部分
#include "1602.h"
#include "delay.h"
sbit RS = P2^3; //定义端口
sbit RW = P2^2;
sbit EN = P2^1;
#define RS_CLR RS=0
#define RS_SET RS=1
#define RW_CLR RW=0
#define RW_SET RW=1
#define EN_CLR EN=0
#define EN_SET EN=1
#define DataPort P1
/*------------------------------------------------
判忙函数
------------------------------------------------*/
bit LCD_Check_Busy(void)
{
DataPort= 0xFF;
RS_CLR;
RW_SET;
EN_CLR;
_nop_();
EN_SET;
return (bit)(DataPort & 0x80);
}
/*------------------------------------------------
写入命令函数
------------------------------------------------*/
void LCD_Write_Com(unsigned char com) {
while(LCD_Check_Busy()); //忙则等待
RS_CLR;
RW_CLR;
EN_SET;
DataPort= com;
_nop_();
EN_CLR;
}
/*------------------------------------------------
写入数据函数
------------------------------------------------*/
void LCD_Write_Data(unsigned char Data) {
while(LCD_Check_Busy()); //忙则等待
RS_SET;
RW_CLR;
EN_SET;
DataPort= Data;
_nop_();
EN_CLR;
}
/*------------------------------------------------
清屏函数
------------------------------------------------*/
void LCD_Clear(void)
{
LCD_Write_Com(0x01);
DelayMs(5);
}
/*------------------------------------------------
写入字符串函数
------------------------------------------------*/
void LCD_Write_String(unsigned char x,unsigned char y,unsigned char *s) {
if (y == 0)
{
LCD_Write_Com(0x80 + x); //表示第一行
}
else
{
LCD_Write_Com(0xC0 + x); //表示第二行
}
while (*s)
{
LCD_Write_Data( *s);
s ++;
}
}
/*------------------------------------------------
写入字符函数
------------------------------------------------*/
void LCD_Write_Char(unsigned char x,unsigned char y,unsigned char Data) {
if (y == 0)
{
LCD_Write_Com(0x80 + x);
}
else
{
LCD_Write_Com(0xC0 + x);
}
LCD_Write_Data( Data);
}
/*------------------------------------------------
初始化函数
------------------------------------------------*/
void LCD_Init(void)
{
LCD_Write_Com(0x38); /*显示模式设置*/
DelayMs(5);
LCD_Write_Com(0x38);
DelayMs(5);
LCD_Write_Com(0x38);
DelayMs(5);
LCD_Write_Com(0x38);
LCD_Write_Com(0x08); /*显示关闭*/
LCD_Write_Com(0x01); /*显示清屏*/
LCD_Write_Com(0x06); /*显示光标移动设置*/ DelayMs(5);
LCD_Write_Com(0x0C); /*显示开及光标设置*/ }。