Aktyw Forum

Zarejestruj się na forum.ep.com.pl i zgłoś swój akces do Aktywu Forum. Jeśli jesteś już zarejestrowany wystarczy, że się zalogujesz.

Sprawdź punkty Zarejestruj się

Realizacja kilku niezależnych linii 1-wire

radzio
Moderator
Moderator
Posty:967
Rejestracja:13 maja 2003, o 10:33
Lokalizacja:Sosnowiec
Kontaktowanie:
Realizacja kilku niezależnych linii 1-wire

Postautor: radzio » 15 maja 2007, o 21:28

Od czasu do czasu pojawiają się pytania o realizację magistrali 1-wire na kilku różnych wyprowadzeniach mikrokontrolera. Rozwiązanie takie pozwala na pominięcie kwestii rejestracji numerów seryjnych układów pracujących na magistrali lub korzystania ze złożonego mechanizmu wyszukiwania układów. Najczęściej w takiej konfiguracji pracują układy termometrów DS18B20. Większość dostępnych procedur obsługi 1-wire pozwala na dołaczenie układu do jednego, ściśle określonego na etapie kompilacji wyprowadzenia. Spotkałem się z próbą zrealizowania obsługi dwóch linii 1-wire poprzez napisanie dwóch niezależnych zestawów procedur ze ściśle określonymi dwoma wyprowadzeniami. Rozwiązanie to oczywiście posiada poważną wadę - kod był zdublowany, co przyczyniło się do niepotrzebnego zużycia pamięci programu. Postanowiłem więc przygotować nieco bardziej uniwersalne oraz oszczędne procedury pozwalające na obsługę do ośmiu linii 1-wire w ramach wybranego portu mikrokontrolera AVR. Idea realizacji tych procedur jest na tyle uniwersalna, że można je przenieść na dowolny inny mikrokontroler.

Jak to działa?

Klasycznie już zmiana stanu na linii 1-wire realizowana jest poprzez modyfikację bitu (lub bitów) w rejestrze kierunku wybranego portu. Jednak do modyfikacji rejestru nie jest wykorzystywana stała wartość, jak to ma miejsce w większości procedur 1-wire, lecz dedykowana do tego celu jest specjalna zmienna, której poszczególne bity odpowiadają bitom rejestru kierunku. Każda operacja zmiany stanu bitów w rejestrze kierunku realizowana jest poprzez operację iloczynu lub sumy logicznej (w zależności czy chcemy wyzerować czy też ustawić bit w rejestrze) ze wspomnianą zmienną. Przed wywołaniem jakiejkolwiek procedury należy do zmiennej owmask zapisać odpowiednią wartość, która "uaktywnia" poszczególne kanały naszej magistrali. Najczęściej w zmiennej owmask ustawiony będzie tylko jeden bit, ale w pewnych wyjątkowych sytuacjach (zapis tych samych wartośći do kilku układów jednocześnie) wskazane jest ustawienie tylu bitów, do ilu układów ma zostać zapisana ta sama dana. W przypadku układów DS18B20 pozwoli to na jednoczesne zainicjowanie procesu pomiaru temperatury, dzięki czemu nie będzie konieczne wysyłanie tych samych komend do wszystkich układów po kolei.

Procedura opóźniająca
Podstawą działania magistrali 1-wire jest dokładne odmierzanie czasu. Przedstawiona poniżej procedura pozwala na wstrzymanie programu na okres ok owdelay*1us (dla częstotliwości pracy mikrokontrolera 4MHz). Parametr do procedury (ilość mikrosekund) należy przed wywołaniem procedury umieścić w zmiennej owdelay.

Kod: Zaznacz cały

ow_delay: nop dec owdelay brne ow_delay ret
Jednym z najczęściej występującym czasem opóźnienia jest czas 480us, tak wiec pozwoliłem sobie przygotować procedurę wstrzymującą dalsze wykonanie programu na wspomiane 480 mikrosekund.

Kod: Zaznacz cały

ow_delay480us: ldi count, 3 owd1: ldi owdelay, 160 rcall ow_delay dec count brne owd1 ret
Ustawienie stanu wysokiego na liniach 1-wire realizowane jest poprzez wyzerowanie odpowiednich bitów w rejestrze kierunku wybranego portu. Dokonywane jest to za pomocą operacji iloczynu logicznego z zanegowaną wartością zmiennej owmask.

Kod: Zaznacz cały

set_ow_lines: mov acc, owmask com acc in tmp, OWDDR and acc, tmp out OWDDR, acc ret

Ustawienie stanu niskiego na liniach 1-wire realizowanejest poprzez ustawienie odpowiednich bitów w rejestrze kierunku wybranego portu. Dokonywane jest to za pomocją operacji sumy logicznej ze zmienną owmask.

Kod: Zaznacz cały

clr_ow_lines: mov acc, owmask in tmp, OWDDR or acc, tmp out OWDDR, acc ret

Pierwsza konkretna i najważniejsza procedura 1-wire - generowanie impulsu reset.Stan wszystkich linii w momencie właściwym dla generowania przez układy impulsów obecności zwracany jest w zmiennej owdata. Pozwala to na sprawdzenie, do których wyprowadzeń podłaczone są układy.

Kod: Zaznacz cały

ow_reset: rcall clr_ow_lines rcall ow_delay480us rcall set_ow_lines ldi owdelay, 75 rcall ow_delay in owdata, OWPIN rcall ow_delay480us ret

Zapis bitu na magistralę. Bit nalezy przekazać poprzez flagę C.

Kod: Zaznacz cały

ow_write_bit: rcall clr_ow_lines ldi owdelay, 15 rcall ow_delay brcc owb1 rcall set_ow_lines owb1: ldi owdelay,100 rcall ow_delay rcall set_ow_lines ldi owdelay,200 rcall ow_delay ret
Odczyt bitu z magistrali. Bit jest zwracany poprzez flagę C.

Kod: Zaznacz cały

rcall clr_ow_lines rcall set_ow_lines ldi owdelay, 10 rcall ow_delay sec in acc, OWPIN and acc, owmask brne orb1 clc orb1: ldi owdelay, 200 rcall ow_delay ret
Zapis bajtu na magistralę. Zapisywany bajt nalezy umieścić w zmiennej owdata

Kod: Zaznacz cały

ow_write: ldi count, 8 ow1: ror owdata rcall ow_write_bit dec count brne ow1 ret
Odczyt bajtu z magistrali. Odczytywany bajt jest zwracany w zmiennej owdata.

Kod: Zaznacz cały

ow_read: ldi count, 8 or1: rcall ow_read_bit ror owdata dec count brne or1 ret
Powyższe procedury pozwalają na skomunikowanie się z układami 1-wire podłaczonymi do kilku wybranych linii portu. Przykładowy program odczytujący temperaturę z dwóch czujników DS18B20 i wystawiający całkowitą wartość na porty A i B znajduje się w załączniku.
Załączniki
owmulti.rar
(1.36KiB)Pobrany 365 razy

Wróć do „AVR/AVR32”

Kto jest online

Użytkownicy przeglądający to forum: Obecnie na forum nie ma żadnego zarejestrowanego użytkownika i 3 gości