logo elektroda
logo elektroda
X
logo elektroda
REKLAMA
REKLAMA
Adblock/uBlockOrigin/AdGuard mogą powodować znikanie niektórych postów z powodu nowej reguły.

[ATmega16][Asembler/AVRStudio] Obsługa czujnika ds 18b20

finch 24 Mar 2011 19:40 2605 9
REKLAMA
  • #1 9317950
    finch
    Poziom 20  
    Witam

    Jestem na etapie dogadywania się z czujnikiem temperatury dallasa, i póki co nie ma widoków na żadną formę komunikacji.
    Poniżej dołączam listning kodu źródłowego z możliwie najczytelniejszymi komentarzami. Całość jest pisana z dokumentacją w ręku a mimo to po zapisie i odczycie scratchpada czujnik zwraca same 0xFF. Nie wiem czy wina leży w złej interpretacji timingów z karty katalogowej czy coś z czujnikami jest nie tak (mam 2 nowe).

    Proszę o jakąkolwiek pomoc, sugestie, przeglądałem inne kody do obsługi termometrów i wydaje mi się że wszystko jest w porządku ale teraz nie jestem już pewien niczego.


    
    .include "m16def.inc"
    
    .def AKU=R20
    .def AKU2=R17
    .def bufor_zap = R30
    .def bufor_odc = R29
    .equ SYS_FREQ=1
    
    .dseg 
    .org 0x060
    DS18B20: .byte 9
    
    .cseg
    .org 0x00
    
    ldi R16, high(ramend)
    out SPH, r16
    ldi R16, low(ramend)
    out SPL, R16
    sbi ddrd, ddd7
    cbi portd,pd7
    
    in R16, SFIOR
    ldi R16, (1<<PUD)
    out SFIOR, R16
    
    ;procedura osbsługi czujnika
    
    rcall inicjalizacja1w
    
    ldi bufor_zap, 0xCC ;skip ROM
    rcall zapisz_1w
    
    ldi bufor_zap, 0x4E ;write scratrchpad
    rcall zapisz_1w
    
    ldi bufor_zap, 0 ; zapis bajtów TH i TL czujnika
    rcall zapisz_1w
    rcall zapisz_1w
    
    ldi bufor_zap, 0b00011111 ; zapis bajtu konfiguracyjnego - rozdzielczość 8 bit
    rcall zapisz_1w
    
    ; ********czytaj scratchpad********
    rcall inicjalizacja1w
    
    ldi bufor_zap, 0xCC ;skip ROM
    rcall zapisz_1w
    
    ldi bufor_zap, 0xBE ;read scratchpad
    rcall zapisz_1w
    
    ldi ZH, high(DS18B20)
    ldi ZL, low(DS18B20)
    ldi R26, 9
    rcall czytaj_scr
    
    start:
    
    rjmp start
    
    ;*********** podprogramy obsługi ***********
    
    czytaj_scr: ;odczytaj cały scratchpad
    x_10:		;poprzez wskaźnik Z
    rcall czytaj_1w
    st Z+, bufor_odc
    dec R26
    brne x_10
    ret
    
    inicjalizacja1w: ; procedure inicjalizacji magistrali 1-wire
    
    sbi DDRD, DDD1 ; ustaw linie DQ jako wyjście
    cbi portd, pd1 ;ściągnij DQ do masy
    
    ldi AKU, 50
    rcall Czekaj_us ;czekaj ~570 us
    
    cbi ddrd, ddd1 ; ustaw linie DQ jako wejście
    
    x1:
    sbic pind, pind1 ;czekaj na presence pulse
    rjmp x1
    
    ldi AKU, 45
    rcall Czekaj_us ;czekaj ~515 us
    ret
    
    zapisz_1:
    
    sbi ddrd, ddd1 ; ustaw linie DQ jako wyjście
    cbi portd, pd1 ; ściągnij DQ do masy
    
    ;ldi AKU, 1
    ;rcall Czekaj_us
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    
    cbi ddrd, ddd1 ;ustaw magistrale w stan logicznego 1
    ldi AKU, 1
    rcall Czekaj_us ;czekaj min 31 us
    ret
    
    zapisz_0:
    
    sbi ddrd, ddd1 ;ustaw linie DQ jako wyjście
    cbi portd, pd1 ;ściągnij do masy
    
    ldi AKU, 3
    rcall Czekaj_us ;czekaj ~53 us
    
    cbi ddrd, ddd1 ;ustaw magistralę w stan logicznego 1
    ret
    
    zapisz_1w:
    push R31
    ldi R31, 8 ;8 obiegów pętli żeby zapisać bajt
    
    x3:
    lsr bufor_zap
    in R25, 0x3F ;adres SREG
    sbrc R25,0 
    rcall zapisz_1
    rcall zapisz_0
    dec R31
    brne x3
    
    pop R31
    ret
    
    czytaj_1w:
    push R31
    push R22
    clr R22 ; przygotowanie bufora odczytu 
    ldi R31, 8 ;8 obiegów pętli żeby odczytać bajt
    
    x2:
    sbi ddrd, ddd1 ;ustaw DQ jako wyjście
    cbi portd, pd1 ;ściągnij do masy
    cbi ddrd, ddd1 ; ustaw DQ jako wejście
    
    clc
    sbic pind, pind1 ;odczytu bitu na magistrali
    sec
    
    ror bufor_odc ;ładuj bufor odczytu bitem z magitrali
    
    ldi AKU, 4
    rcall Czekaj_us ;czekaj ~64 us żeby odczytać
    
    dec R31 ;sprawdź czy pętla obiegła 8 razy 1
    brne x2 ;-odczytano cały bajt danych 1/2
    
    
    pop R22 ;2
    pop R31 ;2
    ret ;4
    ;***** Mikrosekundowa procedura opóźniająca *****
    
    ;Parametry:
    ;R16 - wartość opóźnienia w dziesiątkach us (dla zera - 2560 us)
    
    ;Wymagane stałe:
    ;SYS_FREQ - częstotliwość pracy w MHz
    
    Czekaj_us:
    
    push AKU2
    push R18
    
    mov R18, AKU
    ldi AKU2, SYS_FREQ
    
    Czekaj_us_0:
    mov AKU, R18
    
    Czekaj_us_1:
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    dec AKU
    brne Czekaj_us_1
    
    dec AKU2
    brne Czekaj_us_0
    
    pop R18
    pop AKU2
    
    ret					;Powrót
    


    Pozdrawiam,
    finch

    EDIT
    Zapomniałem dopisać że kwarc musi być częstotliwości 1 MHz.
  • REKLAMA
  • #2 9318724
    hotdog
    Poziom 26  
    na początek zewrzyj pin do masy (bez czujnika) i sprawdź czy odczytuje same 00

    Pozdro
  • REKLAMA
  • #3 9318861
    finch
    Poziom 20  
    Tak, odczytuje zarówno same 0x00 jak zewrę do GND, jak zewrę do Vcc to same 0xFF lub czasami śmieci jak zaczynam podczas próby odczytu ruszać rezystorem przy Vcc.
  • #4 9318926
    hotdog
    Poziom 26  
    to stawiam flaszkę, że coś masz nie tak z timingami :)

    zrób, przynajmniej na razie, odmierzanie czasu w oparciu o timer.

    Nie jestem mistrzem assembera, twoja funkcja, mimo że wygląda dobrze, chyba nie działa dobrze. Ewentualnie fusy lub zła definicja w SYS_FREQ w porównaniu do rzeczywistości.
  • #5 9318944
    finch
    Poziom 20  
    To możemy te flaszkę we dwóch wypić, bo właśnie nad timingami się męczę ;) Wrzuciłem procedurę w Symulator w AVR Studio i to co wyszło mija się daleko z prawdą.
  • REKLAMA
  • #6 9321333
    asembler
    Poziom 32  
    Zarzekałem sie że nie zrobie obsługi bez przerwania bo to strata czasu procesora ale w końcu musiałem.
    Podaje moje wypociny.
    Załączniki:
  • #7 9328234
    finch
    Poziom 20  
    asembler dzięki za odpowiedź i załącznik, pytanie jaki masz kwarc u siebie? U mnie jest ten kłopot że muszę mieć kwarc 1MHz i wtedy obsługa nie robi się taka łatwa.
  • #8 9328291
    asembler
    Poziom 32  
    Po to jest symbol "KWARZ" aby sobie dowolnie regulować. Dowolnie nie znaczy tak do końca:-)
    Praktycznie chodzi o 500kHz do 14MHz bo tyle sprawdzałem a teoretycznie to powinno chodzic od 100kHz do 25.5Mhz ale mogę sie mylić bo nie chce mi sie przeliczać.
    Ciekawi mnie dlaczego musisz miec kwarz 1 MHz.
  • REKLAMA
  • #9 9328807
    finch
    Poziom 20  
    A no dla tego, że pomiar temperatury jest częścią większego projektu, gdzie procesor odmierza czasy rzędu pojedynczych do 30 minut. A przy jednym MHz z timera 16 bit, przy preskalerze 1024 można uzyskać około 60 s co idealnie pasuje do innych procedur.
    Stąd mam narzucony taki wymóg zegara.
  • #10 9334575
    finch
    Poziom 20  
    A więc,

    Po kilku dniach walki bliskim zaprzyjaźnieniu się z dokumentacją czujnika, przepisaniu jeszcze raz wszelkich timingów z udziałem symulatora znaleziono błąd.

    Błąd zawierał się w procedurze zapisu bajtu

    Kod: text
    Zaloguj się, aby zobaczyć kod


    i polegał na tym, że:
    jeżeli procedura napotka zero w danym bicie to komenda sbrc faktycznie pominie procedurę zapisu logicznego jeden i zacznie zapis zera, natomiast jeśli napotka jeden to owszem zapisze tą jedynkę, ale zaraz po powrocie z podprogramu weźmie się za zapis zera defakto wystawiając bzdury.

    Nowa procedura zapisu wygląda następująco:

    Kod: text
    Zaloguj się, aby zobaczyć kod


    Dzięki wszystkim za zaangażowanie w temat.

    Procedura z pierwszego postu działa, warunkiem jest przeliczenie na nowo timingów.

    Pozdrawiam,
    finch
REKLAMA