单片机89C52 ,液晶LCD12864,ADC0809,温度传感器DS18B20
单片机课程设计论文
单片机89C52 ,液晶LCD12864,ADC0809,温度传感器DS18B20
基于18B20温度检测系统设计
一、引言
温度是工农业生产中最常见的参数之一,与产品的质量、生产效率、安全
生产等密切相关,因此在生产过程中需对温度进行检测和监控。然而,传统的测温系统多以二极管、Pt100 及AD590 作为温度检测单元, 通过信号处理电路将待测温度的变化转换为电信号的变化,从而实现温度的测量。伴随着微电子技术的发展,利用单线总线实现信号双向传输的数字温度传感器的出现,改变了传统测量温度的方法。
该设计系统主要由STC89C52 单片机、数字温度传感器DS18B20 及液晶显示器12864三大部分组成。在此系统中,DS18B20 是美国生产的低功耗、高性能、抗干扰能力强的单总线数字温度传感器芯片,具有可编程的温度转换分辨率,可根据应用需要在9 ~12bit 之间选取,且测温范围为:-55~125℃。作为温度采集单元的DS18B20,采用外部电源供电方式,与STC89C2单片机进行双向通信,无需A/D ,就可以直接将被测温度转换为数字信号供单片机进行处理, 最终将换算得到的测量温度值显示在液晶显示器上。
二、实验器材
电源+5V、万用表、电烙铁
三、电路设计分析
(一)、硬件电路
单片机89C52 ,液晶LCD12864,ADC0809,温度传感器DS18B20
1、数字温度传感器18b20与单片机硬件连线
4039383736353433323130292827262524232221
VDD接外部电源,
DQ(
I/O)口与单片机P1.1串口连接,同时接4.7K上拉电阻接电源,GND接地。
下图为所用DS18B20的封装,它是独特的单线接口方式,在与89c52连接时仅需要一条口线即可实现双向通讯,无需外部元件 。
电压范围为3.0 V至5.5 V ,无需备用电源, 测量温度范围为-55℃至+125 ℃。温度传感器可编程的分辨率为9~12位, 温度转换为12位数字格式,最大值为750毫秒 。DS18B20内部结构主要由四部分组成:64位光刻ROM,温度报警触发器,温度传感器以及高速缓存器。此外,DS18B20内部还包括寄生电源、电源检测、存储控制逻辑、8位循环冗余码生成器(CRC)等部分。内部结构为:
单片机89C52 ,液晶LCD12864,ADC0809,温度传感器DS18B20
若是要使采集的数据分辨率越高,则所需要的温度数据转换时间越长。因此,在实际应用中要将分辨率和转换时间权衡考虑。
DS18B20的测温原理如下图所示:
2、LCD12864与单片机的硬件连线
RXX
LCD16824液晶1脚VSS接地,2脚VDD接电源,3脚V0接10K滑动变阻器调节对比度,4脚RS接单片机P1.4口,5脚RW脚接单片机P1.3口,6脚EN接单片机P1.2口,7~14脚DB口接单片机P2口,15脚PSB接高电平,默认为并行串口方式,16~18脚NC\RST\VOUT悬空默认低电平,19脚A默认高电平,接高电
单片机89C52 ,液晶LCD12864,ADC0809,温度传感器DS18B20
平,液晶背景光为亮,20脚K接地。
带中文字库的12864是一种具有4位/8位并行、2线或3线串行多种接口方式,内部含有国标一级、二级简体中文字库的点阵图形液晶显示模块;其显示分辨率为128×64, 内置8192个16*16点汉字,和128个16*8点ASCII字符集.利用该模块灵活的接口方式和简单、方便的操作指令,可构成全中文人机交互图形界面。它每屏最多可实现4行*8=32个中文字符或64个ASCII码字符的显示,内部提供128×2字节的字符显示RAM缓冲区(DDRAM),字符显示是通过将字符显示编码写入该字符显示RAM实现的。根据写入内容的不同,可分别在液晶屏上显示CGROM(中文字库)、HCGROM(ASCII码字库)及CGRAM(自定义字形)的内容。同时它可以先设垂直地址再设水平地址方式显示图形,功能比1602更好。
3、单片机复位和振荡电路连线
4039383736353433323130292827262524232221
A、复位是单片机的初始化操作,其主要功能是把PC初始化为0000H,使单片机从0000H单元开始执行程序。除了进入系统的正常初始化之外,当由于程序运行出错或操作错误使系统处于死锁状态时,为摆脱困境,也需按复位键重新启动。除PC之外,复位操作还对其他一些寄存器有影响,它们的复位状态如表一所示。
表一 一些寄存器的复位状态
寄存器
复位状态
寄存器
复位状态
单片机89C52 ,液晶LCD12864,ADC0809,温度传感器DS18B20
PC ACC PSW SP DPTR P0-P3 IP IE TMOD
0000H 00H 00H 07H 0000H FFH XX000000B 0X000000B
00H
TCON TL0 TH0 TL1 TH1 SCON SBUF PCON
00H 00H 00H 00H 00H 00H 不定 0XXX0000B
RST引脚是复位信号的输入端。复位信号是高电平有效,其有效时间应持续24个振荡周期(即二个机器周期)以上。
B、时钟电路相当于微机处理器的脉搏,单片机内部有一个高增益反相放大器,反相放大端输入为XTAL1,输出为XTAL2,在XTAL1和XTAL2两端跨接石英晶体及微调电容就构成了振荡器。我们用了11.0592M的晶振,则振荡周期为T0=1/11.0592us,时钟周期为2T0,机器周期为12T0. (二)、 软件设计
1、18b20驱动时序 #include<reg52.h> #include <intrins.h>
#define uchar unsigned char #define uint unsigned int sbit dq=P1^1; uint t,s;
uchar flag,count;
void delayus(uint z) //ds18b20内部延时 {
uchar i;
for(i=0;i<z;i++); }
////ds18b20复位,及存在检测// uchar ds18b20_reset() {
uchar k;
dq=1; //释放总线
单片机89C52 ,液晶LCD12864,ADC0809,温度传感器DS18B20
delayus(5); //延时5us dq=0; //拉低总线 delayus(30);
dq=1; //释放总线 delayus(3);
k=dq; // 对数据较采样 delayus(25);
return k; //根据K值判断da18b20是否损坏 }
////写数据到ds18b20//
void ds18b20_writedate(uchar date) {
uchar num;
for(num=0;num<8;num++) {
dq=0; // 拉低总线,产生写信号 delayus(4);
dq=date&0x01; //发送一位数据 date>>=1; // 准备下一位数据传送 delayus(4); //延时4us
dq=1; // 释放总线,等待总线恢复 }
delayus(4); }
///从ds18b20中读数据/// uchar ds18b20_readdate() {
uchar value,i;
for(i=0;i<8;i++)//读8位 {
dq=0; ///拉低总线,产生读信号 delayus(4);
value>>=1; // 准备读温度 delayus(4);
dq=1; //释放总线,准备读数据 if(dq) // 读数据 value|=0x80;
delayus(6); // 延时 }
return value; ///返回独到的数据 }
///ds18b20初始化以及数据处理// uint read_temp()
单片机89C52 ,液晶LCD12864,ADC0809,温度传感器DS18B20
{
uint g,d,m; uint c; m=1;
m=ds18b20_reset();//复位检测ds18b20正常工作,m=0 while(m); //等待复位完成
ds18b20_writedate(0xcc);//跳过rom
ds18b20_writedate(0x44);//启动温度测量,写暂存器 delayus(100);
m=ds18b20_reset();
while(m); //等待转化完成
ds18b20_writedate(0xcc);//跳过rom
ds18b20_writedate(0xbe);//读ds18b20温度暂存器命令 d=ds18b20_readdate();//读低8位数据 g=ds18b20_readdate(); //读高3位数据 g<<=4; //数据转换处理程序
g=g+(d>>4); //整数部分 g=g*100;
d=(d&0x0f)*0.0625*100; c=g+d;
return c; }
///温度转换显示子程序// void write_temp(uint temp) {
12864_writecom(0x88+3); //显示地址指针
12864_writedat(0x30+temp%10000/1000);//写数据最高位(十位) 12864_writedat(0x30+temp%1000/100); //写个位 12864_writedat('.'); //写小数点 12864_writedat(0x30+temp%100/10); //小数位 12864_writedat(0x30+temp%10); }
///中断初始化程序// void init() {
count=0;
TMOD=0x21; TH1=0xfd; TL1=0xfd;
TH0=(65536-50000)/256; //设定时器0初值 TL0=(65536-50000)%256;
单片机89C52 ,液晶LCD12864,ADC0809,温度传感器DS18B20
SM0=0; SM1=1; TR1=1; REN=1; TR0=1; ET0=1; ES=1;
EA=1; 开中断 }
//开定时器0中断1,在液晶上显示温度// void timer0() interrupt 1 {
TH0=(65536-50000)/256; TL0=(65536-50000)%256; count++;
if(count>=18) {
t=read_temp(); write_temp(t); count=0; } }
void ses() interrupt 4 {
TI=0; ET0=0;
if(flag==4) flag=0; switch(flag) {
case 0: SBUF=50; delay(5); break;
case 1: SBUF=t/100;delay(5); break; case 2: SBUF=t%100;delay(5); break; case 3: SBUF=40; delay(5); break; default: flag=0; }
flag++; delay(50); ET0=1; }
2、LCD12864的显示程序
#include<reg52.h> #include <intrins.h>
单片机89C52 ,液晶LCD12864,ADC0809,温度传感器DS18B20
#define uchar unsigned char #define uint unsigned int sbit lcd_en=P1^2; sbit lcd_rs=P1^4; sbit lcd_rw=P1^3; ///sbit lcd_psb=P3^6; void init_12864(void);
void 12864_writecom(uchar com); void 12864_writedat(uchar dat);
void write_12864com(uchar com)//写指令函数 {
lcd_rs=0; lcd_rw=0; lcd_en=0;
P2=com; //P2口传送数据 delay(5); lcd_en=1; delay(5); lcd_en=0; }
void write_12864dat(uchar date)//写数据函数 {
lcd_rs=1; lcd_rw=0; lcd_en=0; P2=date; delay(5); lcd_en=1; delay(5); lcd_en=0; }
void init_12864()//初始化液晶 {
//lcd_psb=1;
write_12864com(0x30); delay(5);
write_12864com(0x0c); delay(5);
write_12864com(0x01); delay(5); }
void write_temp(uint temp)//显示温度 {
单片机89C52 ,液晶LCD12864,ADC0809,温度传感器DS18B20
write_12864com(0x88+4);
write_12864dat(0x30+temp%10000/1000); write_12864dat(0x30+temp%1000/100); write_12864dat('.');
write_12864dat(0x30+temp%100/10); write_12864dat(0x30+temp%10); }
void main() //主函数 { uchar i; SBUF=0;
init_12864();///初始化液晶
12864_writecom(0x0c);//关显示显示游标地址加1 while(1)
{ 12864_writecom(0x80); //写数据入口地址,液晶第一行显示 for(i=0;i<16;i++) {
uchar table1[]="单片机课程设计 "; 12864_writedat(table1[i]); }
12864_writecom(0x90); //液晶第二行入口地址 for(i=0;i<16;i++) {
uchar table1[]="徐新丽 张燕"; 12864_writedat(table1[i]); }
12864_writecom(0x88); //液晶第三行入口地址 for(i=0;i<16;i++) {
uchar table1[]="温度: C"; 12864_writedat(table1[i]); }
init(); //中断初始化 }
四、 总结
1、复位开关焊接前需要测试一下使用的两端是否有效,否则会导致电源与地短路,烧坏电路。焊接时,因为没有仔细检查,后上电前用万用表查出焊错了,还好没有导致严重后果,改正之后可正常使用。
2、焊接前需要对照ds18b20的三个引脚标号,电源与地不能接反。检查电路时查出接反,改正之后能正常工作。
单片机89C52 ,液晶LCD12864,ADC0809,温度传感器DS18B20
3、编程序时需要查看DS18B20以及LCD12864的数据手册,对照手册上的内容进行编程。初始化以及写数据读数据的程序一般为固定模式,对照数据手册以及系统功能,初始化系统;显示数据时要先对读进的数据进行数据处理,否则不能直接得到温度值。
4、在LCD12864上显示中文字时,每个汉字占两位,所以在设置中文时要注意空格的位数,否则会出现乱码,不显示汉字。调试程序时就遇到了这个问题;编程前最好在网上搜查这两个器件的一些注意点,少走歪路。 5、调试成功后,在液晶上显示“单片机课程设计” 成员姓名“..........” 当前温度显示 “温度: **** ” 实物如下图所示。
正面:
反面:
单片机89C52 ,液晶LCD12864,ADC0809,温度传感器DS18B20
五、致谢
本设计历时两星期,通过前期的收集、查阅资料,了解DS18B20的一些特性以及基本用法,确定单片机型号STC89C52;设计电路,用PROTEL画电路原理图,购买器件,同时编写程序并调试;焊接电路,查看电路;最后用单片机驱动显示并调试。这里感谢....同学,显示出错时,及时帮助我们找出程序错误并改正,使液晶能够按照我们的想法与要求显示。同时感谢小组成员张燕同学,与她共同完成这些工作,相互学习,收获很多。
单片机89C52 ,液晶LCD12864,ADC0809,温度传感器DS18B20
附件1、
电路图:
单片机89C52 ,液晶LCD12864,ADC0809,温度传感器DS18B20
附件2:
#include<reg52.h> #include <intrins.h>
#define uchar unsigned char #define uint unsigned int
sbit lcd_en=P1^2; sbit lcd_rs=P1^4; sbit lcd_rw=P1^3; ///sbit lcd_psb=P3^6;
sbit dq=P1^1; uint t,s;
//void init(); ///////////////// uchar flag,count;
void delayus(uint z); void delay(uint z); void init_12864(void);
void write_12864com(uchar com); void write_12864dat(uchar dat);
void write_12864com(uchar com)//写指令函数 {
lcd_rs=0; lcd_rw=0; lcd_en=0; P2=com; delay(5); lcd_en=1; delay(5); lcd_en=0; }
void write_12864dat(uchar date)//写数据函数 {
lcd_rs=1;
单片机89C52 ,液晶LCD12864,ADC0809,温度传感器DS18B20
lcd_rw=0; lcd_en=0; P2=date; delay(5); lcd_en=1; delay(5); lcd_en=0; }
void init_12864()//初始化液晶 {
//lcd_psb=1;
write_12864com(0x30); delay(5);
write_12864com(0x0c); delay(5);
write_12864com(0x01); delay(5); }
void write_temp(uint temp) {
write_12864com(0x88+4);
write_12864dat(0x30+temp%10000/1000); write_12864dat(0x30+temp%1000/100); write_12864dat('.');
write_12864dat(0x30+temp%100/10); write_12864dat(0x30+temp%10); }
void delay(uint z) {
uint x,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--); }
void delayus(uint z) {
uchar i;
for(i=0;i<z;i++); }
uchar clean_ds18b20() {
uchar k; dq=1;