一、实验目的:
 
1)  AT89S52X单片机为核心器件,组成一个数字式温度计。
2)  了解DS18B20的工作原理及使用方法。
3)  掌握DS18B20读写时序的编程方法。
4)  锻炼单片机综合应用和开发的能力
 
二、实验内容与要求:
 
1)显示当前温度:在数码管显示模块上前四个数码管显示当前温度(整数小数各两位)。
2)编程要求:用汇编语言编写此程序,写出各个子程序的功能并在主要的指令后加上必要地文字说明增加程序的可读性。
 
 
1)硬件电路原理图:
如图-1所示,
实验六:温度传感DS18B20实验(数码管显示)_DS18B20实验六:温度传感DS18B20实验(数码管显示)_DS18B20_02
实验六:温度传感DS18B20实验(数码管显示)_温度传感_03
      -1温度测量使用P1.3端口,使用DS18B20器件,显示使用4位数码管。
 
   2)工作原理:本实验通过DS18B20采集环境温度,当单片机检测到DSl820的存在便可以发出ROM操作命令之一,Read ROM(ROM)   Match ROM(匹配ROM)   Skip ROM(跳过ROM)   Search ROM(搜索ROM)    Alarm search(告警搜索)   然后对发存储器操作命令对DS18B20进行读写数据转换等操作。单片机使用时间隙(time slots)来读写DSl820的数据位和写命令字的位,然后将读到的数据转换BCD码在数码管显示出来(DS18B20的详细资料详见附录)。
 
四.软件流程设计:
该系统采用的方法,根据初始化温度传感器,再就是显示温度数值。测量出来温度软件系统基本流程如图所示:   
 
       实验六:温度传感DS18B20实验(数码管显示)_休闲_04实验六:温度传感DS18B20实验(数码管显示)_温度传感_05
 
五.参考程序:
 
/*------------------------------内存分配声明--------------------------*/
TEMPER_L  EQU   31H     ;用于保存读出温度的低字节
TEMPER_H  EQU   30H   ;用于保存读出温度的高字节
T_DF      EQU   33H   ;FORMAT后的小数部分(decimal fraction),半字节的温度小数(存在低四位)
T_INTEGER EQU   32H    ;FORMAT后的整数部分(integer),将两字节的温度整合成1字节
FLAG    BIT     20H       ;标志位
DAT     BIT     P1.3       ;DS18B20数据线
 
/*------------------------------主函数开始-----------------------------*/
        ORG     0000H   ;函数入口地址
        AJMP    MAIN   ;跳转指令
        ORG     0030H                
MAIN:
        CLR     EA              ;使用DS18B20一定要禁止中断
        MOV     SP,#60H
        MOV     T_DF,#00H       ;赋初始温度为30
        MOV     T_INTEGER,#30H
START:  LCALL   GET_TEMPER      ;调用读温度子程序
        LCALL   T_FORMAT        ;将读出的2字节温度格式化,并转换为压缩BCD
        LCALL   DISPLAY         ;显示温度
        AJMP    START
 
/*-----------------------DS18B20的温度转换子程序-----------------------*/
GET_TEMPER:
        LCALL   Set_18B20           ;调用DS18B20初始化程序
        MOV     A,#0CCH         ;跳过ROM匹配
        LCALL   WRITE_1820              ;调用写DS18B20的子程序
        MOV     A,#44H          ;发出温度转换命令
        LCALL   WRITE_1820
        LCALL   DISPLAY         ;用显示温度(持续1s左右)来等待AD转换结束,12位的话要转换750ms
        LCALL   Set_18B20       ;准备读温度前先初始化
        MOV     A,#0CCH         ;跳过ROM匹配
        LCALL   WRITE_1820
        MOV     A,#0BEH         ;发出读温度命令
        LCALL   WRITE_1820
        LCALL   READ_1820       ;DS18B20的程序
        RET
 
/*--------------------------DS18B20初始化程序--------------------------*/
Set_18B20:
        SETB    DAT                           ;置位
        NOP                                          ;空操作
        CLR     DAT                           ;清零
        MOV     R2,#250         ;主机发出延时500微秒的复位低脉冲
        DJNZ    R2,$                    ;自减(-1)循环
        SETB    DAT             ;然后拉高数据线
        MOV     R2,#30
        DJNZ    R2,$            ;延时60us等待DS18B20回应
        JNB     DAT,INIT1
        JMP     Set_18B20       ;超时而没有响应,重新初始化
INIT1:  MOV     R2,#120
        DJNZ    R2,$            ;延时240us
        JB      DAT,INIT2       ;数据变高,初始化成功
        JMP     Set_18B20
INIT2:  MOV     R2,#240
        DJNZ    R2,$
        RET
 
/*-----------------DS18B20的子程序(有具体的时序要求)-----------------*/
WRITE_1820:
        MOV     R2,#8           ;8位数据
WR0:    CLR     DAT
        MOV     R3,#6
        DJNZ    R3,$
        RRC     A
        MOV     DAT,C
        MOV     R3,#20
        DJNZ    R3,$
        SETB    DAT
        NOP
        NOP
        DJNZ    R2,WR0
        SETB    DAT
        RET
 
/*------DS18B20的程序,DS18B20中读出两个字节的温度数据----------------*/
READ_1820:
        MOV     R4,#2           ;将温度高位和低位从DS18B20中读出
        MOV     R1,#TEMPER_L    ;低位存入31H(TEMPER_L)
RE0:    MOV     R2,#8
RE1:    SETB    DAT
        NOP
        NOP
        CLR     DAT
        NOP
        NOP
        SETB    DAT
        MOV     R3,#4
        DJNZ    R3,$
        MOV     C,DAT
        RRC     A
        MOV     R3,#30
        DJNZ    R3,$
        DJNZ    R2,RE1
        MOV     @R1,A
        DEC     R1              ;高位存入30H(TEMPER_H)
        DJNZ    R4,RE0
        RET
 
/*------整合读出的两字节温度(关于DS18B20读出的2字节温度格式请参考资料)-----*/
T_FORMAT:
        MOV     A,#0FH
        ANL     A,TEMPER_L
        MOV     T_DF,A          ;获得小数部分(4)
        MOV     A,TEMPER_L
        SWAP    A
        MOV     @R0,A
        MOV     A,TEMPER_H
        SWAP    A
        XCHD    A,@R0
        MOV     T_INTEGER,A     ;获得整数部分(1字节)
TO_BCD: MOV     A,T_INTEGER
        MOV     B,#10
        DIV     AB
        SWAP    A
        ADD     A,B
        MOV     T_INTEGER,A     ;整数部分压缩BCD码送T_INTEGER
        MOV     A,T_DF
        MOV     B,#10
        MUL     AB
        MOV     B,#16
        DIV     AB
        MOV     R2,A            ;暂存R2
        MOV     A, B
        MOV     B,#10
        MUL     AB
        MOV     B,#16
        DIV     AB
        MOV     B,A
        MOV     A,R2
        SWAP    A
        ADD     A,B
        MOV     T_DF,A          ;小数部分压缩BCD码送T_DF
        RET
 
/*---------------------------显示温度子程序----------------------------*/
DISPLAY:MOV     R1,#250
DISP1:  MOV     A,T_INTEGER
        MOV     R3,#0FEH
        MOV     R4,#0FDH
        SETB    FLAG
DISP2:  CPL     FLAG
        MOV     B,#10H
        DIV     AB
        MOV     R2,A            ;高位送R2暂存
        MOV     DPTR,#2000H     ;字位口
        MOV     A,R3
        MOVX    @DPTR,A         ;送字位
        MOV     A,R2            ;字型R2A
        MOV     DPTR,#TAB       ;表首地址送DPTR
        MOVC    A,@A+DPTR       ;查表
        MOV     DPTR,#6000H     ;字型口
        MOVX    @DPTR,A         ;送字型
        CALL    D1MS            ;延时
        MOV     A,#0FFH
        MOVX    @DPTR,A         ;关闭字型显示
        MOV     R2,B            ;低位送R2暂存
        MOV     DPTR,#2000H     ;字位口
        MOV     A,R4
        MOVX    @DPTR,A         ;送字位
        MOV     A,R2            ;字型R2A
        MOV     DPTR,#TAB       ;表首地址送DPTR
        MOVC    A,@A+DPTR       ;查表
        JNB     FLAG,D1                    ;FLAG 为零,跳到D1
        JMP     D2                       ;否则,跳到D2
D1:     ANL     A,#7FH                ;相与
D2:     MOV     DPTR,#6000H     ;字型口
        MOVX    @DPTR,A         ;送字型
        CALL    D1MS            ;延时
        MOV     A,#0FFH
        MOVX    @DPTR,A         ;关闭字型显示
        MOV     A,T_DF
        MOV     R3,#0FBH
        MOV     R4,#0F7H
        JNB     FLAG,DISP2
        DJNZ    R1,DISP1
        RET
 
/*-------------------------1mS延时(12MHZ)--------------------------*/
D1MS:   MOV     R7,#250
LOOP0:  NOP
        NOP
        DJNZ    R7,LOOP0
        RET
 
/*-------------------------共阳数码管对应字型表-------------------------*/
TAB:    DB 0C0H,0F9H,0A4H,0B0H,99H,92H,82H,0F8H  ;段码表
        ;   0    1    2     3   4   5   6    7   对应内容
        DB 80H,90H,88H,83H,0C6H,0A1H,86H,8EH
        ;   8   9   A    B   C   D    E   F
 END
六.实验步骤:
    1.DS18B20的数据手册,弄明白其时序及编程思路。
    2.看实验开发板的连线手册,分析计算出显示模块数码管的物理地址。
    3.画出程序流程图编写相应的程序。
    4.将程序下载到开发板上并调试程序,使程序达到预定功能。
1.写出项目方案,包括硬件设计方案和软件设计方案。
2.给出电路原理图和程序流程图的设计。
3.提供程序清单,并加以注释。
4.在调试过程中发现了哪些问题?你是怎么解决的?
5.总结项目开发的经验
八.思考题:
     本实验实现了单点的温度采集,你能否在本实验的基础上设计实验实现多点温度采集的系统。
 
 
 
                                      附录
数字温度传感器DS1820(DS18B20)的应用
 
一 单线数字温度计DSl820介绍
 
DSl820数字温度计提供9(二进制)温度读数指示器件的温度信息经过单线接口送入DSl820或从DSl820送出因此从主机CPUDSl820仅需一条线(和地线)DSl820的电源可以由数据线本身提供而不需要外部电源因为每一个DSl820在出厂时已经给定了唯一的序号因此任意多个DSl820可以存放在同一条单线总线上这允许在许多不同的地方放置温度敏感器件DSl820的测量范围从-55+125增量值为0.5可在l s(典型值)内把温度变换成数字每一个DSl820包括一个唯一的64位长的序号该序号值存放在DSl820内部的ROM(只读存贮器)中开始8位是产品类型编码(DSl820编码均为10H)接着的48位是每个器件唯一的序号最后8位是前面56位的CRC(循环冗余校验)DSl820中还有用于贮存测得的温度值的两个8位存贮器RAM编号为0号和11号存贮器存放温度值的符号如果温度为负()1号存贮器8位全为1否则全为00号存贮器用于存放温度值的补码LSB(最低位)1表示0.5将存贮器中的二进制数求补再转换成十进制数并除以2就得到被测温度值(-550125)DSl820的引脚如图226l所示每只D51820都可以设置成两种供电方式即数据总线供电方式和外部供电方式采取数据总线供电方式可以节省一根导线但完成温度测量的时间较长采取外部供电方式则多用一根导线但测量速度较快温度计算
 
1 Ds18209位存贮温值度最高位为符号位下图为18b20的温度存储方式负温度S=1正温度S=0
 
00AAH+85 ,0032H25 ,FF92H55
2. Ds18b2012位存贮温值度最高位为符号位下图为18b20的温度存储方式负温度S=1正温度S=0
0550H+85 ,0191H25.0625 ,FC90H-55
. DSl820工作过程及时序
DSl820工作过程中的协议如下
初始化RoM操作命令存储器操作命令处理数据
1初始化
单总线上的所有处理均从初始化开始
2ROM操作品令
总线主机检测到DSl820的存在便可以发出ROM操作命令之一这些命令如
指令 代码
Read ROM(ROM) [33H]
Match ROM(匹配ROM) [55H]
Skip ROM(跳过ROM] [CCH]
Search ROM(搜索ROM) [F0H]
Alarm search(告警搜索) [ECH]
3存储器操作命令
指令 代码
Write Scratchpad(写暂存存储器) [4EH]
Read Scratchpad(读暂存存储器) [BEH]
Copy Scratchpad(复制暂存存储器) [48H]
Convert Temperature(温度变换) [44H]
Recall EPROM(重新调出) [B8H]
Read Power supply(读电源) [B4H]
4时 序
主机使用时间隙(time slots)来读写DSl820的数据位和写命令字的位
(1)初始化
时序见图2.25-2主机总线to时刻发送一复位脉冲(最短为480us的低电平信号)接着在tl时刻释放总线并进入接收状态DSl820在检测到总线的上升沿之后等待15-60us接着DS1820t2时刻发出存在脉冲(低电平持续60-240 us)如图中虚线所示
以下子程序在MCS51仿真机上通过其晶振为12M.初始化子程序
RESET
PUSH B ;保存B寄存器
PUSH A 保存A寄存器
MOV A,#4 ;设置循环次数
CLR P1.0 ;发出复位脉冲
MOV B,#250 ;计数250
DJNZ B,$ ;保持低电平500us
SETB Pl.0 ;释放总线
MOV B,#6 ;设置时间常数
CLR C ;清存在信号标志
WAITL: JB Pl.0,WH ;若总线释放跳出循环
DJNZ B,WAITL ;总线低等待
DJNZ ACC,WAITL;释放总线等待一段时间
SJMP SHORT
WH: MOV B,#111
WH1: ORL C,P1.0
DJNZ B,WH1 ;存在时间等待
SHORT: POP A
POP B
RET
(2)写时间隙
当主机总线t o时刻从高拉至低电平时就产生写时间隙见图22532254to时刻开始15us之内应将所需写的位送到总线上DSl820t15-60us间对总线采样若低电平写入的位是0见图2253若高电平写入的位是1见图2254连续写2位间的间隙应大于1us
写位子程序(待写位的内容在C)
WRBIT:
PUSH B ;保存B
MOV B,#28 ;设置时间常数
CLR P1.0 ;写开始
NOP ;1us
NOP ;1us
NOP ;1us
NOP ;1us
N0P ;1us
MOVPl.0,C ;C内容到总线
WDLT: DJNZ B,WDLT;等待56Us
POP B
SETB Pl.0 ;释放总线
RET ;返回
写字节子程序(待写内容在A):
WRBYTB:
PUSH B :保存B
MOV B#8H ;设置写位个数
WLOP: RRC A ;把写的位放到C
ACALL WRBIT ;调写 1位子程序
DJNZ BWLOP ;8位全写完?
POP B
RET
(3)读时间隙
见图2255主机总线to时刻从高拉至低电平时总线只须保持低电平l 7ts之后在t1时刻将总线拉高产生读时间隙读时间隙在t1时刻后t 2时刻前有效t zto15s也就是说t z时刻前主机必须完成读位并在t o后的60s120 fzs内释放总线
读位子程序(读得的位到C)
RDBIT:
PUSH B ;保存B
PUSH A ;保存A
MOV B,#23 ;设置时间常数
CLR P1.0 ;读开始图2255t0时刻
NOP ;1us
NOP ;1us
NOP ;1us
NOP ;1us
SETB Pl.0 ;释放总线
MOV A,P1 ;P1口读到A
MOV C,EOH ;P1.0内容C
NOP ;1us
NOP ;1us
NOP ;1us
NOP ;1us
RDDLT: DJNZ B,RDDLT ;等待46us
SETB P1.0
POP A
POP B
RET
读字节子程序(读到内容放到A)
RDBYTE:
PUSH B ;保存B
RLOP MOV B,#8H ;设置读位数
ACALL RDBIT ;调读1位子程序
RRC A ;把读到位在C中并依次送给A
DJNZ B,RLOP ;8位读完?
POP B ;恢复B
RET