2020/09/29_DS18B20温度传感器时序模拟

1、DS18B20封装

单总线DQ,内部9个字节的寄存器和64 bit的ROM(包含唯一标识ID),暂存寄存器包含了转换温度、报警温度上下限。

空闲状态下,总线以上拉形式保持高电平。

数据传输从低位(LSB)开始。


2、18B20复位时序

(1)复位:控制器(单片机)拉低总线480-950μs,然后释放总线(拉高)。此时,单片机引脚需设置为输出。

(2)控制器释放总线后60-240μs,18B20拉低总线,表示应答。然后拉高释放总线。

(3)在第二步18B20拉低总线时,控制器检测总线状态,如果是低电平,则可判定复位成功。此时,单片机引脚需设置为输入。这里可以加一个超时检测,以防超过240μs后,仍未收到复位应答。

(4)检测到复位应答信号后,设置单片机引脚为输出,拉高总线至少1μs,释放总线。


3、向18B20写一个字节的数据

(1)单片机引脚设置为输出,拉低总线12μs。

(2)从最低位开始发送,根据最低位的值,设置引脚为低或高,延时40μs。

(3)单片机拉高总线,保持2μs左右。

(4)对发送字节数据进行逻辑右移一位,回到第(1)步,直到8位数据都发送完成。


4、从18B20读取一个字节的数据

(1)每次读取新的位时,先将读取数据的变量逻辑右移一位。

(2)单片机引脚设置为输出,拉低总线,保持12μs左右,再拉高总线,释放,加几个NOP指令延时即可。

(3)单片机引脚设置为输入,加几个NOP指令延时。

(4)检测引脚状态,收到第一位数据(第一次为最低位)。

(5)读取一位数据后,延时40μs,将单片机引脚设置为输出,拉高总线,延迟2μs以上。

(6)回到第(1)步,读取下一位数据,直到8位数据读取完成。


5、一个完整的温度转换流程

(1)复位(初始化)

(2)发送ROM命令

(3)发送寄存器命令

(4)数据传输

单个18B20连接时,可以在复位后,发送0xCC,调过ROM命令。   

寄存器命令0x44为温度转换命令,发送后,等待750ms以上(12位精度),才可进行数据读取。

寄存器命令0xBE为读取寄存器数据的命令(9个寄存器),大部分情况下,只需要读取开始的两个字节数据(温度转换结果),当读取两个字节后,可以再次复位18B20,以结束后续无关数据的读取。

实际代码时序:  复位,发送0xCC,发送0x44,延时800ms; 复位,发送0xCC,发送0xBE,调用读字节函数,保存低字节数据,调用读字节函数,保存高字节数据。


6、关于温度转换数据的处理

(1)数据一共16bit,高5个bit为符号位,如果温度值为正数,则高5位全0,温度值为负数,则高5位全1。

(2)最低4个bit为温度值的小数部分,中间的7个bit为温度值的整数部分。

(3)小数位和温度值的转换过程:将低4位乘以0.0625即为温度的小数位。 如低4位为0011,则小数部分为 3x0.0625=0.1875。程序中可以预先将小数位的值算出来,取合适的精度,用查表(00-FF,16个数值)的方式来得到小数位。


7、代码参考,温度读取后的数据处理是为了在数码管上显示,分离出符号位、整数位和小数位(小数点后两位精度):



INCLUDE 'derivative.inc' ; 这一句必须加,否则会报 value is truncated to one byte错误

        ; PJ1->DQ(18B20)

        XDEF    init_18b20,convert_18b20

        XREF    DS18B20_RST,r_data_H,r_data_L,r_buff,shuma_data,shuma_table,shuma_point_table,float_table



init_18b20:

              PSHB                    ; 每个函数里面都包含一对入栈和出栈指令,以防破坏外部操作使用 B/X/Y寄存器; A寄存器自动入栈

              PSHX

              PSHY


              BSET    DDRJ,mDDRJ_DDRJ1      ; DJ1  OUTPUT输出模式

              BCLR    PTJ,mPTJ_PTJ1        ; DJ1 -> 0

              LDAA    #$C7

              LDX    #$77

              CALL    delay_n_us            ; 延时 600μs (实际延时略大于600)

              BSET    PTJ,mPTJ_PTJ1        ; DJ1 -> 1

              LDAA    #$C7

              LDX    #$B

              CALL    delay_n_us            ; 延时60μs

              BCLR    DDRJ,mDDRJ_DDRJ1      ; DJ1  INPUT输入模式

              LDX    #2000                ; 设置应答超时,以防进入死循环

              time_out:

                          DEX

                          CPX    #0

                          BEQ    time_out_err

                          BRSET  PTJ,mPTJ_PTJ1,time_out          ; 使用PTJ, 勿使用PTIJ

                          LDAA    #1            ; 正常检测到应答信号,返回1,复位成功

                          STAA    DS18B20_RST

                          BSET    DDRJ,mDDRJ_DDRJ1      ; DJ1  OUTPUT输出模式    检测到复位应答后,单片机将总线拉高,保持1μs

                          BSET    PTJ,mPTJ_PTJ1        ; DJ1 -> 0

                          NOP

                          LDAA    #$13

                          LDX    #$1

                          CALL    delay_n_us          ; 延时1μs


                          PULY

                          PULX

                          PULB

                          RTC


              time_out_err:              ;超时返回0

                          LDAA    #0

                          STAA    DS18B20_RST

                          PULY

                          PULX

                          PULB

                          RTC


convert_18b20:

              PSHB

              PSHX

              PSHY


              CALL    init_18b20

              LDAB    #$CC

              CALL    w_18b20                         

              LDAB    #$44

              CALL    w_18b20

              LDY    #2

delay_800ms:  LDAA    #$F9

              LDX    #$F9FF

              CALL    delay_n_us

              DECY

              CPY    #0

              BNE    delay_800ms



              CALL    init_18b20

              LDAB    #$CC

              CALL    w_18b20

              LDAB    #$BE

              CALL    w_18b20



              CALL    r_18b20

              MOVB    r_buff,r_data_L

              CALL    r_18b20

              MOVB    r_buff,r_data_H

              CALL    init_18b20        ; BE命令会连续返回所有9个字节,这里复位18b20可以中断后面的 数据返回。否则18b20会出错。




; 处理数据,赋值给数码管相关变量

data_pro:


              LDY    #shuma_data

              LDAA    r_data_H

              ANDA    #$F0

              CMPA    #$F0

              BNE    pos_data

              MOVB    #$BF,1,Y+    ; negative data

pos_data:    MOVB    #$FF,1,Y+


              LDAA    r_data_H

              LDAB    r_data_L


              ANDA    #$07

              LDX    #4              ; 左移 4位, 计算整数位

lsr_4:        LSRD

              DECX

              CPX    #0

              BNE    lsr_4 


              LDY    #$0000          ; 计算百位

              LDX    #100

              EDIV

              XGDX                    ; D 和 X 交换, 保存余数 D到X中

              XGDY                    ; 将商保存在D中, 实际用到B

              LDY    #shuma_table    ; 基址

              ABY                    ; 加上B中的 偏移量

              XGDX                    ; 回恢复余数到 D

              LDX    #shuma_data

              MOVB    Y,1,+X


              LDY    #$0000            ; 计算十位

              LDX    #10

              EDIV   

              XGDX                    ; D 和 X 交换, 保存余数 D到X中

              XGDY                    ; 将商保存在D中, 实际用到B

              LDY    #shuma_table    ; 基址

              ABY                    ; 加上B中的 偏移量

              XGDX                    ; 恢复余数到 D

              LDX    #shuma_data

              MOVB    Y,2,+X


              LDY    #shuma_point_table    ;  表基址    个位

              ABY                          ; 加上B中的值 ,偏移量

              LDX    #shuma_data

              MOVB    Y,3,+X


; 小数位 计算             

              LDAB    r_data_L          ; 计算小数位  , 先查表出小数位的十进制表示

              ANDB    #$0F              ; 屏蔽高4位

              LDY    #float_table

              ABY

              MOVB    Y,r_data_L

              LDAB    r_data_L


              LDY    #$0000

              LDX    #10

              EDIV

              XGDX                    ; D 和 X 交换, 保存余数 D到X中

              XGDY                    ; 将商保存在D中, 实际用到B

              LDY    #shuma_table    ; 基址

              ABY                    ; 加上B中的 偏移量

              XGDX                    ; 恢复余数到 D

              LDX    #shuma_data

              MOVB    Y,4,+X


              LDY    #shuma_table    ;  表基址    个位

              ABY                    ; 加上B中的值 ,偏移量

              LDX    #shuma_data

              MOVB    Y,5,+X



              PULY

              PULX

              PULB

              RTC         



; Write a byte to 18b20 ,入口参数  需要写的数据 存放到 B 寄存器

w_18b20: 

              PSHB

              PSHX

              PSHY

              LDY    #8

              BSET    DDRJ,mDDRJ_DDRJ1

w_start:      BCLR    PTJ,mPTJ_PTJ1        ; 输出0

              LDAA    #$17

              LDX    #$13

              CALL    delay_n_us            ; 延时12μs

              TBA

              ANDA    #$01

              BEQ    w0

w1:          BSET    PTJ,mPTJ_PTJ1        ; 写 1

              LDAA    #$C7

              LDX    #$7

              CALL    delay_n_us            ; 延时40μs

              BSET    PTJ,mPTJ_PTJ1

              LSRB 

              LDAA    #$13

              LDX    #$3

              CALL    delay_n_us          ; 延时2μs

              DECY

              CPY    #0

              BNE    w_start

              PULY

              PULX

              PULB

              RTC

              w0:  BCLR    PTJ,mPTJ_PTJ1  ; 写 0

                    LDAA    #$C7

                    LDX    #$7

                    CALL    delay_n_us            ; 延时40μs

                    BSET    PTJ,mPTJ_PTJ1

                    LSRB

                    LDAA    #$13

                    LDX    #$3

                    CALL    delay_n_us          ; 延时2us

                    DECY

                    CPY    #0

                    BNE    w_start

                    PULY

                    PULX

                    PULB

                    RTC



; Read a byte from 18b20  ,返回的数据保存在 r_buff 内,返回数据不要保存在寄存器A/B/X/Y中,因为有出栈操作!

r_18b20:

            PSHB

            PSHX

            PSHY


            LDAB    #$00

            LDY    #8

r_start:    LSRB   

            BSET    DDRJ,mDDRJ_DDRJ1

            BCLR    PTJ,mPTJ_PTJ1      ; 输出0

            LDAA    #$17

            LDX    #$13

            CALL    delay_n_us        ; 延迟12μs

            BSET    PTJ,mPTJ_PTJ1    ; 释放总线

            NOP

            NOP

            BCLR    DDRJ,mDDRJ_DDRJ1  ;设置输入

            NOP

            NOP

            NOP

            BRCLR  PTJ,mPTJ_PTJ1,r0  ; 不能使用PTIJ寄存器    ,在12μs处 采样

r1:        ORAB    #$80


            LDAA    #$C7

            LDX    #$7

            CALL    delay_n_us      ; 延迟40μs

            BSET    DDRJ,mDDRJ_DDRJ1

            BSET    PTJ,mPTJ_PTJ1

            LDAA    #$0F

            LDX    #$13

            CALL    delay_n_us        ; 延迟8μs


            DECY

            CPY    #0

            BNE    r_start

            STAB    r_buff

            PULY

            PULX

            PULB

            RTC

            r0:    ORAB    #$00

                    LDAA    #$C7

                    LDX    #$7

                    CALL    delay_n_us      ; 延迟40μs

                    BSET    DDRJ,mDDRJ_DDRJ1

                    BSET    PTJ,mPTJ_PTJ1

                    LDAA    #$0F

                    LDX    #$13

                    CALL    delay_n_us        ; 延迟8μs

                    DECY

                    CPY    #0

                    BNE    r_start

                    STAB    r_buff

                    PULY

                    PULX

                    PULB

                    RTC


; 使用PIT的通道0,入口参数  微时基参数放在 A,  PIT加载寄存器值放在 X   

; 除去前面的设置指令耗时, PIT延时= (A+1)*(X+1)*0.025  μs

delay_n_us:

              PSHB

              PSHX

              PSHY

              MOVB    #$00,PITINTE        ; 关PIT中断

              MOVB    #$00,PITMUX        ; 选择微时基0


              STAA    PITMTLD0            ; 设置微时基值

              XGDX                        ; 交换D/X寄存器值,将PIT计数值放到D中

              STD    PITLD0              ; 设置PIT加载寄存器

              MOVB    #$81,PITCFLMT

              MOVB    #$01,PITCE          ; 启动计数

              BRCLR  PITTF,mPITTF_PTF0,* ; 查询方式,检查是否计数溢出

              MOVB    #$01,PITTF          ; 清除TF标志位


              MOVB    #$00,PITCE

              MOVB    #$00,PITCFLMT      ; 关PIT


              PULY

              PULX

              PULB

              RTC

你可能感兴趣的:(2020/09/29_DS18B20温度传感器时序模拟)