AT89C51单片机的多点温度测量.docx
《AT89C51单片机的多点温度测量.docx》由会员分享,可在线阅读,更多相关《AT89C51单片机的多点温度测量.docx(27页珍藏版)》请在冰点文库上搜索。
![AT89C51单片机的多点温度测量.docx](https://file1.bingdoc.com/fileroot1/2023-4/30/3dc54826-cec0-41b1-9208-e6ec140587c0/3dc54826-cec0-41b1-9208-e6ec140587c01.gif)
AT89C51单片机的多点温度测量
单片机应用系统设计
课题:
AT89C51单片机的多点温度测量
姓名:
班级:
学号:
指导老师:
日期:
一、绪论
在现代工业控制中和智能化仪表中,对于温度的控制,恒温等有较高的要求,如对食品的管理,冰箱的恒温控制,而且现在越来越多的地方用到多点温度测量,比如冰箱的保鲜层和冷冻层是不同的温度这就需要多点的测量和显示可以让用户直观的看到温度值,并根据需要调节冰箱的温。
它还在其他领域有着广泛的应用,如:
消防电气的非破坏性温度检测,电力、电讯设备之过热故障预知检测,空调系统的温度检测。
。
。
。
。
。
温度检测系统应用十分广阔。
本设计采用DALLAS最新单线数字温度传感器DS18B20简介新的"一线器件"体积更小、适用电压更宽、更经济DALLAS半导体公司的数字化温度传感器DS18B20是世界上第一片支持"一线总线",测量温度范围为-55°C~+125°C,在-10~+85°C范围内,精度为±0.5°C
二、设计过程及工艺要求
1、基本功能
(1)检测两点温度
(2)两秒间隔循环显示温度
2、主要技术参数
测温范围:
-30℃到+99℃
测量精度:
0.0625℃
显示精度:
0.1℃
显示方法:
LCD循环显示
3、系统设计
系统使用AT89C51单片机对两个DS18B20进行数据采集,并通过1602LCD液晶显示器显示所采集的温度。
DS18B20以单总线协议工作,51单片机首先分别发送复位脉冲,使信号上所有的DS18B20芯片都被复位,程序先跳过ROM,启动DS18B20进行温度变换,再读取存储器的第一位和第二位读取温度,通过I/O口传到1602LCD显示。
123
图
(1)DS18B20引脚图
引脚定义如图
(1):
(1)GND为电源地;
(2)DQ为数字信号输入/输出端;
(3)Vcc为外接供电电源输入端(在寄生电源接线方式时接地)。
4、设计原理框图
最小AT89C51系统
图
(2)原理框图
三、硬件设计
本系统硬件部分由三个模块组成:
1、单片机最小系统:
12M晶振、复位电路、AT89C51单片机
2、2个DS18B20温度传感器
3、一个LCD显示屏(配合排阻)
DS18B20内部结构
(1)DS18B20的内部结构如下图所示。
图(3)DS18B20内部结构图
DS18B20有4个主要的数据部件:
①64位激光ROM。
64位激光ROM从高位到低位依次为8位CRC、48位序列号和8位家族代码(28H)组成。
②温度灵敏元件。
③非易失性温度报警触发器TH和TL。
可通过软件写入用户报警上下限值。
④配置寄存器。
配置寄存器为高速暂存存储器中的第五个字节。
DS18B20在0工作时按此寄存器中的分辨率将温度转换成相应精度的数值,其各位定义如图(4)所示。
TM
R1
R0
1
1
1
1
1
MSB
DS18B20配置寄存器结构图
LSB
图(4)
其中,TM:
测试模式标志位,出厂时被写入0,不能改变;R0、R1:
温度计分辨率设置位,其对应四种分辨率如下表所列,出厂时R0、R1置为缺省值:
R0=1,R1=1(即12位分辨率),用户可根据需要改写配置寄存器以获得合适的分辨率。
配置寄存器与分辨率关系表:
R0
R1
温度计分辨率/bit
最大转换时间/us
0
0
9
93.75
0
1
10
187.5
1
0
11
375
1
1
12
750
图(5)
(2)高速暂存存储器
高速暂存存储器由9个字节组成,其分配如下图所示。
当温度转换命令发布后,经转换所得的温度值以二字节补码形式存放在高速暂存存储器的第0和第1个字节。
单片机可通过单线接口读到该数据,读取时低位在前,高位在后,数据格式如图所示。
对应的温度计算:
当符号位S=0时,直接将二进制位转换为十进制;当S=1时,先将补码变为原码,再计算十进制值。
温度低位
温度高位
TH
TL
配置
保留
保留
保留
8位CRC
LSB
DS18B20存储器映像图
MSB
图(6)
温度值格式图DS18B20温度数据表:
23
22
21
20
2-1
2-2
2-3
2-4
MSB
LSB
S
S
S
S
S
26
25
24
图(7)
典型对应的温度值表:
温度/℃
二进制表示
十六进制表示
+125
+25.0625
+10.125
+0.5
0
-0.5
-10.125
-25.0625
-55
0000011111010000
0000000110010001
0000000010100010
0000000000001000
0000000000000000
1111111111111000
1111111101011110
1111111001101111
1111110010010000
07D0H
0191H
00A2H
0008H
0000H
FFF8H
FF5EH
FE6FH
FC90H
图(8)典型对应的温度值表
单片机最小系统:
图(9)单片机最小系统
LCD显示屏电路:
图(10)LCD显示屏电路
具体总体电路图如下:
图(11)总体硬件图
四、软件设计
1、主程序方案
主程序调用了4个子程序和一个欢迎开机画面的程序,4个子程序分别是液晶初始化、DS18B201的初始化、DS18B202的初始化、和液晶显示数据的程序。
(1)液晶初始化程序:
8位数据端口,2行显示,5*7点阵、开启显示,无光标、清屏、AC递增,画面不动。
(2)分别对两个DS18B20温度传感器初始化程序:
初始化,读写一个字节,
(3)液晶显示的子程序:
确定液晶字符的输入位置,将字符输出到液晶显示
(4)液晶显示温度程序:
先读DS18B20当前温度,将温度转化成液晶字符显示。
将各个功能程序以子程序的形式写好,当写主程序的时候,只需要调用子程序调用指令使得程序结构清晰,无论是修改还是维护都比较方便。
将功能程序段写成子程序的形式,除了方便调用之外,还有一个好处那就是以后写程序的时候如果要用到,就可以直接调用这个单元功能模块。
2、流程图
主程序流程图:
开始
图(11)主程序流程图
图(12)液晶初始化流程图
图(13)DS13B20的读取数据流程图
图(14)液晶显示流程图
五、调试仿真
开机画面:
图(15)开机画面
保持两秒后显示第一个温度:
图(16)显示第一个温度
保持两秒后显示第二个传感器测量的温度:
图(17)显示第二个温度
如此循环显示两个温度,仿真成功。
六、设计总结
AT89C51的时钟为12M,I/O口可达32个,较高的时钟频率和丰富的I/O,都为实现电路功能提供了非常有利的条件。
同时也AT89S51内含4KBFLASHROM,开发环境友好,易用,方便,加上Proteus仿真大大加快本系统设计开发。
在此次设计中学会了对Proteus的基本使用,对里面一些基本元件的英文,如电阻RES、电容CAP、晶振CRYSTAL等,学会了连线和运行。
在设计过程中也遇到一些问题,由于LCD是现实的字符型数据,数字不能直接送去显示,所有对于数字的显示首先要转换为字符格式,方法为:
数字+‘0’;对于温度传感器的小数处理也遇到一些问题,两个选的是12位,精度为0.0625,DS18B20的温度寄存器里低八位的低四位为小数部分,小数的值为0.0625*低八位的低四位,但是由于单片机的数据处理能力较差,不能处理小数的乘法运算,用上方法就显示错误,后来想到可以把小数先变成整数处理,令低八位的低四位为t,小数后的第一位=625*t/1000,然后将这个数字在小数点后显示即可。
其实该本设计还有很多的不足,本实验是用单片机的多个I/O口来驱动多路,DS18B20是一总线结构,每一个DS18B20在其ROM中都存有一个其唯一的48位序列号,在出厂前已写入片内RMO中,主机在进行操作程序前必须逐一接入18B20用读ROM(33H)命令将该18B20的序列号读出并登录.当主机需要对众多在线的DS18B20的某一个进行操作,首先要发出匹配ROM命令(55H),紧接着主机提供64位序列(包括该DS8B20的48位序列号),之后操作就是针对该DS18B20的.而所谓跳过ROM命令.即为:
之后的操作是对所有DS18B20的,所以可以在一根总线上挂多个DS18B20。
七、主要参考资料:
[1]林志琦.基于Proteus的单片机可视化软硬件仿真[M].北京:
北京航空航天大学出版社,2006.9
[2]周润景,张丽娜.基于PROTEUS的电路及单片机系统设计与仿真[M].北京:
北京航空航天大学出版社,2006.5
[3]张靖武,周灵彬.单片机系统的PROTEUS设计与仿真[M].北京:
电子工业出版社,2007.4
[4]周润景,张丽娜.PROTEUS入门实用教程[M].北京:
机械工业出版社,2007.9
[5]楼然苗,李光飞.51系列单片机设计实例[M].北京:
北京航空航天大学出版社,2003.3
[6]楼然苗,李光飞.单片机课程设计指导[M].北京:
北京航空航天大学出版社,2007.7
[7].贾东耀,汪仁煌.数字温度传感器在仓库温度检测系统的应用[J].传感器世界,2001
[8]DALLASDS18B20数据手册[Z].http:
//
八、附源程序代码
#include
#include
#include
#defineuintunsignedint
#defineucharunsignedchar
uchartemp_value;//温度值
ucharTempBuffer[7];
voidshow_time();//液晶显示程序
uchartemp_value1;//温度值
ucharTempBuffer1[7];
charxiaoshu=0;
charxiaoshu1=0;
voidshow_time1();
/***********1602液晶显示部分子程序****************/
chardone,count,temp,flag,up_flag,down_flag;
//PortDefinitions**********************************************************
sbitLcdRs=P2^0;
sbitLcdRw=P2^1;
sbitLcdEn=P2^2;
sfrDBPort=0x80;//P0=0x80,P1=0x90,P2=0xA0,P3=0xB0.数据端口
sbitDQ=P1^7;//温度传送数据IO口
sbitDQ1=P1^6;
//内部等待函数**************************************************************************
unsignedcharLCD_Wait(void)
{
LcdRs=0;
LcdRw=1;_nop_();
LcdEn=1;_nop_();
LcdEn=0;
returnDBPort;
}
//向LCD写入命令或数据************************************************************
#defineLCD_COMMAND0//Command
#defineLCD_DATA1//Data
#defineLCD_CLEAR_SCREEN0x01//清屏
#defineLCD_HOMING0x02//光标返回原点
voidLCD_Write(bitstyle,unsignedcharinput)
{
LcdEn=0;
LcdRs=style;
LcdRw=0;_nop_();
DBPort=input;_nop_();//注意顺序
LcdEn=1;_nop_();//注意顺序
LcdEn=0;_nop_();
LCD_Wait();
}
//设置显示模式************************************************************
#defineLCD_SHOW0x04//显示开
#defineLCD_HIDE0x00//显示关
#defineLCD_CURSOR0x02//显示光标
#defineLCD_NO_CURSOR0x00//无光标
#defineLCD_FLASH0x01//光标闪动
#defineLCD_NO_FLASH0x00//光标不闪动
voidLCD_SetDisplay(unsignedcharDisplayMode)
{
LCD_Write(LCD_COMMAND,0x08|DisplayMode);
}
//设置输入模式************************************************************
#defineLCD_AC_UP0x02
#defineLCD_AC_DOWN0x00//default
#defineLCD_MOVE0x01//画面可平移
#defineLCD_NO_MOVE0x00//default
voidLCD_SetInput(unsignedcharInputMode)
{
LCD_Write(LCD_COMMAND,0x04|InputMode);
}
//初始化LCD************************************************************
voidLCD_Initial()
{
LcdEn=0;
LCD_Write(LCD_COMMAND,0x38);//8位数据端口,2行显示,5*7点阵
LCD_Write(LCD_COMMAND,0x38);
LCD_SetDisplay(LCD_SHOW|LCD_NO_CURSOR);//开启显示,无光标
LCD_Write(LCD_COMMAND,LCD_CLEAR_SCREEN);//清屏
LCD_SetInput(LCD_AC_UP|LCD_NO_MOVE);//AC递增,画面不动
}
//液晶字符输入的位置************************
voidGotoXY(unsignedcharx,unsignedchary)
{
if(y==0)
LCD_Write(LCD_COMMAND,0x80|x);
if(y==1)
LCD_Write(LCD_COMMAND,0x80|(x-0x40));
}
//将字符输出到液晶显示
voidPrint(unsignedchar*str)
{
while(*str!
='\0')
{
LCD_Write(LCD_DATA,*str);
str++;
}
}
/***********ds18b20子程序*************************/
/***********ds18b20延迟子函数(晶振12MHz)*******/
voiddelay_18B20(unsignedinti)
{
while(i--);
}
/**********ds18b20初始化函数**********************/
voidInit_DS18B20(void)
{
unsignedcharx=0;
DQ=1;//DQ复位
delay_18B20(8);//稍做延时
DQ=0;//单片机将DQ拉低
delay_18B20(80);//精确延时大于480us
DQ=1;//拉高总线
delay_18B20(14);
x=DQ;//稍做延时后如果x=0则初始化成功x=1则初始化失败
delay_18B20(20);
}
/***********ds18b20读一个字节**************/
unsignedcharReadOneChar(void)
{
uchari=0;
uchardat=0;
for(i=8;i>0;i--)
{
DQ=0;//给脉冲信号
dat>>=1;
DQ=1;//给脉冲信号
if(DQ)
dat|=0x80;
delay_18B20(4);
}
return(dat);
}
/*************ds18b20写一个字节****************/
voidWriteOneChar(uchardat)
{
unsignedchari=0;
for(i=8;i>0;i--)
{
DQ=0;
DQ=dat&0x01;
delay_18B20(5);
DQ=1;
dat>>=1;
}
}
/**************读取ds18b20当前温度************/
voidReadTemp(void)
{
unsignedchara=0;
unsignedcharb=0;
chart;
longtt;
Init_DS18B20();
WriteOneChar(0xCC);//跳过读序号列号的操作
WriteOneChar(0x44);//启动温度转换
delay_18B20(100);//thismessageisweryimportant
Init_DS18B20();
WriteOneChar(0xCC);//跳过读序号列号的操作
WriteOneChar(0xBE);//读取温度寄存器等(共可读9个寄存器)前两个就是温度
delay_18B20(100);
a=ReadOneChar();//读取温度值低位
b=ReadOneChar();//读取温度值高位
temp_value=b<<4;
temp_value+=(a&0xf0)>>4;
t=a&0x0f;
tt=t*625;
xiaoshu=tt/1000;
}
voidtemp_to_str()//温度数据转换成液晶字符显示
{
TempBuffer[0]=temp_value/10+'0';//十位
TempBuffer[1]=temp_value%10+'0';//个位
TempBuffer[2]='.';
TempBuffer[3]=xiaoshu+'0';
TempBuffer[4]=0xdf;
TempBuffer[5]='C';
TempBuffer1[6]='\0';
}
voidDelay1ms(unsignedintcount)
{
unsignedinti,j;
for(i=0;ifor(j=0;j<120;j++);
}
voidshow_time()//液晶显示程序
{
ReadTemp();//开启温度采集程序
temp_to_str();
GotoXY(0,0);
Print("first");
GotoXY(0,1);//温度数据转换成液晶字符
Print("temp:
");
GotoXY(6,1);//液晶字符显示位置
Print(TempBuffer);//显示温度
Delay1ms(400);//扫描延时
}
/***********ds18b20子程序*************************/
/***********ds18b20延迟子函数(晶振12MHz)*******/
/**********ds18b20初始化函数**********************/
voidInit_DS18B201(void)
{
unsignedcharx=0;
DQ1=1;//DQ复位
delay_18B20(8);//稍做延时
DQ1=0;//单片机将DQ拉低
delay_18B20(80);//精确延时大于480us
DQ1=1;//拉高总线
delay_18B20(14);
x=DQ1;//稍做延时后如果x=0则初始化成功x=1则初始化失败
delay_18B20(20);
}
/***********ds18b20读一个字节**************/
unsignedcharReadOneChar1(void)
{
uchari=0;
uchardat=0;
for(i=8;i>0;i--)
{
DQ1=0;//给脉冲信号
dat>>=1;
DQ1=1;//给脉冲信号
if(DQ1)
dat|=0x80;
delay_18B20(4);
}
return(dat);
}
/*************ds18b201写一个字节****************/
voidWriteOneChar1(uchardat)
{
unsignedchari=0;
for(i=8;i>0;i--)
{
DQ1=0;
DQ1=dat&0x01;
delay_18B20(5);
DQ1=1;
dat>>=1;
}
}
/**************读取ds18b201当前温度************/
voidReadTemp1(void)
{
unsignedchara=0;
unsignedcharb=0;
unsignedchart=0;
longtt;
Init_DS18B201();
WriteOneChar1(0xCC);//跳过读序号列号的操作
WriteOneChar1(0x44);//启动温度转换
delay_18B20(100);//thismessageis