电子系统设计与实践课程设计——多点温度测量(汇编语言+C语言版)

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

《电子系统设计与实践》
课程设计报告
课程设计题目:多点温度测量系统设计专业班级:2012级电子信息科学与技术
学生姓名:罗滨志(120802010051)
张倩(120802010020)
冯礼哲(120802010001)
吴道林(120802010006)
朱栖安(120802010039)指导老师:刘万松老师
成绩:
2015 年6 月27日
目录
摘要 (4)
1 总体设计 (4)
1.1 功能要求 (5)
1.2 总体方案及工作原理 (5)
2 系统硬件设计 (6)
2.1 器件选择 (6)
2.1.1主要器件的型号 (6)
2.1.2 AT89C51 (7)
2.1.3智能温度传感器DS18B20 (9)
2.1.4晶振电路方案 (9)
2.1.5 LED液晶显示器 (10)
2.1.6复位电路方案 (10)
2.2 硬件原理图 (11)
3 系统软件设计 (11)
3.1基本原理 (11)
3.1.1主程序 (11)
3.1.2读ROM地址程序 (12)
3.1.3显示ROM地址程序 (13)
3.1.4读选中DS18B20温度的程序 (13)
3.1.5显示温度程序 (14)
3.2软件清单 (15)
3.2.1汇编语言程序 (15)
3.2.2 C语言程序 (24)
4实验步骤 (29)
4.1汇编语言程序调试 (29)
4.2 C语言程序调试 (30)
4.3实验仿真 (31)
5设计总结 (32)
6参考文献: (33)
摘要
温度是我们生活中非常重要的物理量。

随着科学技术的不断进步与发展,温度测量在工业控制、电子测温计、医疗仪器,家用电器等各种控制系统中广泛应用。

温度测量通常可以使用两种方式来实现:一种是用热敏电阻之类的器件,由于感温效应,热敏电阻的阻值能够随温度发生变化,当热敏电阻接入电路时,则流过它的电流或其两端的电压就会随温度发生相应的变化,再将随温度变化的电压或者电流采集过来,进行A/D转换后,发送到单片机进行数据处理,通过显示电路,就可以将被测温度显示出来。

这种设计需要用到A/D转换电路,其测温电路比较麻烦。

第二种方法是用温度传感器芯片,温度传感器芯片能把温度信号转换成数字信号,直接发送给单片机,转换后通过显示电路显示即可。

这种方法电路比较简单,设计方便,现在使用非常广泛。

关键词:多点温度测量单片机温度传感器
1 总体设计
多路温度测量系统的总体结构如图1所示,根据要求,整个系统包含以下几个部分:51单片机、时钟电路、复位电路组成的51单片机小系统;多块测温模块;显示温度值的显示模块和按键模块。

测温模块由温度传感器组成,温度传感器采用美国Dallas半导体公司推出的智能温度传感器DS18B20,温度测量范围为-55 -- +125,可编程为9到12位的A/D转换精度,测温分辨率可达0.0625C,完全能够满足系统要求。

DS18B20采用单总线结构,只需要一根数据线DQ即可与单片机通信,多个DS18B20可同时连接在一根数据线上与单片机通信。

显示器可采用LCD液晶显示器,显示信息量大、效果好、使用方便。

图1 多路温度测量系统的总体结构
系统处理时,由51单片机控制从各个测温模块测量出温度数字量,存入缓冲区;然后通过按键控制,从缓冲区取出,根据数字量和温度的关系计算出温度值,依次送LCD显示器显示。

1.1 功能要求
多点温度测量系统的功能要求如下:
(1)能够测量多点温度;
(2)精度0.1C;
(3)能够通过显示器显示测量点编号和温度值;
(4)可轮流显示各测量点或指定显示某个测量点。

1.2 总体方案及工作原理
单片机系统由AT89C51单片机,复位电路和时钟电路组成,时钟采用12MHZ 的晶振,温度模块由4块温度传感器DS18B20组成,单总线结构,所有的DS18B20的DQ连接在一起与单片机的P3.0相连,通过上拉电阻连接电源,每一个DS18B20都有一个唯一的64位ROM地址,只要发送相应的ROM地址,就能够访问该器件,要访问某个DS18B20,就必须知道它的64位ROM地址,可以通过程序读出它的ROM地址,由于读ROM地址时,一次只能接入一个DS18B20,因此,4个DS18B20的数据线DQ通过开关连接到AT89C51的P3.0.
另外,所有DS18B20的VDD引脚接+5V电源,GND接地;显示器采用LCD1602(LM016L),其数据线与AT89C51的P2口相连,RS与P1.7相连,R/W与P1,6相连,E端与P1.5相连。

设定了两个按键,K0为功能键,与AT89C51的P1.0相连,当K0输入低电平时,读入DS18B20的ROM地址,当K0键输入高电平时,显示选中DS18B20的温度值;K1为测量点选中键,与AT89C51的P1.1相连,用于测量点选择,每按一次,测量点号加1,读入下一个DS18B20的ROM地址或显示下一个DS18B20的相应温度值。

2 系统硬件设计
2.1 器件选择
2.1.1主要器件的型号
2.1.2 AT89C51
AT89C51是一种带4K字节闪烁可编程可擦除只读存储器(FPEROM-FALSH PROGRAMMABLE AND ERASABLE READ ONLY MEORY)的低电压,高性能CMOS8位微处理器,俗称单片机。

AT89C51是一种带4K字节闪烁可编程可擦除只读存储器的单片机,单片机的可擦除只读存储器可以反复擦除100次。

该器件采用ATMEL 高密度非易失存储器制造技术制造,与工业标准的MCS-51指令集和输出管脚相兼容,
AT89C51单片机包含中央处理器、程序存储器(ROM)、数据存储器(RAM)、定时/计数器、串行接口和中断系统等几大单元及数据总线、地址总线和控制总线等三大总线。

其基本结构如图2
图 2 AT89C51单片机的基本结构
AT89C51 是一个低电压,高性能CMOS 8 位单片机,片内含8kB 的可反复擦写的Flash 只读程序存储器和256B 的随机存取数据存储器(RAM),器件采用ATMEL公司的高密度、非易失性存储技术生产,与标准MCS-51 指令系统及8052 产品引脚兼容,片内置有通用8 位中央处理器(CPU)和Flash 存储单元。

图3 AT89C51单片机的引脚
VCC/GND:供电电源。

P0口:可以被定义为数据/地址的低八位,能够用于外部程序/数据存储器。

在FIASH编程时,P0 口作为原码输入口,当FIASH进行校验时,P0输出原码,此时P0外部必须被拉高。

P1口:标准输入输出I/O口,P1口管脚写入1后,被内部上拉为高,可用作输入。

在FLASH编程和校验时,P1口作为第八位地址接收。

P2口:既可用于标准输入输出I/O,也可用于外部程序存储器或数据存储器访问时的高八位地址。

P2口在FLASH编程和校验时接收高八位地址信号和控制信号。

P3口:既可以作标准输入输出I/O,也可作为AT89C51的一些特殊功能口,管脚备选功能 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(外部数据存储器读选通)
RST:复位输入。

当振荡器复位器件时,要保持RST脚两个机器周期的高电平时间。

ALE/PROG:当访问外部存储器时,地址锁存允许的输出电平用于锁存地址的地位字节。

在FLASH编程期间,此引脚用于输入编程脉冲。

在平时,ALE端以不变的频率周期输出正脉冲信号,此频率为振荡器频率的1/6。

PSEN:外部程序存储器的选通信号。

在由外部程序存储器取指期间,每个机器周期两次/PSEN有效。

但在访问外部数据存储器时,这两次有效的/PSEN信号将不出现。

EA / VPP:当/EA保持低电平时,则在此期间外部程序存储器(0000H-FFFFH),不管是否有内部程序存储器。

注意加密方式1时,/EA将内部锁定为RESET;当/EA端保持高电平时,此间内部程序存储器。

在FLASH编程期间,此引脚也用于施加12V编程电源(VPP)。

XTAL1:反向振荡放大器的输入及内部时钟工作电路的输入。

XTAL2:来自反向振荡器的输出。

2.1.3智能温度传感器DS18B20电路
四个DS18B20分别接一个按钮开关,便于分别控制温度,DS18B20的VCC接口接入同一总线且与显示器VDD接口相连,DQ接口与AT89C51的P3.0接口相连,GND接地,如图4;
图4 智能温度传感器原理图
2.1.4晶振电路方案
晶振电路的功能在于给单片机提供振荡时钟信号,使单片机正常工作。

本设计中采用了常用的晶振电路组成方案,具体如图5所示。

图5 晶振电路
2.1.5 LED液晶显示器
图6 液晶显示器
2.1.6复位电路方案
复位电路的功能在于对单片机进行复位从而达到对整个电路复位的功能。

要达到目的则要求在复位按键按下后在RST引脚上要出现一个维持2个机器周期高电平[4]。

考虑到可以利用电容的电压不能突变(需要一定的充放电时间),于是采用如下复位电路。

图7 复位电路
2.2 硬件原理图
图8 硬件原理图
3 系统软件设计
3.1基本原理
多路温度测量系统的软件程序主要由主程序、读DS18B20模块ROM地址程序、显示DS18B20模块ROM地址、读DS18B20模块温度值程序、显示DS18B20模块温度值程序和LCD、DS18B20模块驱动程序等组成。

3.1.1主程序
主程序的流程图如图9所示。

图9 主程序流程图
在主程序中,首先对LCD初始化,其次通过检测按键,判断是读DS18B20模块的ROM地址还是读DS18B20模块的温度值,如果是读ROM地址,则依次调用读ROM程序和显示ROM程序;如果是读温度,则调用测量温度程序和显示温度程序,注意测量某个DS18B20模块之前,一定要读出该模块的ROM并保存到相应的存储单元。

3.1.2读ROM地址程序
读ROM地址程序的流程如图10所示。

读ROM地址时,一次只能把一片DS18B20模块连接到单总线上,读ROM程序实现把当前连接到总线上的DS18B20的ROM 地址读出。

读ROM地址程序处理过程如下,先计算存放当前DS18B20模块ROM 地址的存储单元的偏移地址,然后依次是DS18B20初始化、发读ROM命令和读ROM地址到存储单元。

如图10 读ROM地址程序的流程
3.1.3显示ROM地址程序
显示ROM地址程序实现依次从当前存放ROM地址的缓冲区中取出地址显示,显示ROM地址程序的流程图如图11所示。

如图11 显示ROM地址程序的流程图
3.1.4读选中DS18B20温度的程序
读选中DS18B20温度的程序的流程图如图12所示。

读选中DS18B20模块温度值的处理过程分3个步骤,第一是向总线放启动温度转换命令,启动连接总线上的DS18B20模块温度转换,由于12位DS18B20温度转换时间比较长,所以启动转换后一定要调用延时程序等待转换完成后才能去读温度值;第二根据当前器
件号取当前DS18B20器件的64位ROM地址,发送到总线匹配对应的DS18B20模块;第三向总线发读暂存器命令读匹配的DS18B20模块转换的温度值。

如图12读选中DS18B20温度的程序的流程图
3.1.5显示温度程序
显示温度程序的流程如图13所示。

显示温度程序显示读出的温度值及相应的提示信息。

DS18B20的温度值是2位,存放在两个字节中,其中高字节的高5位为符号位,如果温度值是正数,则符号位为0,如果温度值是负数,则符号位为1。

显示温度处理程序时,先根据高字节的高5位判断是正数还是负数,如果是正数,则提取其中的百位、十位、个位及小数位,转换成字符编码放入相应的显示缓冲区;如果是负数,则提取其中的负号、十位、个位及小数位,转换成字符编码,放入相应的显示缓冲区;最后把显示缓冲区的内容显示到LCD显示器。

如图13 显示温度程序的流程
3.2软件清单
3.2.1汇编语言程序
;系统时钟频率12MHZ
;第一片18B20的ROM地址放在20H-27H
;第二片18B20的ROM地址放在30H-37H
;第三片18B20的ROM地址放在40H-47H
;第二片18B20的ROM地址放在50H-57H
DQ BIT P3.0 ;定义单总线端口
E BIT P1.5 ;定义LCD端口
RW BIT P1.6
RS BIT P1.7
K0 BIT P1.0 ;定义功能开关,K0断开,显示温度;K0接通,读ROM K1 BIT P1.1 ;定义通道选择键
NUM1 EQU 3EH ;定义存放读ROM的编号
NUM2 EQU 3FH ;定义存放显示通道的编号
LCD_3 EQU 3DH ;存放通道温度的百、十、个、小数位
LCD_2 EQU 3CH
LCD_1 EQU 3BH
LCD_0 EQU 3AH
TEMP_DATA_L EQU 4EH ;存放读出的18B20的12为编码
TEMP_DATA_H EQU 4FH
ORG 0000H
LJMP MAIN
ORG 0030H
MAIN: MOV SP, #60H
MOV NUM1, #0 ;编号初始化为0
MOV NUM2, #0
CALL LCD_INIT ;LCD初始化
AGAIN: JB K0, DISPTEMP ;判读ROM,还是显示温度
READ: JB K1, NEXT1 ;读ROM,默认读0号,按一次K1编号加1 JNB K1, $
INC NUM1
MOV A, NUM1
CJNE A, #4, NEXT1 ;如果加到4,则回到0
MOV NUM1, #0
NEXT1: LCALL READ_ROM ;读当前ROM保存
LCALL DISP_ROM ;显示当前ROM
SJMP AGAIN
DISPTEMP: JB K1, NEXT2 ;显示温度,默认显示0号,按一次K1编号加1 JNB K1, $
INC NUM2
MOV A, NUM2
CJNE A, #4, NEXT2 ;如果加到4,则回到0
MOV NUM2, #0
NEXT2: LCALL READ_TEMP ;读当前匹配18B20的温度,保存
LCALL DISP_TEMP ;显示当前匹配18B20的温度
SJMP AGAIN
;**************************************
;匹配ds18b20,读模块温度值到缓冲区
;**************************************
READ_TEMP: MOV R0, #20H
MOV A, NUM2
MOV B, #10H ;由编号取得缓冲区地址
MUL AB
ADD A, R0
MOV R0, A
LCALL DS18B20_INIT ;18B20初始化
MOV A, #0CCH ;跳过ROM命令
LCALL WRITE_BYTE
MOV A, #44H ;启动温度转换
LCALL WRITE_BYTE
LCALL DELAY
LCALL DELAY
LCALL DS18B20_INIT ;18B20初始化
MOV A,# 55H
LCALL WRITE_BYTE ;发匹配命令
MOV R5, #08H
LOOPREAD: MOV A, @R0 ;送入匹配的64位ROM地址
LCALL WRITE_BYTE
INC R0
DJNZ R5, LOOPREAD
MOV A, #0BEH
LCALL WRITE_BYTE ;发读暂存器
LCALL READ_BYTE ;读出温度低字节
MOV TEMP_DA TA_L, A
LCALL READ_BYTE ;读出温度高字节
MOV TEMP_DA TA_H, A
RET
;****************************************
;显示匹配模块温度程序
;****************************************
DISP_TEMP: MOV A, #80H ;写入显示缓冲区起始地址为第1行第1列ACALL WC51R
MOV A, #'A' ;第1行第1列显示字母A
ACALL WC51DDR
MOV A, #'D' ;第1行第2列显示字母D
ACALL WC51DDR
MOV A, #'D' ;第1行第3列显示字母D
ACALL WC51DDR
MOV A, #'R' ;第1行第4列显示字母R
ACALL WC51DDR
MOV A, #':' ;第1行第5列显示字母:
ACALL WC51DDR
MOV A, #' ' ;第1行第6列显示空格
ACALL WC51DDR
MOV A, NUM2 ;第1行第7列显示编号
ADD A, #30H
ACALL WC51DDR
MOV A, #0C0H ;写入显示缓冲区起始地址为第2行第1列
ACALL WC51R
MOV A, #'T' ;第2行第1列显示字母T
ACALL WC51DDR
MOV A, #'E' ;第2行第2列显示字母E
ACALL WC51DDR
MOV A, #'M' ;第2行第3列显示字母M
ACALL WC51DDR
MOV A, #'P' ;第2行第4列显示字母P
ACALL WC51DDR
MOV A, #':' ;第2行第5列显示字母:
ACALL WC51DDR
CONVERT_T: MOV A, TEMP_DA TA_H
ANL A, #80H
JZ TEMPC1 ;如果温度寄存器里的高位为1,则温度为负
CLR C
MOV A, TEMP_DATA_L
CPL A ;负温度将补码转成二进制,取反再加1
ADD A, #01H
MOV TEMP_DA TA_L,A
MOV A, TEMP_DATA_H
CPL A
ADDC A, #00H
MOV TEMP_DA TA_H,A
MOV A, TEMP_DATA_L
ANL A, #0FH
MOV DPTR, #TABLE2
MOVC A, @A+DPTR ;查表得小数位的值
MOV LCD_0, A
MOV A, TEMP_DATA_L
ANL A, #0F0H
SWAP A
MOV TEMP_DA TA_L,A
MOV A, TEMP_DATA_H
ANL A, #0FH
SWAP A
ORL A, TEMP_DATA_L
MOV B, #100
DIV AB
MOV LCD_3, #'-' ;负温度最高位显示“-”号
SJMP TEMPC2
TEMPC1: MOV A, TEMP_DA TA_L
ANL A, #0FH
MOV DPTR, #TABLE2
MOVC A, @A+DPTR
MOV LCD_0, A ;查表得小数位的值
MOV A, TEMP_DATA_L
ANL A, #0F0H
SWAP A
MOV TEMP_DA TA_L, A
MOV A, TEMP_DATA_H
ANL A, #0FH
SWAP A
ORL A, TEMP_DATA_L
MOV B, #100
DIV AB
MOV DPTR, #TABLE1
MOVC A, @A+DPTR
MOV LCD_3, A ;正温度的百位
TEMPC2: MOV A, #10
XCH A, B
DIV AB
MOV DPTR, #TABLE1
MOVC A, @A+DPTR
MOV LCD_2, A ;温度值的十位
MOV A, B
MOV DPTR, #TABLE1
MOVC A, @A+DPTR
MOV LCD_1, A ;温度值的个位
MOV A, LCD_3
ACALL WC51DDR ;第2行第6列显示温度的百位或“-”
MOV A, LCD_2
ACALL WC51DDR ;第2行第7列显示温度的十位
MOV A, LCD_1
ACALL WC51DDR ;第2行第8列显示温度的个位
MOV A, #'.'
ACALL WC51DDR ;第2行第9列显示小数点‘.‘
MOV A, LCD_0
ACALL WC51DDR ;第2行第10列显示温度的小数位
MOV A, #' '
ACALL WC51DDR ;第2行后面的显示空格
MOV A, #' '
ACALL WC51DDR
MOV A, #' '
ACALL WC51DDR
MOV A, #' '
ACALL WC51DDR
MOV A, #' '
ACALL WC51DDR
MOV A, #' '
ACALL WC51DDR
RET
;**************************************
;从ds18b20中读出64位序列号
;**************************************
READ_ROM: MOV R5, #8
MOV A, NUM1 ;由编号取得缓冲区地址
MOV B, #10H
MUL AB
MOV R1, #20H
ADD A, R1
MOV R1, A
LCALL DS18B20_INIT ;18B20初始化
MOV A, #33H
LCALL WRITE_BYTE ;发读ROM命令
D1: LCALL READ_BYTE ;读64位ROM,存入缓冲区
MOV @R1,A
INC R1
DJNZ R5, D1
RET
;*************************************
;将读出的64位序列号显示在LCD上
;*************************************
DISP_ROM: MOV A, #80H ;写入显示缓冲区起始地址为第1行第1列ACALL WC51R
MOV A, #'A' ;第1行第2列显示字母A
ACALL WC51DDR
MOV A, #'D' ;第1行第3列显示字母D
ACALL WC51DDR
MOV A, #'D' ;第1行第4列显示字母D
ACALL WC51DDR
MOV A, #'R' ;第1行第5列显示字母R
ACALL WC51DDR
MOV A, #':' ;第2行第6列显示:
ACALL WC51DDR
MOV A, #' ' ;第2行第7列显示空格
ACALL WC51DDR
MOV A, NUM1
ADD A, #30H ;第2行第8列显示编号
ACALL WC51DDR
MOV A, #0C0H ;写入显示缓冲区起始地址为第2行第1列
ACALL WC51R
MOV A, NUM1 ;由编号取得缓冲区地址
MOV B, #10H
MUL AB
MOV R1, #20H
ADD A, R1
MOV R1, A
MOV R5, #8
D2: MOV A, @R1 ;64位ROM地址转换成16位十六进制数显示MOV B, #16
DIV AB
MOV R3, A
CLR C
SUBB A, #10
MOV A, R3
JC D3
ADD A, #07H
D3: ADD A, #30H
ACALL WC51DDR
MOV A, B
SUBB A, #10H
MOV A, B
JC D4
ADD A, #07H
D4: ADD A, #30H
ACALL WC51DDR
INC R1
DJNZ R5, D2
RET
;******************************************
;初始化DS18B20
;******************************************
DS18B20_INIT:
SETB DQ
NOP
NOP
CLR DQ
MOV R6, #0A0H
DJNZ R6, $
MOV R6, #0A0H
DJNZ R6, $
SETB DQ
MOV R6, #32H
DJNZ R6, $
MOV C,DQ
JC ERROR
MOV R6,#064H
DJNZ R6,$
RET
ERROR: CLR DQ
SJMP DS18B20_INIT
RET
;**************************************** ;读DS18B20一个字节程序
;**************************************** READ_BYTE: MOV R7,#08H
SETB DQ
NOP
NOP
LOOP: CLR DQ
NOP
NOP
NOP
SETB DQ
MOV R6,#07H
DJNZ R6,$
MOV C,DQ
MOV R6,#3CH
DJNZ R6,$
RRC A
SETB DQ
DJNZ R7,LOOP
MOV R6,#3CH
DJNZ R6,$
RET
;*************************************** ;写DS10B20程序
;*************************************** WRITE_BYTE: MOV R7,#08H
SETB DQ
NOP
NOP
LOOP1: CLR DQ
MOV R6,#07H
DJNZ R6,$
RRC A
MOV DQ,C
MOV R6,#34H
DJNZ R6,$
SETB DQ
DJNZ R7,LOOP1
RET
;LCD初始化程序
LCD_INIT: MOV A,#00000001H ;清屏
ACALL WC51R
MOV A,#00111000B ;使用8位数据,显示两行,使用5-7的字型
ACALL WC51R
MOV A,#00001100B ;显示器开,光标关,字符不闪烁
ACALL WC51R
MOV A,#00000110B ;字符不动,光标自动右移一格
ACALL WC51R
RET
;检查忙子程序
F_BUSY: PUSH ACC ;保护现场
OV P2,#0FFH
CLR RS
SETB RW
WAIT: CLR E
SETB E
JB P2.7,W AIT ;忙,等待
POP ACC ;不忙,恢复现场
RET
;写入命令子程序
WC51R: ACALL F_BUSY
CLR E
CLR RS
CLR RW
SETB E
MOV P2,ACC
CLR E
RET
;写入数据子程序
WC51DDR: ACALL F_BUSY
CLR E
SETB RS
CLR RW
SETB E
MOV P2,ACC
CLR E
RET
;**********************************
;延时程序
;**********************************
DELAY: MOV R4,#00H
D5: MOV R5,#00H
DJNZ R5,$
DJNZ R4,D5
RET
;定义0-9的字符编码
TABLE1: DB 30H,31H,32H,33H,34H,35H,36H,37H,38H,39H,3AH
;定义小数位的对应字符编码
TABLE2: DB 30H,31H,31H,32H,33H,33H,34H,34H,35H,36H,36H,37H,38H,38H,39H,39H END
3.2.2 C语言程序
//系统时钟频率12MHZ
#include<reg51.h>
#include<intrins.h>
#define uchar unsigned char
#define uint unsigned int
sbit DQ=P3^0;
sbit EN=P1^5;
sbit RW=P1^6;
sbit RS=P1^7;
sbit K0=P1^0;
sbit K1=P1^1;
uchar NUM1,NUM2;
//存放4个DS18B20的64位ROM地址,
//0-7单元存放第1个DS18B20,8-15单元存放第2个DS18B20
//16-23单元存放第3个DS18B20,24-31单元存放第4个DS18B20
uchar rom[32];
uchar code LCDData[]="0123456789"; //定义0-9的字符编码
uchar code dot_tab[]="0112334456678899";
uchar LCD1_line[16]="ADDR: ";
uchar LCD2_line[16]="TEMP: ";
uchar DA TA_L,DATA_H;
//LCD检查忙函数
void fbusy()
{
P2=0xff;
RS=0;
RW=1;
EN=1;
EN=0;
while((P2&0x80))
{
EN=0;
EN=1;
}
}
//LCD写命令函数
void wc51r(uchar j)
{
fbusy();
EN=0;
RS=0;
RW=0;
EN=1;
P2=j;
EN=0;
}
//LCD写数据函数
void wc51ddr(uchar j)
{
fbusy;
EN=0;
RS=1;
RW=0;
EN=1;
P2=j;
EN=0;
}
//LCD1602初始化
void lcd_init()
{
wc51r(0x01);
wc51r(0x38);
wc51r(0x0c);
wc51r(0x06);
}
//延时函数
void delay(uint useconds) {
for(;useconds>0;useconds--); }
//18b20复位
void ds18b20_init(void) {
while(1)
{
DQ=1;_nop_();_nop_();
DQ=0;delay(50);
DQ=1;delay(3);
if (!DQ) {
delay(25);break;
}
DQ=0; //否则在发复位信号
}
}
//从单总线上读取一个字节
uchar read_byte(void)
{
uchar i;
uchar value=0;
DQ=1;_nop_();_nop_();
for (i=8;i>0;i--)
{
value >>=1;
DQ=0;_nop_();_nop_();_nop_();
DQ=1;
delay(1);
if(DQ) value |=0x08;
delay(6);
}
return(value);
}
//向单总线写一个字节
void write_byte(uchar val)
{
uchar i;
DQ=1;_nop_();_nop_();
for(i=8;i>0;i--)
{
DQ=0;
DQ=val&0x01;
delay(5);
DQ=1;
val=val/2;
}
delay(5);
}
//读出总线上的DS18B20模块的ROM地址,存入指定的ROM单元void read_rom()
{
uchar i,j;
j=NUM1*8;
ds18b20_init();
write_byte(0x33);
for(i=0;i<8;i++)
{
rom[j+i]=read_byte();
}
}
//显示读出的DA18B20模块的ROM地址
void disp_rom()
{
uchar k,j;
uchar temp,temp1,temp2;
LCD1_line[6]=LCDData[NUM1];
wc51r(0x80);
for(k=0;k<16;k++)
{
wc51ddr(LCD1_line[k]);
}
j=NUM1*8;
wc51r(0xc0);
for(k=0;k<8;k++)
{
temp=rom[j+k];
temp1=temp/16;
temp2=temp%16;
if(temp1>9) temp1=temp1+0x37;else temp1=temp1+0x30;
if(temp2>9) temp2=temp2+0x37;else temp2=temp2+0x30;
wc51ddr(temp1);
wc51ddr(temp2);
}
}
//读选中的DS18B20模块的温度值
void read_temp()
{
uchar i,j;
j=NUM2*8;
ds18b20_init();
write_byte(0xcc);
write_byte(0x44);
delay(400);
ds18b20_init();
write_byte(0x55);
for(i=0;i<8;i++)
{
write_byte(rom[j+i]);
}
write_byte(0xbe);
DA TA_L=read_byte();
DA TA_H=read_byte();
}
//显示匹配的DS18B20模块的温度值
void disp_temp()
{
uchar k;
uchar temp;
LCD1_line[6]=LCDData[NUM2];
wc51r(0x80);
for(k=0;k<16;k++)
{
wc51ddr(LCD1_line[k]);}
wc51r(0xc0);
if((DATA_H&0xf0)==0xf0)
{
DATA_L=~DATA_L;
if(DA TA_L==0xff)
{
DATA_L=DATA_L+0x01;
DATA_H=~DATA_H;
DATA_H=DATA_H+0x01;
}
else
{
DATA_L=DATA_L+0x01;
DATA_H=~DATA_H;
}
LCD2_line[10]=dot_tab[DA TA_L&0x0f];
temp=((DATA_L&0xf0)>>4)|((DATA_H&0x0f)<<4);
LCD2_line[6]='-';
LCD2_line[7]=LCDData[(temp%100)/10];
LCD2_line[8]=LCDData[(temp%100)%10];
}
else
{
LCD2_line[10]=dot_tab[DA TA_L&0x0f];
temp=((DA TA_L&0xf0)>>4)|((DATA_H&0x0f)<<4);
LCD2_line[6]=LCDData[temp/100];
LCD2_line[7]=LCDData[(temp%100)/10];
LCD2_line[8]=LCDData[(temp%100)%10];
}
LCD2_line[9]='.';
for(k=0;k<16;k++)
{
wc51ddr(LCD2_line[k]);}
}
//主函数
void main()
{
NUM1=0;NUM2=0;
lcd_init();
while(1)
{
if(K0==0)
{
if(K1==0)
{
while(K1==0);
NUM1++;if(NUM1==4) NUM1=0;
}
read_rom();
disp_rom();
}
else
{
if(K1==0)
{
while(K1==0);
NUM2++;if(NUM2==4) NUM2=0;
}
read_temp();
disp_temp();
}
}
}
4 实验步骤
4.1汇编语言程序调试
在Keil软件中输入实验发送端参考程序,调试程序如图13。

如图13 汇编语言调试程序
如图13发送端程序调试图可以看出程序调试无错误,所以将调试无错误的发送端程序转换为HEX文件;
4.2 C语言程序调试
在Keil软件中输入实验发送端参考程序,调试程序如图14。

如图14 C语言程序调试
如图14发送端程序调试图可以看出程序调试无错误,所以将调试无错误的发送端程序转换为HEX文件;
4.3实验仿真
按照多点温度测量系统的电路原理图在Proteus软件中连接相应源器件如图15
如图15 电路硬件原理图
将首先转换好的HEX文件下载到相应的芯片中,在Proteus中仿真图形如图15
如图16 电路仿真图
5 设计总结
本设计介绍了多点温度测量系统设计方法,论文首先介绍了多点温度测量的总体设计,其中包括以下几个部分:51单片机、时钟电路、复位电路组成的51
单片机小系统;多块测温模块;显示温度值的显示模块和按键模块。

智能温度传感器主要使用美国DALLAS半导体公司推出的DS18B20,而显示器主要采用LCD 液晶显示器,显示信息量大、效果好、使用也比较方便。

通过本设计我们可以从多方面了解温度的测量原理及其工作原理,将单一的温度测量变成多元化的系统,可以同时检测不同温度,将复杂的系统简单化,在系统仿真运行时,测量温度值一定要读出各DS18B20模块的ROM地址,而DS18B20模块的ROM地址只能一个一个地读出,这是我们在运行仿真时要特别注意的。

6参考文献:
【1】蔡骏编著.单片机实验指导教程.安徽:安徽大学出版社,2008.7
【2】刘万松、曹晓龙.微型计算机原理及应用实验教程.四川:西南交通大学出版社,2013.8
【3】杨加国. 单片机原理与应用及C51程序设计. 清华大学出版社,2009(2)
【4】李光飞、楼然苗、胡佳文、谢象佐.单片机课程设计实例教程.北京:北京航空航天大学出版社,2004.9。

相关文档
最新文档