;=======================================================
; Проект 31. Цифровой термометр DS18B20 (шина 1-Wire)
; PIC16F84A, 4 МГц (1 команда = 1 мкс)
; Линия данных — RB0, подтяжка 4,7 кОм на +5 В
; Целая часть температуры выводится на RB1..RB7 (7 бит)
;=======================================================
        LIST    p=16F84A
        #include <p16f84a.inc>
        __CONFIG _XT_OSC & _WDT_OFF & _PWRTE_ON & _CP_OFF

#define DQ      PORTB,0

        cblock  0x0C
        d1, d2, bitcnt, byte, lsb, msb, temp
        endc

        ORG     0x000
        goto    Start

Start
        bsf     STATUS,RP0
        movlw   b'00000001'     ; RB0 — вход (линия отпущена)
        movwf   TRISB
        bcf     STATUS,RP0
        bcf     DQ              ; в защёлке всегда ноль

Main
        call    OwReset
        movlw   0xCC            ; SKIP ROM — один датчик на шине
        call    OwWrite
        movlw   0x44            ; CONVERT T — запуск измерения
        call    OwWrite
        call    Delay750ms      ; ждём преобразования

        call    OwReset
        movlw   0xCC
        call    OwWrite
        movlw   0xBE            ; READ SCRATCHPAD
        call    OwWrite
        call    OwRead
        movwf   lsb             ; младший байт температуры
        call    OwRead
        movwf   msb             ; старший байт

        ;--- целые градусы: сдвигаем результат на 4 разряда ---
        swapf   lsb,w
        andlw   0x0F
        movwf   temp
        swapf   msb,w
        andlw   0xF0
        iorwf   temp,f
        rlf     temp,f          ; выводим в старшие биты порта
        movf    temp,w
        andlw   0xFE            ; RB0 оставляем за шиной
        movwf   PORTB
        goto    Main

;--- импульс сброса и проверка присутствия ---
OwReset
        bsf     STATUS,RP0
        bcf     TRISB,0         ; прижимаем линию к нулю
        bcf     STATUS,RP0
        call    Delay500us
        bsf     STATUS,RP0
        bsf     TRISB,0         ; отпускаем
        bcf     STATUS,RP0
        call    Delay500us
        return

;--- запись байта из W ---
OwWrite
        movwf   byte
        movlw   .8
        movwf   bitcnt
WBit
        bsf     STATUS,RP0
        bcf     TRISB,0         ; старт тайм-слота
        bcf     STATUS,RP0
        nop
        nop
        nop
        nop
        nop
        nop
        rrf     byte,f          ; младший бит вперёд
        btfsc   STATUS,C
        goto    WOne
        call    Delay60us       ; ноль: держим линию низкой
        goto    WEnd
WOne
        bsf     STATUS,RP0
        bsf     TRISB,0         ; единица: сразу отпускаем
        bcf     STATUS,RP0
        call    Delay60us
WEnd
        bsf     STATUS,RP0
        bsf     TRISB,0
        bcf     STATUS,RP0
        nop
        nop
        decfsz  bitcnt,f
        goto    WBit
        return

;--- чтение байта в W ---
OwRead
        movlw   .8
        movwf   bitcnt
RBit
        bsf     STATUS,RP0
        bcf     TRISB,0         ; короткий старт
        bcf     STATUS,RP0
        nop
        nop
        bsf     STATUS,RP0
        bsf     TRISB,0         ; отпускаем и читаем
        bcf     STATUS,RP0
        nop
        nop
        nop
        nop
        bcf     STATUS,C
        btfsc   DQ
        bsf     STATUS,C
        rrf     byte,f
        call    Delay60us
        decfsz  bitcnt,f
        goto    RBit
        movf    byte,w
        return

Delay60us
        movlw   .19
        movwf   d1
X60     nop
        decfsz  d1,f
        goto    X60
        return

Delay500us
        movlw   .165
        movwf   d1
X500    nop
        decfsz  d1,f
        goto    X500
        return

Delay750ms
        movlw   .250
        movwf   d2
Y1      movlw   .250
        movwf   d1
Y2      nop
        nop
        nop
        nop
        nop
        nop
        nop
        nop
        nop
        nop
        decfsz  d1,f
        goto    Y2
        decfsz  d2,f
        goto    Y1
        return

        END
