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

[AtTiny2313][ASM] Obsługa 1-wire

Adam Pyka 11 Kwi 2009 11:39 2150 2
REKLAMA
  • #1 6400736
    Adam Pyka
    Poziom 19  
    Witam!
    Piszę obsługę 1-wire w asemblerze od podstaw (takie jest zadanie).
    Napisałem sobie obsługi timingowe 1-wire zgodnie z dokumentacją ds18b20 i mam problem z implementacją odczytu/zapisu bajtu na bazie procedur odczytu/zapisu bitu.
    W załączniku jest kod całości, a poniżej problematyczne procedury:
    ;---------------------------------------
    ; Procedury komunikacyjne 1-wire
    ;
    ; Rejestr R20 - wartosc do wyslania / wartosc odczytana
    ; Rejestr R16 - tymczasowy licznik petli
    ; Rejestr R21 - flaga stanu linii 1-wire (odczytanego bitu)
    ;---------------------------------------
    
    ow_write: ;wysyla bajt po magistrali 1-wire
    	ldi R16, 8
    	Petla_w8:
    		dec R16
    		sbrs R20, R16 ;sprawdza czy jest w stanie wysokim
    		rcall ow_write_l
    		sbrc R20, R16 ;sprawdza czy jest w stanie niskim
    		rcall ow_write_h
    	brne Petla_w8
    ret
    
    ow_read: ;odczytuje bajt z magistrali 1-wire
    	ldi R16, 8 ;laduje wartosc licznika do R16
    	clr R20 ;zeruje rejestr R20
    	Petla_r8:
    		dec R16 ;zaczynamy liczyc od 7
    		rcall ow_read_b ;odczytuje bit z magistali		
    		sbrc R21, 0 ;sprawdza czy jest w stanie niskim (mozna ominac zerowanie bo zostalo to zrobione wczesniej)
    		sbr R20, R16 ;ustawia odpowiedni bit, jezeli na magistrali takowy jest w stanie wysokim
    	brne Petla_r8
    ret

    Oczywiście nie mogę użyć sbrs w ten sposób:
    sbrs R20, R16

    Więc pojawia się pytanie jak sprawdzać kolejne bity w kolejnych przebiegach "pętli" (w przypadku procedury zapisu) oraz jak ustawiać logiczne 1 w kolejnych bitach przy kolejnych przebiegach "pętli" (w przypadku procedury odczytu).
    A może jest jakiś inny sposób?

    Pozdrawiam,
    Adam Pyka
  • REKLAMA
  • Pomocny post
    #2 6407445
    rrata
    Poziom 19  
    Adam Pyka napisał:
    Więc pojawia się pytanie jak sprawdzać kolejne bity w kolejnych przebiegach "pętli" (w przypadku procedury zapisu) oraz jak ustawiać logiczne 1 w kolejnych bitach przy kolejnych przebiegach "pętli" (w przypadku procedury odczytu).
    Jeśli chodzi o zapis to zrób tak, że sprawdzasz, czy najmłodszy bit w rejestrze jest wyzerowany, jeśli tak to ustawiasz stan niski. Następnie przesuwasz w prawo zawartość rejestru (niezależnie czy było 0 czy 1) i tak w kółko (w sumie osiem razy > ilość bitów w rejestrze).

    Odczyt podobnie. Jeśli na wejściu będziesz miał stan wysoki to ustawiasz jedynkę na najstarszym bicie w rejestrze. Następnie przesuwasz zawartość rejestru w prawo (niezależnie czy wcześniej był stan niski czy wysoki) i tak osiem razy.
  • #3 6408811
    Adam Pyka
    Poziom 19  
    Dziękuję, udało się :)
    Oto procedury obsługi zapisu/odczytu bajtów:
    ow_write: ;wysyla bajt po magistrali 1-wire
    mov R17, R20 ;tworzy kopie danych z R20 do R17
    ldi R16, 1 ;laduje R16 wartoscia 1
    petla_w:
    mov R20, R17 ;tworzy kopie R17 i zapisuje ja w R20
    and R20, R16 ;iloczyn logiczny R20 i R16 zapisany w R20
    rcall ow_write_bit
    lsl R16 ;przesun bity w R16 o jedna pozycje w lewo
    cpi R16, 0 ;porownuje wartosc rejestru z zerem
    brne petla_w ;skacze do etykiety jezeli powyzszy warunek rozny
    ret
    ow_read: ;odczytuje bajt z magistrali 1-wire
    ldi R17, 0
    ldi R16, 1
    petla_r1:
    rcall ow_read_bit
    tst R20
    breq petla_r2
    or R17, R16
    petla_r2:
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    lsl R16
    tst R16
    brne petla_r1
    mov R20, R17
    ret


    Oraz obsługi wysyłania/odbioru bitu do/z magistrali:
    ow_write_bit: ;zapis do magistrali 1-wire bitu (ramka ok 100us)
    sbi DDRD, DDD6 ;wlacz tryb wyjsciowy linii 6 portu D
    cbi PORTD, PORTD6 ;wymusza stan niski na linii
    ldi R23, 1 ;wartosc mnoznika opoznienia
    rcall Czekaj_us ;opoznienie 10us
    tst R20 ;sprawdza, czy wartosc R20 jest wartoscia zerowa
    brne wb_jedynka ;skacze, jezeli jedynka do wyslania
    rjmp wb_kontynuuj ;jezeli zero to pomin ponizsza instrukcje
    wb_jedynka: ;ustaw stan wysoki
    sbi PORTD, PORTD6 ;wymusza stan wysoki na linii
    wb_kontynuuj:
    ldi R23, 9 ;wartosc mnoznika opoznienia
    rcall Czekaj_us ;opoznienie 90us
    sbi PORTD, PORTD6 ;wymusza stan wysoki na linii
    nop ;1.5us opoznienia po ramce
    ret
    ow_read_bit: ;odczyt z magistrali 1-wire bitu (ramka ok. 100us)
    sbi DDRD, DDD6 ;wlacz tryb wyjsciowy linii 6 portu D
    cbi PORTD, PORTD6 ;wymus stan niski na magistrali
    nop
    nop ;opoznienie 3us
    cbi DDRD, DDD6 ;wlacz tryb wejsciowy linii 6 portu D
    cbi PORTD, PORTD6 ;bez wewnetrznego podciagania linii portu
    nop ;odczekaj jeden cykl zegarowy na ustalenie stanu wejscia
    nop
    nop
    nop
    nop
    nop
    nop ;opoznienie ok. 9us i sprawdzenie stanu linii
    9
    ldi R20, 1
    sbis PIND, 6 ;test magistrali - pomija nast. instrukcje jezeli odczytano 1
    ldi R20, 0
    ldi R23, 9 ;laduje mnoznik opoznienia
    rcall Czekaj_us ;opoznienie 90us
    nop ;1.5us opoznienia po ramce
    ret


    Raz jeszcze dziękuję za pomoc.
    Pozdrawiam,
    Adam Pyka
REKLAMA