Algorytm poszukiwania układów
w sieci 1-Wire.
Każdy z układów z interfejsem 1-Wire posiada unikatowy 64-bitowy kod identyfikacyjny.
Kod ten nosi nazwę kod ROM i może być utożsamiany z unikatowym adresem układu z
interfejsem 1-Wire. Kod ten używany jest przez układ Master do wyboru układu w sieci.
W związku z tym, że jest to kod unikatowy, to jeśli nie jest znana liczba układów Slave w
sieci, może ona zostać określona przy jego użyciu przez zastosowanie funkcji
przeszukiwania sieci. Algorytm jej działania oparty jest o zasadę przeszukiwania drzewa
binarnego. Gałęzie przeszukiwane są do momentu aż zostanie odnaleziony koniec gałęzi
lub pamięć ROM układu 1-Wire. Funkcja przeszukuje drzewo do momentu aż wszystkie
numery ROM i wszystkie zakończenia zostaną odkryte.
Algorytm rozpoczyna się od wysłania rozkazu reset. Jeśli jego przesłanie zakończy się
powodzeniem, to znaczy odpowiednio zareagują na niego układy dołączone do magistrali,
wysyłana jest 1-bajtowa komenda zwana search o kodzie 0xF0 lub 0xFC. Komenda ta
przygotowuje układy podłączone do magistrali do przeszukiwania.
Firma Dallas zaimplementowała dwa rodzaje komend przeszukujących. Najczęściej
używane jest przeszukiwanie tzw. normalne (0xF0) sprawdzające wszystkie układy
podłączone do linii. Innym rodzajem przeszukiwania jest tzw. warunkowe, które znajduje
układy będące w stanie alarmowym, np. załączone termostaty czy timery, które
sygnalizują zakończenie odmierzania czasu. Redukowany jest w ten sposób obszar
przeszukiwania do tylko tych układów, które muszą zostać z jakiś powodów odczytane
czy ustawione.
Po wysłaniu przez układ Master komendy przeszukiwania, układy Slave podłączone do
magistrali 1-Wire (wszystkie, których dotyczy komenda) odpowiadają wysyłając
jednocześnie mniej znaczący bit własnego adresu. Według standardu 1-Wire, układ
Master inicjuje przesłanie każdego bitu zapisywanego czy odczytywanego z układu Slave.
W związku ze specyfiką interfejsu, gdzie wszystkie układy podłączone są do wspólnej linii
przesyłowej i na odebraną komendę przeszukiwania odpowiadają w tym samym czasie
(jednocześnie i synchronicznie z sygnałem zegarowym wysyłanym przez układ Master),
rezultat odczytu docierający do układu Master jest iloczynem logicznym stanów wyjść
układów Slave (wired and).
Po tym jak układy Slave prześlą 1-szy bit swojego adresu, układ Master inicjuje odbiór
następnego bitu, na który układy Slave odpowiadają wysyłając ponownie 1-szy bit adresu
lecz tym razem jest to jego bit komplementarny. Następnie układ Master wysyła bit
adresu do układów Slave. Jeśli urządzenie Slave odbiera bit, który zgadza się z bitem na
pozycji adresu, pozostaje załączone i aktywne. Jeśli natomiast odebrany bit nie
odpowiada temu z adresu, urządzenie Slave przechodzi do stanu oczekiwania i nie
przesyła już żadnych danych. Stan ten trwa aż do odebrania następnego sygnału reset.
Opisywana wyżej procedura tzn. odbiór przez układ Master jednego bitu jako normalny
i komplementarny a następnie przesłanie tego bitu adresu do układu Slave (jako
normalny ), powtarzana jest dla wszystkich 63 pozostałych bitów adresu. W takiej
sytuacji urządzenie Slave wywołuje wszystkie układy dołączone do magistrali, lecz w
danym momencie, po odbiorze bitu adresu, tylko jeden z nich przejdzie do stanu
oczekiwania. Na końcu procedury znany jest adres ostatniego układu dołączonego do
magistrali. W następnych przejściach procedury uwzględniana jest inna ścieżka, dotąd
nie przeszukiwana.
Wyjaśnienia wymaga jeszcze jedna drobna nieścisłość opisu. Proszę zauważyć, że w tym
opisie bitem 1-szym nazywam najmniej znaczący bit adresu układu, czyli bit na pozycji 0,
natomiast bit 64 to bit na pozycji 63.
Jest oczywiste, że wszystkie uczestniczące w przeszukiwaniu układy mają bit o tej samej
wartości na danej jego pozycji (tabela 1). Jeśli na przeszukiwanej gałęzi nie znajduje się
Strona 1 z 18
Bit Bit Interpretacja
rzeczywisty uzupełniony
0 0 Na pozycji bitu znajdują się 0 i 1 ; to jest sprzeczność
0 1 Na pozycji bitu znajduje się 0
1 0 Na pozycji bitu znajduje się 1
1 1 Brak urządzeń na przeszukiwanej gałęzi
Tabela 1. Interpretacja bitów odebranych przez układ Master w czasie przeszukiwania
żaden układ, przeszukiwanie jest zatrzymywane i rozpoczynane jest nowe, od wysyłania
sygnału 1-Wire reset . Sytuacja, gdy na pozycji bitu umieszczone jest zarówno 0 jak i
1 , nazywana jest sprzecznością i jest kluczem do określania kierunku i gałęzi
przeszukiwania.
Opisywany algorytm wykrywa warunek sprzeczności w pierwszym przebiegu
(bit/uzupełnienie = 0/0) i na jego podstawie wybiera gałąz 0 do kontynuacji pracy. To
jest metoda przyjęta dla tego algorytmu. Możliwe jest stworzenie własnego, w którym do
kontynuacji wybrana będzie gałąz 1 . Pozycja bitu, dla której ostatnio określony został
warunek sprzeczności jest zapamiętywana dla następnych operacji wyszukiwania.
Wynik porównania pozycji przeszukiwanego Obierana gałąz przeszukiwania
bitu z pozycją ostatnio odnalezionej
sprzeczności
= Wybierz gałąz 1
< Obierz tę samą gałąz co ostatnio (od ostatnio
znalezionego adresu)
> Wybierz gałąz 0
Tabela 2. Określanie kierunku przeszukiwań
Algorytm zapamiętuje także ścieżkę ostatnich sprzeczności, które wystąpiły w obrębie
pierwszych 8 bitów adresu układu. Jest to kod rodziny układów. Jako rezultat takiego
działania, układy odkryte podczas przeszukiwania grupowane są w rodziny. Ostatnio
odkryty warunek sprzeczności w obrębie rodziny, może zostać użyty do przeszukiwania
selektywnego danej rodziny układów (np. czujników temperatury czy pamięci).
Strona 2 z 18
Opisy zmiennych:
1-Wire Reset
cmp_id_bit uzupełnienie jedynkowe bitu (w
tym przypadku to negacja); należy pamiętać o
fakcie, że do układu Master dociera iloczyn
logiczny wszystkich bitów wysyłanych przez
układy dołączone do magistrali 1-Wire
id_bit pierwszy bit odczytany podczas
Wykryto Nie
sekwencji odczytu; uwaga jak powyżej
obecność
układów?
id_bit_number pozycja bitu w adresie
(numerze ROM) układu; zmienna zmienia się od
1 do 64, podczas gdy faktyczna pozycja (waga)
bitu jest o 1 mniejsza (0..63)
Tak
LastDeviceFlag zmienna wskazująca, że
poprzednio odszukany układ był ostatnim w
danej gałęzi
Czy Tak
LastDiscrepancy indeks wskazujący na bit,
LastDeviceFlag
od którego bitu powinno się rozpocząć następne
=1?
poszukiwanie sprzeczności (określanie gałęzi
przeszukiwań)
LastFamilyDiscrepancy indeks wskazujący
Nie
na bit identyfikujący ostatnią sprzeczność
wykrytą w obrębie 8-bitowego kodu rodziny
id_bit_number = 1
układów
last_zero = 0
last_zero pozycja bitu ostatnio zapisanego 0,
dla której nie wykryto sprzeczności
ROM_NO bufor o rozmiarze 8 bajtów, który
Wyślij komendę
zawiera numer ROM (adres) ostatnio wykrytego
search (0xF0 lub 0xEC)
układu
search_direction zmienna o rozmiarze 1 bitu
wskazująca kierunek przeszukiwania drzewa;
wszystkie układy znajdujące się na kierunku
przeszukiwania są aktywne, reszta znajduje się w
stanie oczekiwania na następne przeszukiwanie
Strona 3 z 18
Pobierz id_bit i bit
komplementarny cmp_id_bit
id_bit TAK
=cmp_id_bit
=1?
NIE
id_bit TAK NIE NIE
=cmp_id_bit id_bit_number= id_bit_number>
=0? LastDiscrepancy? LastDiscrepancy?
NIE TAK TAK
search_direction = search_direction = 1 search_direction = 0
id_bit
search_direction=
id_bit_number
NIE search_ TAK last_zero =
Direction id_bit_number
=0?
id_bit_number =
search_direction
i wyślij przez interfejs NIE Czy TAK LastFamilDiscr.=
1-Wire last_zero last_zero
<9?
Zwiększ
id_bit_number o 1
NIE id_bit_ TAK LastDiscrepancy = LastDiscr. TAK Ustaw flagę
number last_zero =0? LastDeviceFlag
>64?
NIE
Strona 4 z 18
CRC8 NIE Ustal warunki początkowe:
poprawny? LastDiscrepancy=0 Ustaw wartość funkcji
LastFamilyDiscrep.=0 na FAASZ
LastDeviceFlag=0
TAK
Ustaw wartość funkcji
na PRAWDA
KONIEC
Rysunek 1. Algorytm działania funkcji wyszukiwania układów 1-Wire
Wyszukiwanie proste.
Poprzez manipulację wartościami zmiennych LastDiscrepancy, LastFamilyDiscrepancy,
LastDeviceFlag i wartością rejestru ROM_NO możliwe są do przeprowadzenia dwa
podstawowe warianty wyszukiwania układów.
Szukanie pierwszego.
Pierwszy z nich to wyszukanie pierwszego adresu urządzenia. Jest to możliwe po
ustawieniu LastDiscrepancy, LastFamilyDiscrepancy i LastDeviceFlag na wartość 0 i po
tym wywołanie funkcji poszukiwania. Rezultat może zostać odczytany z rejestru
ROM_NO. Jeśli żadne urządzenie nie jest podłączone do magistrali 1-Wire, wówczas
przeszukiwanie jest przerywane. Jeśli znaleziono jakiś układ, jego adres można pobrać
właśnie z tejże tabeli. Implementację tej funkcji można znalezć na listingu 2 pod nazwą
int one_wire_FIRST().
Szukanie następnego.
Drugi wariant to wyszukanie następnego układu, po pierwszym lub po kolejnym.
Wykorzystywany jest po wywołaniu funkcji szukaj pierwszego układu lub jako kolejne w
ciągu poleceń wyszukiwania następnych urządzeń. Rezultat działania zwracany jest w
buforze ROM_NO. Jeśli poprzednio odszukano ostatnie urządzenie, zostanie ustawiona
zmienna informująca o zakończeniu przeszukiwania a funkcja zwróci wartość FALSE.
Implementację tej funkcji można znalezć na listingu 2 pod nazwą int one_wire_NEXT().
Zaawansowane funkcje wyszukiwania.
Inne możliwości stwarza tzw. przeszukiwanie zaawansowane, dzięki któremu można się
odwołać do konkretnego układu lub grupy układów. Podobnie jak poprzednio, funkcje
wywołuje się po uprzedniej manipulacji zawartością zmiennych.
Strona 5 z 18
Weryfikacja.
Weryfikacja przeprowadza sprawdzenie, czy układ o znanym adresie podłączony jest do
magistrali 1-Wire. Można ją przeprowadzić podając adres układu w rejestrze ROM_NO
oraz ustawiając wartość zmiennych: LastDiscrepency na 0x40 (64 dziesiętnie) i
LastDeviceFlag na 0. Po opisanych nastawach należy wywołać funkcję wyszukiwania a po
jej zakończeniu należy sprawdzić zawartość ROM_NO. Jeśli bufor zawiera adres, który był
poszukiwany oznacza to, że urządzenie jest podłączone do magistrali 1-Wire.
Implementację tej funkcji można znalezć na listingu 2 pod nazwą int one_wire_VERIFY().
Wyszukiwanie w obrębie rodziny układów.
Innym rodzajem operacji jest przeszukiwanie konkretnej rodziny układów. Jak zapewne
pamiętamy z wcześniejszej lektury, każdy układ z interfejsem 1-Wire posiada własny
unikatowy 64-bitowy kod, z czego pierwsze 8 bitów określa kod rodziny układów. Kod ten
pozwala oprogramowaniu funkcjonującemu w układzie Master na orientację, czy pewne
funkcje, związane z daną rodziną układów, są dostępne czy też nie. Jeśli dana sieć
zawiera wiele różnych układów, to dobrą praktyką jest komunikacja z daną ich grupą, np.
czujnikami temperatury.
Aby odwołać się do konkretnej grupy układów, należy pierwszy bajt bufora ROM_NO
ustawić na wartość równą kodowi grupy a resztę bufora wypełnić wartością 0. Należy
również ustawić wartość zmiennej LastDiscrepancy ustawić na 0x40 (64 dziesiętnie) a
LastDeviceFlag i LastFamilyDiscrepancy na wartość 0. Jeśli funkcja poszukiwania znajdzie
układ z rodziny podanym kodzie, wówczas jego adres zostanie umieszczony w ROM_NO.
Jeśli natomiast brak jest układu z pożądanej grupy, to ROM_NO będzie zawierać adres
pierwszego znalezionego układu. W związku z tym konieczne jest sprawdzenie wartości
1-go bajtu ROM_NO po zakończeniu pracy funkcji. Implementację tej funkcji można
znalezć na listingu 2 pod nazwą void one_wire_TSETUP(byte family_code).
Pomijanie grupy układów.
Inną dostępną operacją jest można by powiedzieć odwrotna do powyżej opisanej
funkcja pomijania danej rodziny układów. Polega ona na pomijaniu rodziny układów, do
której należy poprzednio odszukany układ. Można w ten sposób znacznie przyspieszyć
wyszukiwanie, ograniczając się do konkretnej grupy układów, na której w danym
momencie nam zależy, pomijając wszystkie pozostałe. Funkcja może być wywołana
wyłącznie po przeprowadzonym poprzednio szukaniu, np. pierwszego układu. Aby ją
uruchomić należy wartość LastFamilyDiscrepancy skopiować do zmiennej LastDiscrepancy
i wywołać wyszukiwanie. Następne szukanie odnajdzie pierwszy z układów po podanym
kodzie rodziny. Jeśli dana rodzina należała do ostatniej grupy układów, to wówczas
zmienna LastDeviceFlag przyjmie wartość prawda . Implementację tej funkcji można
znalezć na listingu 2 pod nazwą void one_wire_FAMILYSKIP().
Zmienna Last- LastFamily LastDeviceFlag ROM_NO
Discrepancy Discrepancy
Opis funkcji
Szukaj pierwszego 0 0 0 adres układu
Szukaj następnego nie zmieniać nie zmieniać nie zmieniać adres układu
Weryfikacja 0x40 bez znaczenia 0 należy wpisać adres
poszukiwanego układu a następnie
sprawdzić rezultat
Szukaj układów z 0x40 0 0 należy ustawić 1-szy bajt na kod
danej rodziny rodziny układów a następnie sprawdzić
rezultat
Omiń układy z pobierz z 0 0 nie zmieniać
danej rodziny ostatniego
wyszukiwania
Tabela 3. Podsumowanie opisu funkcji wyszukujących 1-Wire.
Strona 6 z 18
Jako ciekawostkę warto wspomnieć, że układ DS2480B posiada zaimplementowany
sprzętowo niemal identyczny algorytm. Zwalnia to użytkownika od konieczności
powtórnej jego implementacji i oszczędza czas konieczny na zbudowanie urządzenia i
oczywiście co w dzisiejszych czasach nie ma już tak wielkiego znaczenia pamięć
programu mikrokontrolera.
Jacek Bogusz
szukaj szukaj szukaj
pierwszego następnego następnego
Szukaj pierwszego:
LastDiscrepancy = LastDeviceFlag = 0
sygnalizacja 1-Wire reset
czekaj na odpowiedz układów, jeśli brak odpowiedzi to koniec pracy
id_bit_number = 1, last_zero = 0
wyślij komendę przeszukiwania układów (0xF0)
odczytaj pierwszy bit id_bit
[urządzenie (A = 1)] and [urządzenie (B = 0)] and [urządzenie (C = 1)] = 0
odczytaj bit komplementarny cmp_id_bit
[urządzenie (A = 0)] and [urządzenie (B = 1)] and [urządzenie (C = 0)] = 0
jeśli id_bit_number>LastDescrepancy to search_direction=0, last_zero=1
wyślij na magistralę 1-Wire bit search_direction równy 0 (urządzenia A i C przejdą w stan
oczekiwania na sygnał reset)
zwiększ id_bit_number (zmienna przyjmie on wartość 2)
odczytaj drugi bit id_bit (będzie on miał wartość 0, bo odpowie urządzenie B)
czytaj drugi bit komplementarny cmp_id_bit (będzie on miał wartość 1 z powodu jak wyżej)
bit i bit komplementarny mają różną wartość: search_direction = id_bit
wyślij na magistralę 1-Wire search_direction równy 0, urządzenie B jest określane przez
zawartość ROM_NO i jest wybrane (aktywne)
LastDescrepancy = last_zero
Szukaj następnego:
sygnalizacja 1-Wire reset
czekaj na odpowiedz układów, jeśli brak odpowiedzi to koniec pracy
id_bit_number = 1, last_zero = 0
wyślij komendę przeszukiwania układów (0xF0)
odczytaj pierwszy bit id_bit
[urządzenie (A = 1)] and [urządzenie (B = 0)] and [urządzenie (C = 1)] = 0
odczytaj bit komplementarny cmp_id_bit
[urządzenie (A = 0)] and [urządzenie (B = 1)] and [urządzenie (C = 0)] = 0
ponieważ id_bit_number = LastDescrepancy to zmiennej search_direction nadaj wartość 1
wyślij na magistralę 1-Wire bit search_direction równy 1 (urządzenie B przejdzie w stan
spoczynkowy)
zwiększ id_bit_number (przyjmie on wartość 2)
odczytaj drugi bit id_bit (będzie on miał wartość 0, bo [urządzenie (A = 0) and [urządzenie (C =
1)] = 0)
Strona 7 z 18
czytaj drugi bit komplementarny cmp_id_bit (będzie on miał wartość 0, bo [urządzenie (A = 1)
and [urządzenie (C = 0)] = 0)
ponieważ id_bit_number > LastDescrepancy, to search_direction = 0 i last_zero = 2
wyślij na magistralę 1-Wire search_direction równy 0, urządzenie A jest określane przez
zawartość ROM_NO i jest wybrane (aktywne), urządzenie C przejdzie w stan spoczynkowy
LastDescrepancy = last_zero
Szukaj następnego:
sygnalizacja 1-Wire reset
czekaj na odpowiedz układów, jeśli brak odpowiedzi to koniec pracy
id_bit_number = 1, last_zero = 0
wyślij komendę przeszukiwania układów (0xF0)
odczytaj pierwszy bit id_bit
[urządzenie (A = 1)] and [urządzenie (B = 0)] and [urządzenie (C = 1)] = 0
odczytaj bit komplementarny cmp_id_bit
[urządzenie (A = 0)] and [urządzenie (B = 1)] and [urządzenie (C = 0)] = 0
ponieważ id_bit_number < LastDescrepancy to search_direction = ROM_NO = 1
wyślij na magistralę 1-Wire bit search_direction równy 1 (urządzenie B przejdzie w stan
spoczynkowy)
zwiększ id_bit_number (przyjmie on wartość 2)
odczytaj drugi bit id_bit (będzie on miał wartość 0, bo [urządzenie (A = 0) and [urządzenie (C =
1)] = 0)
czytaj drugi bit komplementarny cmp_id_bit (będzie on miał wartość 0, bo [urządzenie (A = 1)
and [urządzenie (C = 0)] = 0)
ponieważ id_bit_number = LastDescrepancy, to search_direction = 1
wyślij na magistralę 1-Wire search_direction równy 1, urządzenie C jest określane przez
zawartość ROM_NO i jest wybrane (aktywne), urządzenie A przejdzie w stan spoczynkowy
LastDescrepancy = last_zero, które jest równe 0 tak więc LastDeviceFlag = prawda
Szukaj następnego:
zmienna LastDeviceFlag ma wartość prawda , więc koniec pracy
LastDiscrepancy = LastDeviceFlag = 0
Rysunek 2. Schemat i pseudokod funkcjonowania opisywanego algorytmu dla adresu 2-
bitowego.
Strona 8 z 18
/*************************************************
Na podstawie AN187 firmy MAXIM-DALLAS
2004/04 Jacek Bogusz
kompilator RC-51
*************************************************/
#pragma SMALL
#include
#include
//************* definicje stałych dla preprocesora ********************
#define FALSE 0
#define TRUE 1
#define byte unsigned char
#define XTAL 110592 //definicja rezonatora (8..25MHz!)
#define nop() ACC++ //opóznienie, 1 cykl maszynowy
sbit one_wire_IO = P1^0; //definicja podłączenia linii portu 1W
//****************** deklaracje metod i funkcji ***********************
//wyszukanie pierwszego układu na magistrali 1-Wire
int one_wire_FIRST();
//wyszukanie następnego układu
int one_wire_NEXT();
//weryfikacja,czy układ jest dołączony do magistrali
int one_wire_VERIFY();
//wyszukiwanie układów w konkretnej grupie
void one_wire_TSETUP(byte family_code);
//omijanie grupy układów
void one_wire_FAMILYSKIP();
//wysłanie sygnału reset na magistralę 1-Wire
int one_wire_RESET();
//wysłanie bajtu na magistralę 1-Wire
void one_wire_WRBYTE(byte byte_value);
//wysłanie bitu na magistralę 1-Wire
void one_wire_WRBIT(bit bit_value);
//odczyt bitu z magistrali 1-Wire
byte one_wire_RDBIT();
Strona 9 z 18
//ogólna funkcja wyszukiwania
int one_wire_SEARCH();
//wyliczenie sumy kontrolnej odebranych bajtów
byte docrc8(byte value);
//************************ zmienne globalne ***************************
//adres odnalezionego układu
byte ROM_NO[8];
//ostatnio odnaleziona sprzeczność
int LastDiscrepancy;
//ostatnio odnaleziona sprzeczność w obrębie 8-bitów rodziny układów
int LastFamilyDiscrepancy;
//flaga sygnalizująca, że układ jest ostatnim z danej grupy lub dołączonych układów
int LastDeviceFlag;
//suma kontrolna CRC8
byte crc8;
//--------------------------------------------------------------------------
// Odnajduje "pierwszy" układ na magistrali 1-Wire
// Zwraca TRUE, jeśli odnaleziono układ (adres zawarty w ROM_NO)
// Zwraca FALSE, jeśli nie ma układu
int one_wire_FIRST()
{
//ustalenie warunków początkowych
LastDiscrepancy = LastFamilyDiscrepancy = 0;
LastDeviceFlag = FALSE;
return (one_wire_SEARCH());
}
//--------------------------------------------------------------------------
// Odnajduje "następny" układ na magistrali 1-Wire
// Zwraca TRUE, jeśli odnaleziono układ (adres zawarty w ROM_NO)
// Zwraca FALSE, jeśli nie ma układu
int one_wire_NEXT()
{
//ustalenie war.początkowych polega na nie zmienianiu poprzedniego stanu
return one_wire_SEARCH();
}
Strona 10 z 18
//--------------------------------------------------------------------------
//Ogólna funkcja wyszukiwania; podstawowa implementacja algorytmu
// Zwraca TRUE, jeśli odnaleziono układ (adres zawarty w ROM_NO)
// Zwraca FALSE, jeśli nie ma układu; koniec przeszukiwania
int one_wire_SEARCH()
{
int id_bit_number;
int last_zero, rom_byte_number, search_result;
int id_bit, cmp_id_bit;
byte rom_byte_mask, search_direction;
//inicjalizacja zmiennych
id_bit_number = 1;
last_zero = 0;
rom_byte_number = 0;
rom_byte_mask = 1;
search_result = 0;
crc8 = 0;
//jeśli poprzednie wywołania nie odszukało ostatniego układu
if (!LastDeviceFlag)
{
//1-Wire reset
if (!one_wire_RESET())
{
//inicjalizacja zmiennych
LastDiscrepancy = LastFamilyDiscrepancy = 0;
LastDeviceFlag = FALSE;
return FALSE;
}
//wysłanie komendy "szukaj"
one_wire_WRBYTE(0xF0);
//pętla, w której przeprowadzane jest szukanie
do {
//odczytaj bit i bit komplementarny
id_bit = one_wire_RDBIT();
cmp_id_bit = one_wire_RDBIT();
//sprawdz warunek różnych wartości bitu i bitu komplementarnego
if ((id_bit == 1) && (cmp_id_bit == 1)) break; else
{
//bit adresu 0 lub 1 dla wszystkich dołączonych układów
if (id_bit != cmp_id_bit) search_direction = id_bit;
Strona 11 z 18
else
{
if (id_bit_number < LastDiscrepancy)
search_direction = ((ROM_NO[rom_byte_number] & rom_byte_mask) > 0);
else search_direction = (id_bit_number == LastDiscrepancy);
if (search_direction == 0)
{
last_zero = id_bit_number;
//sprawdz, czy to ostatni warunek sprzeczny w obrębie rodziny układów
if (last_zero < 9)
LastFamilyDiscrepancy = last_zero;
}
}
//ustaw lub wyzeruj bit w zmiennej rom_byte_number
//za pomocą maski rom_byte_mask
if (search_direction == 1)
ROM_NO[rom_byte_number] |= rom_byte_mask; else ROM_NO[rom_byte_number] &= ~rom_byte_mask;
//wyślij bit kierunku poszukiwania
one_wire_WRBIT(search_direction & 0x01);
//zwiększ licznik id_bit_number i przesuń w lewo maskę rom_byte_mask
id_bit_number++;
rom_byte_mask <<= 1;
//jeśli maska jest 0, to wez nowy adres rom_byte_number kasuj maskę
if (rom_byte_mask == 0)
{
//wylicz CRC8
docrc8(ROM_NO[rom_byte_number]);
rom_byte_number++;
rom_byte_mask = 1;
}
}
//wykonaj dla wszystkich bajtów adresu
}while(rom_byte_number < 8);
//jeśli poszukiwanie zakończyło się sukcesem
if (!((id_bit_number < 65) || (crc8 != 0)))
{
//ustaw zmienne LastDiscrepancy, LastDeviceFlag, search_result
LastDiscrepancy = last_zero;
//sprawdz, czy to ostatni układ
if (LastDiscrepancy == 0)
Strona 12 z 18
LastDeviceFlag = TRUE;
search_result = TRUE;
}
}
//jeśli nie znaleziono żadnego układu
if (!search_result || !ROM_NO[0])
{
LastDiscrepancy = 0;
LastDeviceFlag = FALSE;
LastFamilyDiscrepancy = 0;
search_result = FALSE;
}
return search_result;
}
//--------------------------------------------------------------------------
// Weryfikuje,czy urządzenie od podanym adresie jest dołączone do 1-Wire
// Zwraca TRUE, jeśli tak
int one_wire_VERIFY()
{
byte rom_backup[8];
int i,rslt,ld_backup,ldf_backup,lfd_backup;
//przechowaj kopię stanu aktualnego
for (i = 0; i < 8; i++) rom_backup[i] = ROM_NO[i];
ld_backup = LastDiscrepancy;
ldf_backup = LastDeviceFlag;
lfd_backup = LastFamilyDiscrepancy;
//ustaw procedurę wyszukiwania
LastDiscrepancy = 64;
LastDeviceFlag = FALSE;
if (one_wire_SEARCH())
{
//sprawdz czy znaleziono ten sam układ
rslt = TRUE;
for (i = 0; i < 8; i++)
{
if (rom_backup[i] != ROM_NO[i])
{
rslt = FALSE;
break;
Strona 13 z 18
}
}
} else rslt = FALSE;
//odtworzenie stanu początkowego
for (i = 0; i < 8; i++) ROM_NO[i] = rom_backup[i];
LastDiscrepancy = ld_backup;
LastDeviceFlag = ldf_backup;
LastFamilyDiscrepancy = lfd_backup;
//zwróć rezultat weryfikacji
return rslt;
}
//--------------------------------------------------------------------------
// Ustawienie warunków dla wyszukiwania układów w rodzinie, po tym można
// uruchomić funkcję "szukaj następnego" (one_wire_NEXT)
void one_wire_TSETUP(byte family_code)
{
int i;
ROM_NO[0] = family_code;
for (i = 1; i < 8; i++) ROM_NO[i] = 0;
LastDiscrepancy = 64;
LastFamilyDiscrepancy = 0;
LastDeviceFlag = FALSE;
}
//--------------------------------------------------------------------------
// Ustawienie warunków do pomijania przy wyszukiwaniu danej rodziny układów
// dla funkcji one_wire_NEXT().
void one_wire_FAMILYSKIP()
{
LastDiscrepancy = LastFamilyDiscrepancy;
LastFamilyDiscrepancy = 0;
if (LastDiscrepancy == 0) LastDeviceFlag = TRUE;
}
//--------------------------------------------------------------------------
// Wysłanie sygnału reset i sprawdzenie obecności układów na magistrali;
// zwracane jest TRUE, jeśli układy są obecne
Strona 14 z 18
int one_wire_RESET()
{
byte delay;
bit err;
//pętla opóznienia 480 < t < 960 cykli
delay = (byte)(XTAL/12e6*480/4);
//pętle opózniające służą do wytworzenia tzw. time slots, których dokładny opis
//można znalezć w opisie standardu 1-Wire
do
{
one_wire_IO = 0;
nop();
} while(--delay);
//pętla opóznienia 60 < t < 75 cm.
delay = (byte)( XTAL / 12e6 * 66 / 2 );
do
{
one_wire_IO = 1;
}while(--delay);
//stan niski oznacza, że urządzenie(a) 1W jest(są) podłączone
err = one_wire_IO;
//opóznienie 480 < t
delay = (byte)(XTAL/12e6*(480-66)/4);
do {
nop();
nop();
}while(--delay);
err = one_wire_IO;
//stan niski linii portu 1W oznacza błąd
return (!err);
}
//--------------------------------------------------------------------------
// Przesłanie lub odczyt bitu przez linię 1W
bit one_wire_bit_io(bit b)
{
byte delay;
delay = (byte)(XTAL/12e6*15/2-2); //15 > t
Strona 15 z 18
one_wire_IO = 0; //1
one_wire_IO = b; //3
while(--delay); //3 + delay * 2
b = one_wire_IO;
delay = (byte)(XTAL/12e6*45/2); //60 < t
while(--delay);
one_wire_IO = 1;
return b;
}
//--------------------------------------------------------------------------
// Przesłanie bajtu przez magistralę 1-Wire
void one_wire_WRBYTE(byte byte_value)
{
byte bit_counter = 8;
do
{
byte_value = byte_value >> 1 | (one_wire_bit_io(byte_value & 0x01) ? 0x80 : 0);
}while(--bit_counter);
}
//--------------------------------------------------------------------------
// Przesłanie pojedynczego bitu przez magistralę 1-Wire
void one_wire_WRBIT(bit bit_value)
{
one_wire_bit_io(bit_value);
}
//--------------------------------------------------------------------------
// Odczyt pojedynczego bitu z magistrali 1-Wire
byte one_wire_RDBIT()
{
return (one_wire_bit_io(1));
}
//--------------------------------------------------------------------------
// Tablica wartości do wyznaczenia sumy kontrolnej CRC8
Strona 16 z 18
code byte dscrc_table[] = {
0, 94,188,226, 97, 63,221,131,194,156,126, 32,163,253, 31, 65,
157,195, 33,127,252,162, 64, 30, 95, 1,227,189, 62, 96,130,220,
35,125,159,193, 66, 28,254,160,225,191, 93, 3,128,222, 60, 98,
190,224, 2, 92,223,129, 99, 61,124, 34,192,158, 29, 67,161,255,
70, 24,250,164, 39,121,155,197,132,218, 56,102,229,187, 89, 7,
219,133,103, 57,186,228, 6, 88, 25, 71,165,251,120, 38,196,154,
101, 59,217,135, 4, 90,184,230,167,249, 27, 69,198,152,122, 36,
248,166, 68, 26,153,199, 37,123, 58,100,134,216, 91, 5,231,185,
140,210, 48,110,237,179, 81, 15, 78, 16,242,172, 47,113,147,205,
17, 79,173,243,112, 46,204,146,211,141,111, 49,178,236, 14, 80,
175,241, 19, 77,206,144,114, 44,109, 51,209,143, 12, 82,176,238,
50,108,142,208, 83, 13,239,177,240,174, 76, 18,145,207, 45,115,
202,148,118, 40,171,245, 23, 73, 8, 86,180,234,105, 55,213,139,
87, 9,235,181, 54,104,138,212,149,203, 41,119,244,170, 72, 22,
233,183, 85, 11,136,214, 52,106, 43,117,151,201, 74, 20,246,168,
116, 42,200,150, 21, 75,169,247,182,232, 10, 84,215,137,107, 53};
//--------------------------------------------------------------------------
// Wyliczenie sumy kontrolnej CRC8
byte docrc8(byte value)
{
crc8 = dscrc_table[crc8 ^ value];
return crc8;
}
//--------------------------------------------------------------------------
// Program główny, demonstracja sposobu użycia funkcji
void main()
{
int rslt,i,cnt;
//wyszukiwanie wszystkich układów 1-Wire
printf("\nSZUKAM WSZYSTKICH\n");
cnt = 0;
rslt = one_wire_FIRST();
while (rslt)
{
//wypisanie odnalezionego adresu układu
for (i = 7; i >= 0; i--)
Strona 17 z 18
printf("%02X", ROM_NO[i]);
printf(" %d\n",++cnt);
rslt = one_wire_NEXT();
}
//odnalezienie układów wyłącznie z rodziny 0x1A
printf("\nSZUKAM RODZINY '0x1A'\n");
cnt = 0;
one_wire_TSETUP(0x1A);
while (one_wire_NEXT())
{
//weryfikacja odnalezionych układów
if (ROM_NO[0] != 0x1A)
break;
//wypisanie odnalezionych adresów układów
for (i = 7; i >= 0; i--)
printf("%02X", ROM_NO[i]);
printf(" %d\n",++cnt);
}
//odnalezienie wszystkich za wyjątkiem rodzin o kodach 0x04, 0x1A, 0x23, and 0x01
printf("\nSZUKAM WSZYSTKICH Z WYJATKIEM: 0x10, 0x04, 0x0A, 0x1A, 0x23, 0x01\n");
cnt = 0;
rslt = one_wire_FIRST();
while (rslt)
{
//weryfikacja
if ((ROM_NO[0] == 0x04) || (ROM_NO[0] == 0x1A) ||
(ROM_NO[0] == 0x01) || (ROM_NO[0] == 0x23) ||
(ROM_NO[0] == 0x0A) || (ROM_NO[0] == 0x10))
one_wire_FAMILYSKIP();
else
{
//wypisanie
for (i = 7; i >= 0; i--)
printf("%02X", ROM_NO[i]);
printf(" %d\n",++cnt);
}
rslt = one_wire_NEXT();
}
}
Listing 2. Implementacja funkcji wyszukiwania układów podłączonych do magistrali 1-Wire w języku C.
Strona 18 z 18
Wyszukiwarka
Podobne podstrony:
Poszukiwanie cyklu Eulera algorytm Fleury`ego
Algorytmy uczenia sieci jednokierunkowych
Sieci komputerowe wyklady dr Furtak
Ogolne zasady proj sieci wod kan
sieci
Sieci elektroenergetzcyne
Analizowanie działania układów mikroprocesorowych
punkty sieci po tyczMx
Sieci telekomunikacyjne Łączność bezprzewodowa
monter sieci i urzadzen telekomunikacyjnychr5[02] z2 01 n
analiza algorytmow
2009 12 Metaprogramowanie algorytmy wykonywane w czasie kompilacji [Programowanie C C ]
6 6 Zagadnienie transportowe algorytm transportowy przykład 2
ZWYCIĘSTWO W SIECI
więcej podobnych podstron