Skocz do zawartości

Operacje na bitach i ekspander MCP23017


Pomocna odpowiedź

Napisano

Mam stan 3 zmiennych byte wystawić na ekspanderze 16 bitowym, podzielonym na dwa rejestry (MCP23017). W zmiennych znaczących jest tylko 5 młodszych bitów, więc 15 bitów mam wystawić na 16 wyjść.

Czyli

x1 | x2 | x3

---10000 | ---10000 | ---10000

-1000010 | 00010000

rejestr B | rejestr A

Jak to wykonać na operacjach bitowych?

Poradziłem sobie brzydko

bitWrite(tmp,0,bitRead(sem1,0));
     bitWrite(tmp,1,bitRead(sem1,1));
     bitWrite(tmp,2,bitRead(sem1,2));
     bitWrite(tmp,3,bitRead(sem1,3));
     bitWrite(tmp,4,bitRead(sem1,4));
     bitWrite(tmp,5,bitRead(sem2,0));
     bitWrite(tmp,6,bitRead(sem2,1));
     bitWrite(tmp,7,bitRead(sem2,2));

     Wire.beginTransmission(mcp1);
     Wire.write(0x12); // GPIOA
     Wire.write(tmp); // zapis
     Wire.endTransmission();   

     bitWrite(tmp1,0,bitRead(sem2,3));
     bitWrite(tmp1,1,bitRead(sem2,4));
     bitWrite(tmp1,2,bitRead(sem3,0));
     bitWrite(tmp1,3,bitRead(sem3,1));
     bitWrite(tmp1,4,bitRead(sem3,2));
     bitWrite(tmp1,5,bitRead(sem3,3));
     bitWrite(tmp1,6,bitRead(sem3,4));
     bitWrite(tmp1,7,0);

     Wire.beginTransmission(mcp1);
     Wire.write(0x13); // GPIOB
     Wire.write(tmp1); // zapis
     Wire.endTransmission();

ale czy da się to uprościć?

Da się. Generalnie potrzebujesz kilka operacji. Po pierwsze, musisz "przyciąć" te bajty do 5 bitów, to znaczy upewnić się, że w najstarszych trzech bitach na pewno są tylko zera:

x &= 0b00011111;

Operacja ta powoduje, że na przykład wartość

0b10110111

zamieni się na:

0b00010111

Drugą operacją jest przesunięcie bitowe, które pozwoli ci przesunąć te bity na właściwe miejsce:

x <<= 5;

Dizęki temu wartość:

0b00010111

zamieni się w:

0b0001011100000

tylko trzeba się wcześniej jeszcze upewnić, że x jest zmienną 16-bitową.

Na koniec, potrzebujesz sposobu na połączenie tych wartości ze sobą:

x |= y;

Co przy

x = 0b0000010111
y = 0b1011100000

da ci

x = 0b1011110111

No i oczywiście da się wszystko razem:

uint16_t wynik = (x & 0x1f) << 10 | (y & 0x1f) << 5 | (z & 0x1f);
  • Pomogłeś! 1

Dzięki. Zrozumiałem ideę, ale jeszcze się gubię w tych &!%|&

Teraz wystarczy dolny i górny bajt wysłać do rejestrów multipleksera 😉

Jeśli zmieni się tylko jedna zmienna, np. z

to prawidłowe będzie?

uint16_t wynik |= (z & 0x1f);

Nie, bo jeśli jakieś jedynki zmieniły się na zera, to nadal będziesz mieć tam jedynki ze starej wartości.

0b010101 | 0b001001 == 0b011101

Jak się gubisz, to może doczytaj co one dokładnie robią i poćwicz na różnych przykładach. To nie jest skomplikowane.

  • 4 lat(a) później...

Witam szanowne grono...

 

dawno tu nikogo nie ma, ale moze ktos mi pomoze..

Chodzi mi o sposob na zdekodowanie danych do kilku zmiennych z jednej zmiennej jak z przykladu powyzej..

Zalozmy:

Mam trzy zmienne..

X:

Y:

Z:

Kazda z tych zmiennych to powiedzmy bajt ktora bedzie przechowywac wartosci z zakresu np. 5 bitow...

Teraz musze "spakowac" te dane do zmiennej "int", i na to juz jest sposob jak kolega pokazal powyzej (bardzo fajny i prosty przyklad swoja droga!)..

Teraz przesylam ta zmienna przez Uart powiedzmy i musze odtworzyc te liczby w takim samym zestawie zmiennych jak wyzej..tylko jak??

Prosilbym o wyrozumialosc bowiem jestem bardzo poczatkujacym "arduino'wcem"..domyslam sie ze sposob na to bedzie bardzo podobny jak przy "pakowaniu" ale jakos nie moge nic wymyslic..

Bylbym bardzo wdzieczny za jakis prosty przyklad zebym mogl to pojac..

Pozdrawiam🙂

Bądź aktywny - zaloguj się lub utwórz konto!

Tylko zarejestrowani użytkownicy mogą komentować zawartość tej strony

Utwórz konto w ~20 sekund!

Zarejestruj nowe konto, to proste!

Zarejestruj się »

Zaloguj się

Posiadasz własne konto? Użyj go!

Zaloguj się »
×
×
  • Utwórz nowe...