1 Wire SEARCH ROM

Pozostałe układy mikrokontrolerów, układy peryferyjne i inne, nie mieszczące się w powyższych kategoriach.
StaryAnoda

1 Wire SEARCH ROM

Postautor: StaryAnoda » sobota 29 paź 2016, 21:11

Cześć

Piszę funkcję wyświetlającą mi wszystkie numery seryjne urządzeń podłączonych pod 1 Wire. Mam problem pewnie błachy, jeżeli ktoś wie co jest nie tak niech piszę. Zaznaczam, że funkcję do wysyłania czy odbierania danych są sprawdzone i działają poprawnie. I tak do magistrali mam podłączone dwa czujniki DS18B20. Na podstawie algorytmu który jest w fazie czysto testowej próbuję odczytać numery tych dwóch czujników. W momencie krytycznym czyli tym w którym wybieram czy chcę czujnik numer 1 czy 0 (Czyli wtedy kiedy otrzymuję odebrane dwa bity o wartości 0 0) wszystko działa po zmienieniu parametru Bit odczytuję poprawnie numer czujnika. Problem następuję gdy chcę zrobić to automatycznie czyli aby od razu adresy obu czujników były wyświetlanie. Niestety nie mogę tego dokonać drugi czujnik ma błędy w swoim numerze seryjnym

Tutaj mój kod:

Kod: Zaznacz cały

   while(1)
   {
      Search();

      for(i = 1; i <= 8; i++)
      {
         lcd_locate(0,0);
         lcd_str("                     ");
         lcd_locate(0,0);
         lcd_int(buf[i-1]);
         _delay_ms(5000);
      }
      _delay_ms(1000);
      lcd_locate(1,0);
      lcd_str("2");
   }
}


void Search(void)
{
   uint8_t bitA = 0, bitB = 0;
   uint8_t currentBit = 0;
   uint8_t Bit = 0;


   Reset = One_Wire_Reset_Pulse();
   One_Wire_Send_Byte(0xF0);

   for(currentBit = 0; currentBit < 64; currentBit++)
   {
      bitA = One_Wire_Read_Bit();
      bitB = One_Wire_Read_Bit();

      if(bitA == 1 && bitB == 0) Bit = 2;
      if(bitA == 0 && bitB == 1) Bit = 1;
      
      //if((bitA == 0)&& (bitB == 0))Bit = 1; Kiedy tak zrobię to działa ale wyświetla jeden numer seryjny
      //if((bitA == 0)&& (bitB == 0))Bit = 2; Kiedy tak zrobię to działa ale wyświetla jeden numer seryjny

      if((bitA == 0)&& (bitB == 0)) -- To jest mój niby automat który powinien kontrolować i odpowiadać za wysyłanie dwóch numerów
      {
         Bit = 1;
         if(Bit_numer == currentBit)
         {
            Bit = 2;
            Bit_numer = 100;
         }
         else
         {
            Bit_numer = currentBit;
         }
      }

      if((currentBit >= 0 )&&(currentBit <= 7))
      {
         if(Bit == 2) (buf[0] |= 0x01 << (currentBit));
      }
      if((currentBit >= 8 )&&(currentBit <= 15))
      {
         if(Bit == 2) (buf[1] |= 0x01 << (currentBit -8));
      }
      if((currentBit >= 16 )&&(currentBit <= 23))
      {
         if(Bit == 2) (buf[2] |= 0x01 << (currentBit -16));
      }
      if((currentBit >= 24 )&&(currentBit <= 31))
      {
         if(Bit == 2) (buf[3] |= 0x01 << (currentBit -24));
      }
      if((currentBit >= 32 )&&(currentBit <= 39))
      {
         if(Bit == 2) (buf[4] |= 0x01 << (currentBit -32));
      }
      if((currentBit >= 40 )&&(currentBit <= 47 ))
      {
         if(Bit == 2) (buf[5] |= 0x01 << (currentBit -40));
      }
      if((currentBit >= 48 )&&(currentBit <= 55 ))
      {
         if(Bit == 2) (buf[6] |= 0x01 << (currentBit -48));
      }
      if((currentBit >= 56 )&&(currentBit <= 63 ))
      {
         if(Bit == 2) (buf[7] |= 0x01 << (currentBit -56));
      }

      switch (Bit)
      {
      case 1:
         One_Wire_Send_Bit(0);
         break;
      case 2:
         One_Wire_Send_Bit(1);
         break;
      }
   }
}

StaryAnoda

Re: 1 Wire SEARCH ROM

Postautor: StaryAnoda » sobota 29 paź 2016, 21:45

Ok problem rozwiązany po pierwszym wypełnieniu tablicy i jej wyświetleniu nie kasowałem jej zawartości przez co wynik nie był zgodny.

Awatar użytkownika
Antystatyczny
Geek
Geek
Posty: 1177
Rejestracja: czwartek 03 wrz 2015, 22:02

Re: 1 Wire SEARCH ROM

Postautor: Antystatyczny » sobota 29 paź 2016, 22:02

A co do zerowania tablic...

Można tak:

Kod: Zaznacz cały


uint8_t buf[8];
uint8_t idx;

for(idx = 0; idx < sizeof(buf); ++idx)
{
   buf[idx] = 0;
}


Można też tak:

Kod: Zaznacz cały

uint8_t buf[8];
uint8_t idx = sizeof(buf);

do
{
   idx--;
   buf[idx] = 0;
}
while (idx);


Albo tak:

Kod: Zaznacz cały

uint8_t buf[8];
/* należy zainkludować string.h  */
memset(buf, 0, sizeof(buf));


Można też stworzyć unię i za jej pomocą zerować tablicę, ale nie wiem, czy ma to sens w tym przypadku. Chyba najprościej będzie zastosować memset.
"The true sign of intelligence is not knowledge but imagination" Albert Einstein.

StaryAnoda

Re: 1 Wire SEARCH ROM

Postautor: StaryAnoda » niedziela 30 paź 2016, 16:00

Cześć !!!

Czy jest mi ktoś w stanie podpowiedzieć w jaki sposób zrealizować odczyt dowolnej ilości czujników podłączonych (chodzi o numery seryjne poszczególnych urządzeń) do 1 Wire. Podana funkcja wyświetla numery seryjne tylko dwóch urządzeń.

Kod: Zaznacz cały

while(1)
   {
      memset(buf, 0, sizeof(buf));

      Search();

      for(i = 1; i <= 8; i++)
      {
         lcd_locate(0,0);
         lcd_str("                     ");
         lcd_locate(0,0);
         lcd_int(buf[i-1]);
         _delay_ms(3000);
      }
   }
}



void Search(void)
{
   uint8_t bitA = 0, bitB = 0;
   uint8_t currentBit = 0;
   uint8_t Bit = 0;


   Reset = One_Wire_Reset_Pulse();
   One_Wire_Send_Byte(0xF0);

   for(currentBit = 0; currentBit < 64; currentBit++)
   {
      bitA = One_Wire_Read_Bit();
      bitB = One_Wire_Read_Bit();

      if(bitA == 1 && bitB == 0) Bit = 2;
      if(bitA == 0 && bitB == 1) Bit = 1;

      if((bitA == 0)&& (bitB == 0))
      {
         Bit = 1;
         if(Bit_numer == currentBit)
         {
            Bit = 2;
            Bit_numer = 100;
         }
         else
         {
            Bit_numer = currentBit;
         }
      }

      if((currentBit >= 0 )&&(currentBit <= 7))
      {
         if(Bit == 2) (buf[0] |= 0x01 << (currentBit));
      }
      if((currentBit >= 8 )&&(currentBit <= 15))
      {
         if(Bit == 2) (buf[1] |= 0x01 << (currentBit -8));
      }
      if((currentBit >= 16 )&&(currentBit <= 23))
      {
         if(Bit == 2) (buf[2] |= 0x01 << (currentBit -16));
      }
      if((currentBit >= 24 )&&(currentBit <= 31))
      {
         if(Bit == 2) (buf[3] |= 0x01 << (currentBit -24));
      }
      if((currentBit >= 32 )&&(currentBit <= 39))
      {
         if(Bit == 2) (buf[4] |= 0x01 << (currentBit -32));
      }
      if((currentBit >= 40 )&&(currentBit <= 47 ))
      {
         if(Bit == 2) (buf[5] |= 0x01 << (currentBit -40));
      }
      if((currentBit >= 48 )&&(currentBit <= 55 ))
      {
         if(Bit == 2) (buf[6] |= 0x01 << (currentBit -48));
      }
      if((currentBit >= 56 )&&(currentBit <= 63 ))
      {
         if(Bit == 2) (buf[7] |= 0x01 << (currentBit -56));
      }

      switch (Bit)
      {
      case 1:
         One_Wire_Send_Bit(0);
         break;
      case 2:
         One_Wire_Send_Bit(1);
         break;
      }
   }
}

StaryAnoda

Re: 1 Wire SEARCH ROM

Postautor: StaryAnoda » niedziela 30 paź 2016, 21:23

Ok więc wytłumaczę mój kod i moje rozumowanie.

Wykonuję reset wszystkich urządzeń będących na magistrali 1 Wire.
Wysyłam komendę SEARCH ROM o wartość 0xF0
Inicjuję pętle for która będzie odbiera za jednym obiegiem jeden 64 bitowy numer seryjny.
Pobieram dwa bity bitA i bitB.
Jeżeli pierwszy bit adresu we wszystkich adresach ma wartość 0 wtedy odbieram wartość 0 1
Jeżeli pierwszy bit adresu we wszystkich adresach ma wartość 1 wtedy odbieram wartość 1 0
Jeżeli pierwszy bit jest różny w urządzeniach podłączonych do magistrali to otrzymuję wartość 0 0
W wyrażeniach warunkowych sprawdzam jaką wartość ma odebrany bit oraz przypisuję do zmiennej pomocniczej Bit odpowiednią wartość która będzie informować jaką wartość ma wysłać na magistralę.
Jeżeli został odebrany bit o wartości 1 jest on od razu wsuwany do tablicy przy pomocy tej linii kodu:

Kod: Zaznacz cały

if(Bit == 2) buf[currentBit / 8] |= 1 << (currentBit & 7);

Na samym dole mamy konstrukcję Switch której argumentem jest zmienna pomocnicza Bit. To ten przełącznik decyduję o tym jaki bit zostanie wysłany na magistralę.

Teraz najważniejsze:
Na przykład w kolejnym obiegu pętli zostają odebrane dwa bity 0 0 czyi na tej pozycji która jest teraz analizowana mamy urządzenia które na tych pozycja mają różne bity. Jeżeli następuję to w czasie kiedy pętla jest pierwszy raz uruchomiona algorytm z góry wysyła wartość 0 na magistralę (odłączając drugie urządzenie (czeka ono na ponowny sygnał reset)) w następnych liniach mamy warunek

Kod: Zaznacz cały

Bit = 1;
         if(Bit_numer == currentBit)
         {
            Bit = 2;
            Bit_numer = 100;
         }
         else
         {
            Bit_numer = currentBit;
         }

(Zmienna Bit_numer jest zmienną globalną i w chwili inicjalizacji przyjmuję wartość 100) jeżeli funkcja jest wywoływana po raz pierwszy to wykonywana jest cześć po słówku kluczowym else czyli przypisanie numeru obiegu pętli przy której w następnym wywołaniu funkcji musi zostać zmieniona wartość do wysłania, Po wszystkim zostanie ta zmienna znowu zainicjowana wartością 100.



Kod: Zaznacz cały

   while(1)
   {
      memset(buf, 0, sizeof(buf));
      Search();
      for(i = 0; i != 8; i++)
      {
         lcd_locate(0,0);
         lcd_str("                ");
         lcd_locate(0,0);
         lcd_int(buf[i]);
         _delay_ms(2000);
      }
   }
}


void Search(void)
{
   uint8_t bitA = 0, bitB = 0;
   uint8_t currentBit = 0;
   uint8_t Bit = 0;


   Reset = One_Wire_Reset_Pulse();
   One_Wire_Send_Byte(0xF0);

   for(currentBit = 0; currentBit < 64; currentBit++)
   {
      bitA = One_Wire_Read_Bit();
      bitB = One_Wire_Read_Bit();

      if(bitA == 1 && bitB == 0) Bit = 2;
      if(bitA == 0 && bitB == 1) Bit = 1;

      if((bitA == 0)&& (bitB == 0))
      {
         Bit = 1;
         if(Bit_numer == currentBit)
         {
            Bit = 2;
            Bit_numer = 100;
         }
         else
         {
            Bit_numer = currentBit;
         }
      }
      if(Bit == 2) buf[currentBit / 8] |= 1 << (currentBit & 7);
      
      switch (Bit)
      {
      case 1:
         One_Wire_Send_Bit(0);
         break;
      case 2:
         One_Wire_Send_Bit(1);
         break;
      }
   }
}

StaryAnoda

Re: 1 Wire SEARCH ROM

Postautor: StaryAnoda » środa 02 lis 2016, 14:40

Cześć

Panowie możecie mi podpowiedzieć gdzie jest różnica w kodzie który tutaj przedstawiam w stosunku do mojego kodu:
Czemu ten kod działa a mój nie ?
Oba kody rozumiem tak mi się wydaję ale mój nie działa poprawnie (więc pewnie czegoś nie rozumiem)

Kod: Zaznacz cały

   while(1)
   {
      for(j = 0; j != 3; j++)
      {
         pos = Search(pos, buf);
         for(i = 0; i != 8; i++)
         {
            lcd_locate(0,0);
            lcd_str("                ");
            lcd_locate(0,0);
            lcd_int(buf[i]);
            lcd_locate(1,0);
            lcd_int(j);
            lcd_locate(1,2);
            lcd_int(i);
            _delay_ms(1000);
         }
      }
      while(1)
      {

      }
   }
}


uint8_t Search(uint8_t deviationpos,uint8_t *buf)
{
   uint8_t bitA = 0, bitB = 0;
   uint8_t currentBit = 0;
   uint8_t newPos = 0, bitMask = 0x01;

   Reset = One_Wire_Reset_Pulse();
   One_Wire_Send_Byte(0xF0);

   for(currentBit = 0; currentBit < 64; currentBit++)
   {
      bitA = One_Wire_Read_Bit();
      bitB = One_Wire_Read_Bit();

      if(bitA == 0 && bitB == 1) (*buf) &= ~bitMask;
      if(bitA == 1 && bitB == 0) (*buf) |= bitMask;

      if(bitA == 0 && bitB == 0)
      {
         if(currentBit == deviationpos) (*buf) |= bitMask;

         if(currentBit>deviationpos)
         {
            (*buf)&=~bitMask;
            newPos=currentBit;
         }
      }
      One_Wire_Send_Bit((*buf) & bitMask);
      bitMask <<= 1;

      if (!bitMask)
      {
         bitMask = 0x01;
         buf++;
      }
   }
   return newPos;
}

Awatar użytkownika
Antystatyczny
Geek
Geek
Posty: 1177
Rejestracja: czwartek 03 wrz 2015, 22:02

Re: 1 Wire SEARCH ROM

Postautor: Antystatyczny » piątek 04 lis 2016, 23:41

Jeszcze nie wiem, co tam masz źle w wyszukiwaniu urządzeń, ale również nad tym pracuję. Opieram się na artykule ze strony Maxima:
https://www.maximintegrated.com/en/app- ... mvp/id/187

oraz na jego całkiem niezłym tłumaczeniu:
http://www.easy-soft.net.pl/artykuly/te ... ia-ukladow
"The true sign of intelligence is not knowledge but imagination" Albert Einstein.


Wróć do „Inne mikroklocki, również peryferyjne”

Kto jest online

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