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

[atmega32][asm]procedury do 1-wire

marcinxat 12 Mar 2009 18:11 2549 9
REKLAMA
  • #1 6272576
    marcinxat
    Poziom 11  
    witam

    Przeszukując elektrodę można znaleźć mnóstwo procedurek dotyczących 1-wire na AVR ale niestety w większości pod język C lub bascom.

    W jednym wątku znalazłem jakieś procedury ale jak ktoś w nim zauważył z błędami. Kolejną procedurkę znalezioną w kursie asm pod avr znalazłem na mikrokontrolery.net.
    Procedurki są ustawione pod 4MHz.

    #define DQ_PORT DDRD
    #define DQ 5
    #define IN_DQ PIND
    #define SET_DQ cbi DQ_PORT, DQ		;ustawienie jako wejścia
    #define CLR_DQ sbi DQ_PORT, DQ		;ustawienie jako wyjścia
    #define acc r19
    #define count r20
    #define temp r21
    #define rdel r22
    #define lsb r23
    #define msb r24
    

    delay:
    	nop
    	subi rdel, 1
    	brne delay
    	ret
    
    ; procedura generujaca sygnał reset na linii 1wire
    ow_reset:
    	CLR_DQ 					; stan niski na linii 1wire
    	ldi rdel, 255 			;
    	rcall delay 			;
    	ldi rdel, 119 			; opóźnienie ok 480 us
    	rcall delay 			;
    	
    	SET_DQ 					; stan wysoki na linii 1wire
    	ldi rdel, 255 			;
    	rcall delay ;
    	ldi rdel, 119 			; opóźnienie ok 480 us
    	rcall delay ;
    	ret
    
    ; procedura nadania bitu przez linię 1wire
    ow_write_bit:
    	CLR_DQ 					; stan niski na linii 1wire
    	ldi rdel, 7
    	rcall delay
    	cpi acc, 0
    	breq dalej
    	SET_DQ
    dalej:
    	ldi rdel, 80
    	rcall delay
    	SET_DQ
    	ret
    
    ; procedura odczytu bitu z linii 1wire
    ow_read_bit:
    	CLR_DQ
    	ldi rdel, 1
    	rcall delay
    	SET_DQ
    	ldi rdel, 11
    	rcall delay
    	ldi acc, 1
    	sbis IN_DQ, DQ
    	ldi acc, 0
    	ret
    
    ; procedura wysłania bajtu na linię 1wire
    ow_write:
    	mov temp, acc 			; zapamiętanie danej wejściowej w rejestrze temp
    	ldi count, 1 			; załadowanie do licznika wartości początkowej
    loop1:
    	mov acc, temp 			; przywrócenie danej wejściowej
    	and acc, count 			; iloczyn logiczny danej wejściowej i licznika
    	rcall ow_write_bit 		; wywołanie procedury zapisu bitu
    	lsl count 				; przesuniecie licznika o 1 bit w lewo
    	cpi count, 0 			; sprawdzenie, czy licznik = 0
    	brne loop1 				; jeśli nie to wróc na początek pętli
    	ret
    
    ; procedura odczytu bajtu z linii 1wire
    ow_read:
    	ldi temp, 0 			; wyzerowanie rejestru temp
    	ldi count, 1 			; załadowanie do licznika wartości początkowej
    loop2:
    	rcall ow_read_bit 		; wywołanie procedury odczytu bitu z linii 1wire
    	cpi acc, 0 				; porównanie zwróconej wartośći z liczbą 0
    	breq rd1 				; jeśli równe to skocz do rd1
    	or temp, count 			; jeśli rózne to wykonaj sumę logiczną temp i licznika
    rd1:
    	ldi rdel, 6 			; opóźnienie
    	rcall delay
    	lsl count 				; przesunięcie licznika o 1 bit w lewo
    	cpi count, 0 			; sprawdzenie, czy licznik = 0
    	brne loop2 				; jeśli nie to skocz na początek pętli
    	mov acc, temp 			; przepisanie temp do acc
    	ret


    Przy resecie 1-wire najpierw następuje wymuszenie stanu niskiego na okres 480us poleceniem CLR_DQ (czyli sbi DQ_PORT, DQ) czyli ustawienie końcówki DQ jako wyjście. Po 480us użyta jest komeda SET_DQ (cbi DQ_PORT, DQ) czyli ustawienie DQ jako wejście.
    Mam następujące pytania:
    1. czy gdy ustawiam DQ jako wejście nie powinno się podpiąć jeszcze wewnętrznego rezystora? Z komentarzy wynika że na DQ wymuszony będzie stan wysoki gdy użyję cbi DQ_PORT, DQ.
    2. czy ustawienie DQ jako wyjście automatycznie wymusza na nim stan niski?
    3. czy czasy opóźnień są prawidłowo ustawione dla 4MHz?

    A może posiada ktoś przejrzyste procedurki obsługi 1-wire? Muszę przyznać że się już pogubiłem.
    pozdrawiam i dzięki z góry

    Dodano po 5 [godziny] 43 [minuty]:

    Być może pytania okazały się zbyt dosłowne.

    Jeśli mógłbym więc prosić o procedurki do 1-wire w asemblerze byłbym wielce zobowiązany.
  • REKLAMA
  • Pomocny post
    #2 6274782
    krzych41
    Poziom 15  
    
    ;*
    ;*******************************************************************************
    ;*PROCEDURY OBSŁUGI MAGISTRALI 1-Wire DLA MIKROKONTROLERA AVR 
    ;*******************************************************************************
    ;*
    ;*Nazwa pliku   :AVR_1Wire.asm
    ;*
    ;*Przeznaczenie :dowolny AVR, za wyjątkiem AT90S1200
    ;*Kwarc         :4MHz
    ;*
    ;*******************************OPIS********************************************
    ;*
    ;*Interfejsem 1Wire jest linia PXy, która jest skonfigurowana jako wejściowa
    ;* bez podciągania. Do jej rejestru wyjściowego (PORTXy) jest na stałe wpisana
    ;* wartość 0.
    ;* Dane będą odbierane poprzez bezpośredni odczyt rejestru PINX.
    ;* Wysłanie bitu o wartości 1 będzie się wiązało z ustawieniem bitu y portu PX
    ;* w tryb wejściowy (stan H wymuszany zewnętrznym rezystorem podciągającym).
    ;* Wysłanie bitu o wartości 0 będzie polegało na przełączeniu bitu portu
    ;* w tryb wyjściowy. Wówczas zapisane wcześniej 0 do PORTXy spowoduje 
    ;* ustawienie linii interfejsu w stan niski.
    ;*
    ;*Zawiera procedury:
    ;* - PINIT - inicjacji transmisji danych między mikroprocesorem a układem
    ;*   1Wire - procedura zerowania.
    ;*   Jeśli na wyjściu z procedury:
    ;*   - Z=1 - do portu PB0 podłączony(e) jest (są) układ(y) 1Wire.
    ;*   - Z=0, N=1 - do linii nie jest podłączony żaden układ 1Wire
    ;*   - Z=0, N=0 - na linii 1Wire jest zwarcie
    ;* - PISZ1W - procedura zapisu przez mikroprocesor jednego bajtu danych
    ;*   do układu 1Wire. Zapisywany bajt pobierany jest z rejestru BuZap.
    ;* - PISZ_1 - procedura zapisu jedynki do układu 1Wire
    ;* - PISZ_0 - procedura zapisu zera do układu 1Wire
    ;* - CZYT1W - rocedura odczytu przez mikroprocesor jednego bajtu z linii
    ;*   1Wire. Bajt zostaje zapisany w rejestrze BufOd.
    ;* - TAU_5 - opóźnienia (5 * LiPet)[us]
    ;*   Przed wywołaniem procedury należy wpisać do rejestru LiPet wartość 
    ;*    żądanego opóźnienia/5 [w mikrosekundach].
    ;*   W opóźnienie wliczone są rozkazy zapisu do rejestru, wejścia i wyjścia
    ;*    z procedury: ldi, rcall, ret = (1+3+4)*T = 2us
    ;*
    ;###############################################################################
    ;
    ;*********Definicje rejestrów: BufOd
    .def    BufOd    =R0         ;bufor danych
    .def    TempL    =R1         ;mł.rej. czasowego przechowania danych
    ;---------------------------------------------------------------
    .def    TempH    =R16        ;st.rej. czasowego przechowania danych
    .def    LiPet    =R17        ;licznik pętli procedur
    .def    BuZap    =R18        ;bufor zapisu danych
    
    ;*********Definicje stałych:
    .equ    CzROM    =$33        ;dla układu 1Wire rozkaz podania numeru seryjnego
    
    ;********Definicje linii 1Wire
    .equ	RS1W	=DDRX        ;rejestr sterujący 1Wire
    .equ	DW1W	=PINX        ;rejestr danych wejściowych 1Wire
    .equ    L1Wir   =y           ;PXy - linia 1Wire
    
    ;###############################################################################
    ;
    ; Procedura inicjacji transmisji danych dla układów 1Wire:
    ;
     PINIT:
             clr    TempL           ;przygotuj rejestr
             sbi    RS1W,L1Wir      ;DDXy=1 = PXy - WY = 1Wire stan L
             ldi    LiPet,96        ;stan L utrzymaj przez 96*5=480 us
             rcall  TAU_5
             cbi    RS1W,L1Wir      ;DDXy=0 = PXy - WE = 1Wire stan H
             ldi    LiPet,13        ;odczekaj 13*5=65 us
             rcall  TAU_5
             sbis   DW1W,L1Wir      ;skocz o 1, gdy linia 1Wire ustawiona
            ;będzie wyzerowana gdy zgłosi się układ 1Wire,lub będzie zwarcie 
             inc    TempL           ;zgłosił się, więc inkrementuj rejestr
             ldi    LiPet,83        ;poczekaj do końca szczeliny 83*5=415 us
             rcall  TAU_5
             sbis   DW1W,L1Wir      ;skocz o 1, gdy linia 1Wire ustawiona
            ;będzie wyzerowana, gdy będzie zwarcie na linii
             inc    TempL           ;wyzerowana - zwarcie na linii
             dec    TempL           
             ret
            ;jeśli Z=1, to do portu PXy podłączony(e) jest (są) układ(y) 1Wire.
            ;jeśli Z=0, N=1, to do linii nie jest podłączony żaden układ 1Wire
            ;jeśli Z=0, N=0, to na linii 1Wire jest zwarcie
    ;
    ; Procedura zapisu przez mikroprocesor jednego bajtu danych do układu 1Wire.
    ;  Zapisywany bajt pobierany jest z rejestru BuZap.
    ;
     PISZ1W:
             ldi    LiPet,8         ;zapisz 8 bitów
     PISW1:  push   LiPet
             ror    BuZap           ;C->R(7)->...->R(0)->C 
             brcc   PISW3           ;jeśli C=0
             rcall  PISZ_1          ;bo C=1
     PISW2:  pop    LiPet
             dec    LiPet
             brne   PISW1           ;jeśli nie koniec bajtu
             ret
     PISW3:  rcall  PISZ_0
             rjmp   PISW2                                                  
    ;
    ; Procedura zapisu jedynki do układu 1Wire:
    ;
     PISZ_1: 
             sbi    RS1W,L1Wir      ;DDXy=1 = PXy - WY = 1Wire stan L
             ldi    LiPet,1         ;utrzymaj ten stan przez 5us
             rcall  TAU_5
             cbi    RS1W,L1Wir      ;DDXy=0 = PXy - WE = 1Wire stan H
             ldi    LiPet,20        ;poczekaj jeszcze 100us
             rcall  TAU_5
             ret
    ;
    ; Procedura zapisu zera do układu 1Wire:
    ;
     PISZ_0:
             sbi    RS1W,L1Wir      ;DDXy=1 = PXy - WY = 1Wire stan L
             ldi    LiPet,14        ;utrzymaj ten stan przez 70us (60 do 120us)
             rcall  TAU_5
             cbi    RS1W,L1Wir      ;DDXy=0 = PXy - WE = 1Wire stan H
             ret
    ;
    ; Procedura odczytu przez mikroprocesor jednego bajtu z linii 1Wire.
    ; Linią 1Wire może być dowolny PIN dowolnego portu !
    ;  Bajt zapisany zostaje w rejestrze BufOd.
    ;
    ;UWAGA:
    ;      Są trzy równoważne procedury odczytu i można stosować 
    ;      dowolną z nich. W Procedurze 1 można w miejsce rozkazów: sec - ror
    ;      wykorzystać macro insbr.
    ;
     CZYT1W: 
             ldi    LiPet,8         ;odczytaj bajt (8 bitów, od najmłodszego)
     CZYW1:  push   LiPet
             sbi    RS1W,L1Wir      ;DDXy=1 = PXy - WY = 1Wire stan L
             push   LiPet           ;utrzymaj ten stan przez 1us
             pop    LiPet
             cbi    RS1W,L1Wir      ;DDXy=0 = PXy - WE = 1Wire stan H
             ldi    LiPet,2         ;poczekaj 10us na rozpoczęcie próbkowania
             rcall  TAU_5
    		 sec					;ustaw C
    		 sbis 	DW1W,L1Wir	    ;omiń następny rozkaz, jeśli bit ustawiony
    		 clc					;zeruj C
    		 ror 	BufOd			;C->R(7)->...->R(0)->C
             ldi    LiPet,12        ;odczekaj 60us do końca slotu
             rcall  TAU_5
             pop    LiPet
             dec    LiPet
             brne   CZYW1           ;jeśli nie koniec bajtu
             ret
    ;
    ;            PROCEDURA 2:
    ;         
    ; CZYT1W: 
    ;         ldi    LiPet,8         ;odczytaj bajt (8 bitów, od najmłodszego)
    ; CZYW1:  push   LiPet
    ;         sbi    RS1W,L1Wir      ;DDXy=1 = PXy - WY = 1Wire stan L
    ;         push   LiPet           ;utrzymaj ten stan przez 1us
    ;         pop    LiPet
    ;         cbi    RS1W,L1Wir      ;DDXy=0 = PXy - WE = 1Wire stan H
    ;         ldi    LiPet,2         ;poczekaj 10us na rozpoczęcie próbkowania
    ;         rcall  TAU_5
    ;         in     TempL,DW1W      ;odczytaj port PX
    ;         push   LiPet
    ;         ldi    LiPet,L1Wir+1
    ; CZYW2:  ror    TempL           ;odczytany bit->...->R(0)->C
    ;         dec    LiPet           ;nie zmienia C !!
    ;         brne   CZYW2           ;jeśli odczytany bit nie jest w C 
    ;         pop    LiPet
    ;         ror    BufOd           ;C->R(7)->...->R(0)->C
    ;         ldi    LiPet,12        ;odczekaj 60us do końca slotu
    ;         rcall  TAU_5
    ;         pop    LiPet
    ;         dec    LiPet
    ;         brne   CZYW1           ;jeśli nie koniec bajtu
    ;         ret  
    ;
    ;           PROCEDURA 3:       
    ;
    ; CZYT1W: 
    ;         ldi    LiPet,8         ;odczytaj bajt (8 bitów, od najmłodszego)
    ; CZYW1:  push   LiPet
    ;         sbi    RS1W,L1Wir      ;DDXy=1 = PXy - WY = 1Wire stan L
    ;         push   LiPet           ;utrzymaj ten stan przez 1us
    ;         pop    LiPet
    ;         cbi    RS1W,L1Wir      ;DDXy=0 = PXy - WE = 1Wire stan H
    ;         ldi    LiPet,2         ;poczekaj 10us na rozpoczęcie próbkowania
    ;         rcall  TAU_5
    ;         in     TempL,DW1W      ;odczytaj port PX
    ;         bst    TempL,y         ;zapisz bit y rejestru TempL do T
    ;         lsr    BufOd           ;0->R(7)->...->R(0)
    ;         bld    BufOd,7         ;wpisz odczytany bit na pozycję 0 rejestru
    ;         ldi    LiPet,12        ;odczekaj 60us do końca slotu
    ;         rcall  TAU_5
    ;         pop    LiPet
    ;         dec    LiPet
    ;         brne   CZYW1           ;jeśli nie koniec bajtu
    ;         ret
    ;
    ; Procedura opóźnienia (5 * LiPet)[us]: 
    ;
     TAU_5:
             push   LiPet
             ldi    LiPet,2
     TAU1:   dec    LiPet
             brne   TAU1            ;skocz, jeśli nie zero
             pop    LiPet
             dec    LiPet
             brne   TAU2            ;skocz, jeśli nie zero
             ret
     TAU2:   push   LiPet
             ldi    LiPet,2
     TAU3:   nop
             nop
             nop
             dec    LiPet
             brne   TAU3            ;skocz, jeśli nie zero
             nop
             pop    LiPet
             dec    LiPet
             brne   TAU2            ;skocz, jeśli nie zero
             ret
    
    ;*******************************************************************************
    ;*                            KONIEC PROCEDUR
    ;*******************************************************************************
    
  • #3 6275111
    marcinxat
    Poziom 11  
    Dzięki wielkie za procedurki.

    A co do tych pytań to dalej proszę o odpowiedzi.
  • REKLAMA
  • Pomocny post
    #4 6275529
    rrata
    Poziom 19  
    1. Z tego co widzę w datasheet od DS18B20 to linia 1wire powinna miec rezystor 4k7, więc włączanie dodatkowo rezystora wewnętrznego pewnie niewiele da.
    2. Jeżeli odpowiedni bit w rejestrze PORTx (u Ciebie PORTD) będzie już miał wartość 0 to tak.
  • REKLAMA
  • Pomocny post
    #5 6275842
    krzych41
    Poziom 15  
    Przeczytaj uważnie wstępny opis do moich procedur. Tam są odpowiedzi na Twoje pytania.
  • #6 6276166
    marcinxat
    Poziom 11  
    Co do podanej przez Ciebie procedury to właściwie wszystko jest jasne. Naprawdę świetnie to wszystko wyjaśnione.

    Mam jednak takie pytanie podczas inicjalizacji najpierw generowany jest stan niski na czas 480us. Następnie odczekanie 65us i sprawdzenie czy są urządzenia 1-wire. Później następuje odczekanie 415us "do końca szczeliny".

    O co chodzi z końcem szczeliny? I dlaczego akurat 415us?
    Poza tym dlaczego sprawdzany raz jest stan linii 1-wire po 65us odczekiwania a potem znów po kolejnych 415us? Aha no i do czego tu potrzebny jest TempL?
  • Pomocny post
    #7 6276672
    krzych41
    Poziom 15  
    W procedurze inicjacji TempL służy za wskaźnik błędu. Pozostałe Twoje pytania powinny wyjaśnić materiały z załącznika.
  • #8 6278382
    marcinxat
    Poziom 11  
    wielkie dzięki za pomoc; i stała się jasność :)

    pozdrawiam

    Dodano po 33 [minuty]:

    no to odczyt działa bez zarzutu.

    Teraz kolejna sprawa a mianowicie gdy podpiętych jest kilka urządzeń 1-wire na jednej linii. Chodzi mi o to ażeby wykryć ilość podłączonych do linii urządzeń. Gdy podajemy sekwencję reset na 1-wire to możemy stwierdzić na podstawie odpowiedzi, że "coś" jest dołączone do 1-wire. A jak można stwierdzić ile urządzeń jest podpiętych?
  • #9 6278867
    krzych41
    Poziom 15  
    Jeśli nie znasz kodu adresu dołączonych urządzeń, patrz "Opis 1-wire1" str. 3-4 (pkt 2.3.4), jeśli znasz, wysyłasz kolejno ich adresy, a one Ci odpowiadają, że są podłączone. Rozkaz: SEARCH ROM = 0xF0
  • REKLAMA
  • #10 6288635
    marcinxat
    Poziom 11  
    wielkie dzięki wszystkim za pomoc

    pozdrawiam
REKLAMA