Algorytm poszukiwania ukladow w Nieznany

background image





Strona 1 z 18

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ę

background image





Strona 2 z 18

Bit

rzeczywisty

Bit

uzupełniony

Interpretacja

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łąź „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łąź „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

bitu z pozycją ostatnio odnalezionej

sprzeczności

Obierana gałąź przeszukiwania

=

Wybierz gałąź „1”

<

Obierz tę samą gałąź co ostatnio (od ostatnio
znalezionego adresu)

>

Wybierz gałąź „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).

background image





Strona 3 z 18




1-Wire Reset

Wykryto Nie

obecność

układów?


Tak


Czy Tak

LastDeviceFlag

=1?

Nie

id_bit_number = 1

last_zero = 0

Wyślij komendę

„search” (0xF0 lub 0xEC)

Opisy zmiennych:

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

sekwencji odczytu; uwaga jak powyżej

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)

LastDeviceFlag – zmienna wskazująca, że

poprzednio odszukany układ był ostatnim w

danej gałęzi

LastDiscrepancy – indeks wskazujący na bit,

od którego bitu powinno się rozpocząć następne

poszukiwanie sprzeczności (określanie gałęzi

przeszukiwań)

LastFamilyDiscrepancy – indeks wskazujący

na bit identyfikujący ostatnią sprzeczność

wykrytą w obrębie 8-bitowego kodu rodziny

układów

last_zero – pozycja bitu ostatnio zapisanego 0,

dla której nie wykryto sprzeczności

ROM_NO – bufor o rozmiarze 8 bajtów, który

zawiera numer ROM (adres) ostatnio wykrytego

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

background image





Strona 4 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


background image





Strona 5 z 18









CRC8

NIE

Ustal warunki początkowe:

poprawny?

LastDiscrepancy=0

Ustaw wartość funkcji

LastFamilyDiscrep.=0

na FAŁSZ

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 znaleźć 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 znaleźć 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.

background image





Strona 6 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 znaleźć 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
znaleźć 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
znaleźć na listingu 2 pod nazwą void one_wire_FAMILYSKIP().

Zmienna

Opis funkcji

Last-

Discrepancy

LastFamily

Discrepancy

LastDeviceFlag

ROM_NO

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

danej rodziny

0x40

0

0

należy ustawić 1-szy bajt na kod

rodziny układów a następnie sprawdzić

rezultat

Omiń układy z

danej rodziny

pobierz z

ostatniego

wyszukiwania

0

0

nie zmieniać

Tabela 3. Podsumowanie opisu funkcji wyszukujących 1-Wire.

background image





Strona 7 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 pierwszego:

LastDiscrepancy = LastDeviceFlag = 0

sygnalizacja 1-Wire reset

czekaj na odpowiedź 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 odpowiedź 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)

szukaj

pierwszego

szukaj

następnego

szukaj

następnego

background image





Strona 8 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 odpowiedź 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.

background image





Strona 9 z 18

/*************************************************
Na podstawie AN187 firmy MAXIM-DALLAS
2004/04 Jacek Bogusz

kompilator RC-51
*************************************************/


#pragma SMALL
#include <reg51.h>
#include <stdio.h>

//************* 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óźnienie, 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();

background image





Strona 10 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();

}

background image





Strona 11 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();

//sprawdź 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;

background image





Strona 12 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;

//sprawdź, 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 weź 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;

//sprawdź, czy to ostatni układ

if (LastDiscrepancy == 0)

background image





Strona 13 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())

{

//sprawdź czy znaleziono ten sam układ

rslt = TRUE;

for (i = 0; i < 8; i++)

{

if (rom_backup[i] != ROM_NO[i])

{

rslt = FALSE;

break;

background image





Strona 14 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

background image





Strona 15 z 18

int one_wire_RESET()
{

byte delay;

bit err;

//pętla opóźnienia 480 < t < 960 cykli

delay = (byte)(XTAL/12e6*480/4);

//pętle opóźniające służą do wytworzenia tzw. time slots, których dokładny opis
//można znaleźć w opisie standardu 1-Wire

do

{

one_wire_IO = 0;

nop();

} while(--delay);

//pętla opóźnienia 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óźnienie 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

background image





Strona 16 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

background image





Strona 17 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--)

background image





Strona 18 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.


Wyszukiwarka

Podobne podstrony:
ALGORYTM id 57461 Nieznany
Algorytm obliczania parametrow Nieznany
Algorytmy Genetyczne A Logika R Nieznany (2)
algorytmika id 57568 Nieznany (2)
ALGORYTM SLEDZENIA TRAJEKTORII Nieznany (2)
Analizowanie dzialania ukladow Nieznany
4 Klient algorytmy id 37672 Nieznany (2)
3 Okreslanie wlasciwosci uklado Nieznany
algorytmy 5 id 57587 Nieznany (2)
binarne drzewa poszukiwan1 id 8 Nieznany (2)
Algorytmy immunologiczne S T Wi Nieznany (2)
algorytmy numeryczne w delphi Nieznany (2)
Algorytmy 2 id 57578 Nieznany
2 znl algorytm2010'11id 21184 Nieznany (2)
Algorytmy poszukiwania i porzadkowania elementy jezyka programowania prezentacja 3
3 algorytmy id 33513 Nieznany (2)
Algorytmy I Struktury Danych (W Nieznany (2)
Ogloszenie o poszukiwaniu praco Nieznany
Algorytmy1 id 57858 Nieznany

więcej podobnych podstron