Operacje bitowe C/C++

0

Witam.

Chciałbym się dowiedzieć jak rozumieć wyniki poniższych operacji.

  GPIOA->MODER   &= ~((3ul << 2*5));
  GPIOA->MODER   |=  ((1ul << 2*5));
  GPIOA->OTYPER  &= ~((1ul <<   5));
  GPIOA->OSPEEDR &= ~((3ul << 2*5));
  GPIOA->OSPEEDR |=  ((1ul << 2*5));
  GPIOA->PUPDR   &= ~((3ul << 2*5));

Doszukałem się parę rzeczy w sieci, dzięki którym mogę się jedynie domyśleć, jak prezentuje się powyższy wynik. Jednak nigdzie nie znalazłem oczywistego dowodu. Moje rozumowanie.

GPIOA->MODER &= ~((3ul << 2*5));
3ul to inaczej 0000 0000 0000 0000 0000 0000 0000 0011

teraz przesuń o 10 bitów w lewo czyli
0000 0000 0000 0000 000 1100 0000 0000
zaneguj
1111 1111 1111 1111 1111 0011 1111 1111
Czyli w pierwszym nawiasie ma my powyższa wartość, która wpisujemy w rejestr MODER. Czy dobrze dedukuje ?

2
  1. http://ideone.com/eKjDPE
  2. Otwierasz kalkulator, tryb programisty, wpisujesz tę liczbę i konwertujesz na tryb binarny.

Oczywiście wiesz, że &= oznacza przypisz wynik bitowego ANDa do pierwszej liczby?

0

Tak dokładnie. Przy okazji widzę, że dobrze policzyłem. Zastanawiam się jednak jaki sens jest używania mnożenia w drugim argumencie zamiast po prostu wpisać 10, a nie 25 no i to działanie GPIOA->MODER &= ~((3ul << 25)); (GPIOA->MODER |= ((1ul << 2*5));) może być przecież przekalkulowane w jednej linii :]

tak mamy działanie
1111 1111 1111 1111 1111 0011 1111 1111 |= 0000 0000 0000 0000 0000 0100 0000 0000
i wynik
1111 1111 1111 1111 1111 0111 1111 1111
Po co tyle pisania jak można to było zrobić w jednej linii
GPIOA->MODER &= ~((1ul << 11)

Może później dojdę do tego dlaczego nie tak , a tak...

0

Może po to, żeby pokazać elementy cząstkowe, tak jak np. jak muszę konwertować 2 minuty na sekundy to czasem piszę 2 * 60 zamiast 120.

0

Możliwe, że jest tak jak piszesz.
Teraz chyba widzę problem, po wpisaniu do uC tylko jednej Lini

 GPIOA->MODER   &=  ~((1ul << 11) 

nie działa jak należy, chyba, że coś źle policzyłem, albo ta pierwsza linia jest potrzebna do czegoś o czym nie wiem a jest to w dokumentacji...

1

Nie wczytywałem się w temat, ale może chodzi o to że 2*5to nie jest11` ?

0

Tylko ,że to jest przypisanie w jednej lini zastępujące to dwa. Spróbuj policzyć, a wyjdzie 11, a nie 10...

0

Owszem te dwie operacje:

GPIOA->MODER   &= ~((3ul << 2*5));
GPIOA->MODER   |=  ((1ul << 2*5));

Można zastąpić na:

GPIOA->MODER   &= ~((2ul << 2*5));
GPIOA->MODER   |=  ((1ul << 2*5));

lub na:

GPIOA->MODER   &= ~((1ul << 2*5+1));
GPIOA->MODER   |=  ((1ul << 2*5));

W obu przypadkach wg mnie - gorzej wygląda ponieważ człowiek zaczyna się zastanawiać czemu nie na odwrót.

0

A Jak zapisać to w jednym działaniu ? Ja spróbowałem tak
GPIOA->MODER &= ~((1ul << 11)

to teoretycznie powinno dać ten sam wynik w rejestrze co te dwa działania

 GPIOA->MODER   &= ~((3ul << 2*5));
  GPIOA->MODER   |=  ((1ul << 2*5));

Ale Uc tego nie przyjmuje...

1

Te operacje zerują bit nr 11 oraz ustawiają bit 10.
Nie da się zrobić tego jedną operacją (to znaczy da się ale ta jedna będzie bardziej skomplikowana niż te dwie).

0

I tu masz rację i o to chodziło :)

1 użytkowników online, w tym zalogowanych: 0, gości: 1