Jak funkcja shiftOut działa wewnętrznie? (wyjaśnienie kodu źródłowego)

Sprawdzałem kod funkcji shiftOut() w wiring_shift.c i nie całkiem rozumiem, co się dzieje w funkcji digitalWrite. Widzę, że !!(val & (1 << i)) pobiera wartość bitową z val ale jak to dokładnie działa?

Cała funkcja jest poniżej.

void shiftOut(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder, uint8_t val) { uint8_t i; for (i = 0; i < 8; i++) { if (bitOrder == LSBFIRST) digitalWrite(dataPin, !!(val & (1 << i))); else digitalWrite(dataPin, !!(val & (1 << (7 - i)))); digitalWrite(clockPin, HIGH); digitalWrite(clockPin, LOW); } } 

Komentarze

  • !!(val & (1 << i)) to najbardziej złożona część tego kodu. Jeśli rozumiesz to, co robisz, nie rozumiesz?
  • @ edgar-bonet Właściwie to było pytanie. Widzę, że w jakiś sposób oblicza wartość bitu, ale nie ' nie rozumiem, jak to zrobić.
  • Rozumiesz zachowanie funkcji shiftOut? To znaczy, rozumiesz, że jest ona ' ll shift out wartość (w formie binarnej) i wraz z nią poda impuls zegarowy.

Odpowiedź

I „będę zakładać bitOrder == LSBFIRST.

  • i to numer bitu, tj. „indeks” następnego zapisywanego bitu
  • 1 to 00000001 binarnie
  • << to operator przesunięcia w lewo. Zwraca swój pierwszy argument przesunięty w lewo o tyle pozycji, ile wskazuje drugi argument
  • 1<<i jest binarny 00000001 przesunięte w lewo o i pozycje, tj. coś w rodzaju 0...010...0, gdzie pojedyncza 1 znajduje się na i-tej pozycji, licząc od prawej będący pozycją 0)
  • & to „operator bitowy i”, gdzie any_bit & 0 to zero, a any_bit & 1 to any_bit
  • val & (1 << i) to 0...0(i-th bit of val)0...0 binarnie, gdzie i-ty bit val znajduje się na i-tej pozycji wyniku
  • !! jest podwójną negacją: to konwertuje zero na zero i dowolną wartość niezerową na jeden
  • !!(val & (1 << i)) wynosi 0 lub 1 i jest dokładnie i-tym bitem val

Komentarze

  • pozwólcie mi podsumować to, co rozumiem. Załóżmy, że val = '10010111'; for i=2 !!(val & (1 << i)) = !!('10010111' & '00000100') = !!('00000100') = 1 If i is = 3 !!(val & (1 << i)) = !!('10010111' & '00001000') = !!('00000000') = 0
  • Zgadza się!
  • A to oznacza, że jeśli dam 16-bitowe lub dłuższe dane do shiftOut, wyśle najmniej znaczących 8 bitów i zignoruje resztę.
  • shiftOut() pobiera dane uint8_t. Jeśli wywołasz to z 16-bitowym argumentem, kompilator niejawnie usunie 8 najbardziej znaczących bitów przed rzeczywistym wywołaniem shiftOut().
  • @SteveMcDonald: Tak, wynik byłby taki sam bez podwójnej negacji, ponieważ digitalWrite() interpretuje dowolne nie- wartość zerowa (nie tylko 1) w znaczeniu HIGH. Najwyraźniej autor shiftOut() nie chciał polegać na tym zachowaniu i zamiast tego chciał zawsze wywoływać digitalWrite() z 0 (tj. LOW) lub 1 (HIGH).

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *