Hoe werkt de shiftOut-functie intern? (uitleg over broncode)

Ik was shiftOut() functiecode aan het onderzoeken in wiring_shift.c en ik begreep niet helemaal wat er in de digitalWrite-functie gebeurt. Ik zie dat !!(val & (1 << i)) de bitwaarde overneemt van val maar hoe werkt het precies?

De hele functie staat hieronder.

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); } } 

Reacties

  • !!(val & (1 << i)) is het meest complexe deel van deze code. Als je dit begrijpt , wat is dan het deel dat je niet begrepen?
  • @ edgar-bonet Eigenlijk was dit de vraag. Ik kan zien dat het op de een of andere manier de bitwaarde berekent, maar ik ' begreep niet hoe het doet dit.
  • Je begrijpt het gedrag van de shiftOut-functie? Ik bedoel, je begrijpt dat het ' ll shift out een waarde (in binaire vorm) en geeft daarbij een klokpuls.

Antwoord

Ik “neem aan bitOrder == LSBFIRST.

  • i is het bitnummer, dwz de “index” van het volgende te schrijven bit
  • 1 is 00000001 in binair formaat
  • << is de operator voor verschuiven naar links. Het geeft het eerste argument terug dat evenveel posities naar links is verschoven als aangegeven door het tweede argument.
  • 1<<i is binair 00000001 naar links verschoven met i posities, dat wil zeggen zoiets als 0...010...0, waarbij de enkele 1 op de i-de positie staat, geteld vanaf de rechterkant zijnde positie 0)
  • & is de “bitsgewijze en operator”, waarbij any_bit & 0 nul is en any_bit & 1 is any_bit
  • val & (1 << i) is 0...0(i-th bit of val)0...0 in binair, waarbij het i-de bit van val zich in de i-de positie van het resultaat bevindt
  • !! is een dubbele negatie: het converteert nul naar nul en elke niet-nulwaarde naar één
  • !!(val & (1 << i)) is 0 of 1, en is precies het i-de bit van val

Reacties

  • laat me samenvatten wat ik begrijp. Laten we aannemen dat val = '10010111'; for i=2 !!(val & (1 << i)) = !!('10010111' & '00000100') = !!('00000100') = 1 If i is = 3 !!(val & (1 << i)) = !!('10010111' & '00001000') = !!('00000000') = 0
  • Dit is correct!
  • En dit betekent dat als ik 16bit of meer gegevens geef om uit te schakelen, het zal de minst significante 8 bits verzenden en de rest negeren.
  • shiftOut() neemt uint8_t gegevens. Als je het aanroept met een 16-bits argument, zal de compiler impliciet de 8 meest significante bits verwijderen voor de daadwerkelijke aanroep van shiftOut().
  • @SteveMcDonald: Ja, de uitvoer zou hetzelfde zijn zonder de dubbele ontkenning, omdat digitalWrite() interpreteert elke niet- nulwaarde (niet alleen 1) als betekenis HIGH. Blijkbaar wilde de auteur van shiftOut() niet vertrouwen op dit gedrag, en wilde in plaats daarvan altijd digitalWrite() aanroepen met een 0 (dwz LOW) of 1 (HIGH).

Geef een reactie

Het e-mailadres wordt niet gepubliceerd. Vereiste velden zijn gemarkeerd met *