Задача
Прочитать температуру с цифрового датчика DS18B20.
Микроконтроллер: PIC16F84A, кварц 4 МГц. Среда: MPLAB X + MPASM (или любой совместимый ассемблер). Как настроить среду и прошить контроллер — в статье программирование PIC.
Что понадобится
- PIC16F84A
- кварц 4 МГц + 2×22 пФ
- датчик DS18B20
- резистор 4,7 кОм (подтяжка шины)
- светодиоды для индикации
Схема подключения
| Вывод | Подключение |
|---|---|
| RB0 / DQ | линия данных датчика, подтяжка 4,7 кОм на +5 В |
| VDD датчика | +5 В (или паразитное питание от линии) |
| GND датчика | общий провод |
Алгоритм
- Послать импульс сброса и дождаться отклика присутствия.
- Отправить команду SKIP ROM — на шине один датчик, адресация не нужна.
- Дать команду CONVERT T и подождать окончания преобразования.
- Снова сбросить шину и командой 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.