DS18B20 与数字温度计

DS18B20 是温度检测器件,具有单总线、数字化的特点。
它的外形结构还比较脆弱,一般来说,它只是适合于检测室温的场合,环境条件稍稍恶劣一些,它就抗不住了。
在工业场合,做而论道一般还是使用 PT100,这个东西抗造。

做而论道用 18B20 和单片机制作了数字温度计,在办公室里放了 N 多年。
它和酒精温度计显示的温度,还是有些差异,也不知道谁测量的准。

做而论道编写程序,基本上以汇编为主,一般也不想拿出来,因为很少有人看汇编的程序。
用汇编语言编写程序,思维要跟着计算机、存储器、二进制、逻辑运算、...、来走。
多数人的思维,还是停留在中小学阶段,还是以十进制来分析问题,弄不了计算机本身的东西,所以都不愿意看汇编的程序。

做而论道编写的关于 DS18B20 的程序,在 PROTEUS 软件中,仿真的效果图如下:

DS18B20 与数字温度计_第1张图片

图片链接:http://xiangce.baidu.com/picture/detail/544db91e604402c24acc7adc30294a86c41227d6

http://hi.baidu.com/%D7%F6%B6%F8%C2%DB%B5%C0/album/item/40138fd88d1001e971fe7fa9b80e7bec56e797b3.html#

仿真实验时,可以断开 DS18B20 支路,数码管将会显示:Error。

图中的 DS18B20,可以用“属性”来设置小数。
小数的范围是:0、1/16 ~ 15/16,即十进制的:0、0.0625 ~ 0.9375。
小数共有四位,是 0.0625 的整数倍,但是它的器件上,只能显示 1 位小数。

在 18B20 的温度数据中,最低四位:0001 ~ 1111,就代表了十进制的:0.0625 ~ 0.9375。

看到过很多的文章,都谈到了,怎样才能从这四位数中求出十进制的小数。
呵呵,好多的方法,都是笨的真可以!
很有一些人,都知难而退了,就用查表来解决小数的问题。其实也就是查出一位小数,就都很满足了。

做而论道用了十余条指令吧,很简单的,就求出了两位小数,并且把第三位小数按照四舍五入,进到了前一位。
想要把四位小数都求出来,也不过20条指令而已,约 30us,就能解决问题。

程序中,使用了模块化的设计方法,相当规范。
模块中的转移指令,都已经设计好了偏移量,省去了好多的标号。这样,每个模块,仅有一个标号,看起来极为清晰。

不多说了,程序如下:
;=================================
DQ     EQU P3.7 ;18B20 接口

NO_18  BIT 20H  ;20H.0     存在标志位
D_BUF  EQU 30H  ;30H ~ 37H 显示空间
TEMP   EQU 38H  ;38H ~ 39H 温度数据
S_BOTT EQU 3AH  ;栈底位置
;=================================
    ORG   0000H
START:
    MOV   SP, #S_BOTT
    CALL  GET_T
    CALL  T_PROC
    CALL  DISPLAY
    JMP   $ - 6
;=================================
GET_T:
    CALL  INIT_18B20
    JB    NO_18, $ + 25
    MOV   A, #0CCH
    CALL  W_18B20
    MOV   A, #44H
    CALL  W_18B20
    CALL  DISPLAY
    CALL  INIT_18B20
    MOV   A, #0CCH
    CALL  W_18B20
    MOV   A, #0BEH
    CALL  W_18B20
    CALL  R_18B20
RET
;=================================
INIT_18B20:       ;初始化
    CLR   DQ       ;复位
    MOV   R3, #20   ;540us
    DJNZ  R3, $
    DJNZ  R3, $
    SETB  DQ
    MOV   R3, #30
    DJNZ  R3, $
    MOV   C,  DQ  ;读状态
    MOV   NO_18, C
    MOV   R3, #150
    DJNZ  R3, $     ;300us
RET
;=================================
W_18B20:
    MOV   R2, #8  ;写入8位数
    CLR   DQ
    MOV   R3, #6
    DJNZ  R3, $
    RRC   A
    MOV   DQ, C
    MOV   R3, #23
    DJNZ  R3, $
    SETB  DQ
    DJNZ  R2, $ - 15
RET
;=================================
R_18B20:          ;读出温度
    MOV   R0, #TEMP
    MOV   R4, #2  ;读出两字节
    MOV   R2, #8  ;读出8位数
    CLR   DQ
    NOP
    NOP
    NOP
    SETB  DQ
    MOV   R3, #9
    DJNZ  R3, $
    MOV   C, DQ
    RRC   A
    MOV   R3, #23
    DJNZ  R3, $
    DJNZ  R2, $ - 18;读出8位数
    MOV   @R0, A ;先存放到 TEMP
    INC   R0     ;后读出存 TEMP+1
    DJNZ  R4, $ - 24 
RET
;=================================
T_PROC:
    JNB   NO_18, $ + 22
;-------------------下面是显示Err
    MOV   30H, #26
    MOV   31H, #14  ;这些地址,如果是高128的地址,
    MOV   32H, #32  ;就应该使用间接寻址。
    MOV   33H, #32  ;
    MOV   34H, #31  ;现在,就用直接寻址吧。
    MOV   35H, #32
RET
;-------------------下面是数据处理
    MOV   30H, #0
    MOV   31H, #0
    MOV   32H, #0
    CLR   F0
    MOV   A, TEMP + 1
    JNB   ACC.7, $ + 16
;-------------------下面是求补
    CLR   C
    CLR   A
    SUBB  A, TEMP
    MOV   TEMP, A
    CLR   A
    SUBB  A, TEMP + 1
    MOV   TEMP + 1, A
    SETB  F0        ;负号标志
;-------------------下面处理整数
    MOV   A, TEMP
    SWAP  A
    ANL   A, #15
    MOV   B, A
    MOV   A, TEMP + 1
    ANL   A, #15
    SWAP  A
    ADD   A, B
    MOV   B, #100
    DIV   AB
    MOV   31H, A    ;百位
    MOV   A, #10
    XCH   A, B
    DIV   AB
    MOV   32H, A    ;十位
    XCH   A, B
    ADD   A, #16
    MOV   33H, A
;-------------------下面处理两位小数
    MOV   A, TEMP   ;
    ANL   A, #15    ;0001~1111=0.0625~0.9375
    MOV   B, #10
    MUL   AB        ;乘以10
    MOV   B, A      ;暂存
    SWAP  A         ;交换到低四位,就是除以16
    ANL   A, #15    ;低四位就是十分位小数
    MOV   34H, A    ;写入显示位置

    MOV   A, #10  ;再乘以10,将求出百分位小数
    XCH   A, B
    ANL   A, #15    ;这是刚才除以16的余数
    MUL   AB        ;乘以10
    MOV   C, ACC.3  ;低四位中的最高位
    SWAP  A         ;交换,就是除以16
    ANL   A, #15    ;下面是进行四舍五入 
    ADDC  A, #0     ;加上低四位中的最高位即可
    MOV   35H, A   ;写入百分位小数
;-------------------下面消除无效零
    MOV   R0, #D_BUF
    MOV   A, @R0
    JNZ   $ + 8
    MOV   @R0, #26  ;' '
    INC   R0
    CJNE  R0, #D_BUF + 3, $ - 6
;-------------------下面处理负号
    JNB   F0, $ + 6
    DEC   R0
    MOV   @R0, #28  ;'-'
RET                 ;约用100us
;=================================
DISPLAY:
    MOV   R1, #34
    CALL  DIS_ALL
    DJNZ  R1, $ - 2
RET                 ;占用时间约为200ms
;-----------------------
DIS_ALL: ;共阳数码管, P0:段, P2:反相位
    MOV   R2, #254  ;位选, 低电平有效
    MOV   R0, #D_BUF
    MOV   A, @R0
    ADD   A, #(TAB - $ - 3)
    MOVC  A, @A + PC
    MOV   P2, #255
    MOV   P0, A
    MOV   P2, R2
    DJNZ  R7, $     ;显示1ms
    DJNZ  R7, $
    MOV   A, R2
    RL    A
    MOV   R2, A
    INC   R0
    CJNE  R0, #D_BUF + 6, $ - 19 ;显示6位
    MOV   P2, #255
RET                 ;占用时间约为6.2ms
;-----------------------
TAB: ;共阳段码
    DB  0C0H, 0F9H, 0A4H, 0B0H, 099H, 092H, 082H, 0F8H;0~7
    DB  080H, 090H, 088H, 083H, 0C6H, 0A1H, 086H, 08EH;8~F
    DB  040H, 079H, 024H, 030H, 019H, 012H, 002H, 078H
    DB  000H, 010H, 0FFH  ;0.~9. ' '
    DB  08CH, 0BFH, 089H, 0C7H, 0A3H, 0AFH ;P,-,H,L,o,r
;=================================
END
;=================================
;欢迎转载,但是要注明出处--做而论道。

 

你可能感兴趣的:(非同一般)