AFON // радиотехник affonya@mail.ru
← Проекты на PIC

Проект 31. Цифровой термометр DS18B20

Цифровой датчик по однопроводной шине: импульс сброса, тайм-слоты записи и чтения — весь протокол 1-Wire реализован вручную на ассемблере с точностью до микросекунд.

Задача

Прочитать температуру с цифрового датчика DS18B20.

Микроконтроллер: PIC16F84A, кварц 4 МГц. Среда: MPLAB X + MPASM (или любой совместимый ассемблер). Как настроить среду и прошить контроллер — в статье программирование PIC.

Что понадобится

  • PIC16F84A
  • кварц 4 МГц + 2×22 пФ
  • датчик DS18B20
  • резистор 4,7 кОм (подтяжка шины)
  • светодиоды для индикации

Схема подключения

ВыводПодключение
RB0 / DQлиния данных датчика, подтяжка 4,7 кОм на +5 В
VDD датчика+5 В (или паразитное питание от линии)
GND датчикаобщий провод

Алгоритм

  1. Послать импульс сброса и дождаться отклика присутствия.
  2. Отправить команду SKIP ROM — на шине один датчик, адресация не нужна.
  3. Дать команду CONVERT T и подождать окончания преобразования.
  4. Снова сбросить шину и командой READ SCRATCHPAD прочитать два байта температуры.

Листинг на ассемблере

Код проверен ассемблером и собирается без ошибок. Скачать: p31.asm · p31.hex (готовая прошивка).

;=======================================================
; Проект 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

Пояснения

  • Линией управляют не уровнем, а направлением вывода: в защёлке всегда ноль, а переключение TRISB либо прижимает шину к нулю, либо отпускает её на подтяжку.
  • Тайм-слоты жёстко нормированы: ошибка в десятки микросекунд ломает обмен, поэтому задержки считаны в машинных циклах при кварце 4 МГц.
  • Температура приходит с шагом 0,0625 °C: младшие четыре бита — дробная часть, поэтому для целых градусов результат сдвигают на четыре разряда.

Что дальше

Разобравшись с этим проектом, переходите к следующему в разделе проекты на PIC. Справочник по архитектуре и периферии контроллеров — на странице микроконтроллеры PIC.