Kuinka shiftOut-toiminto toimii sisäisesti? (selitys lähdekoodille)

Tutkin shiftOut() -toimintokoodia wiring_shift.c ja en tiennyt oikein, mitä digitalWrite-toiminnossa tapahtuu. Näen, että !!(val & (1 << i)) ottaa bittiarvon kohteesta val mutta miten se toimii?

Koko toiminto on alla.

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

Kommentit

  • !!(val & (1 << i)) on tämän koodin monimutkaisin osa. Jos ymmärrät tämän, niin mikä on tekemäsi osa ei ymmärrän?
  • @ edgar-bonet Oikeastaan tämä oli kysymys. Näen sen jotenkin laskevan bittiarvon, mutta en ymmärtänyt miten ' se tekee tämän.
  • Ymmärrätkö shiftOut-funktion käyttäytymisen? Tarkoitan, että ymmärrät sen ' ll shift out arvo (binäärimuodossa). Ja antaa kellopulssin sen mukana.

vastaus

Oletan, että bitOrder == LSBFIRST.

  • i on bittinumero, ts. seuraavan kirjoitettavan bitin ”indeksi”
  • 1 on 00000001 binaarissa
  • << on siirtymä vasemmalle. Se palauttaa ensimmäisen argumenttinsa siirretty vasemmalle niin monta paikkaa kuin toinen argumentti osoittaa.
  • 1<<i on binaarinen 00000001 siirtynyt vasemmalle i -asennoilla, ts. 0...010...0 -työkalulla, jossa yksittäinen 1 on i: nnessä sijainnissa laskettaessa oikealta (oikeanpuoleisin sijainti 0)
  • & on ”bitti ja operaattori”, jossa any_bit & 0 on nolla ja any_bit & 1 on any_bit
  • val & (1 << i) on 0...0(i-th bit of val)0...0 binaarisessa muodossa, jossa val-arvon i-bitti on tuloksen i-nnessä asemassa
  • !! on kaksinkertainen negaatio: se muuntaa nollan nollaksi ja kaikki nollasta poikkeavat arvot yhdeksi
  • !!(val & (1 << i)) on joko 0 tai 1 ja on täsmälleen i: nnen bitin val

Kommentit

  • anna minun tehdä yhteenveto ymmärrämästäni. Oletetaan, että val = '10010111'; for i=2 !!(val & (1 << i)) = !!('10010111' & '00000100') = !!('00000100') = 1 Jos i on = 3 !!(val & (1 << i)) = !!('10010111' & '00001000') = !!('00000000') = 0
  • Tämä on oikein!
  • Ja tämä tarkoittaa, että annan 16 bittiä tai pidempää dataa shiftOut, se lähettää vähintään 8 merkitsevää bittiä ja ohittaa loput.
  • shiftOut() vie uint8_t -dataa. Jos kutsut sitä 16-bittisellä argumentilla, kääntäjä poistaa implisiittisesti 8 merkittävintä bittiä ennen varsinaista kutsua shiftOut().
  • @SteveMcDonald: Kyllä, lähtö olisi sama ilman kaksoisnegatiota, koska digitalWrite() tulkitsee mitä tahansa muuta kuin nolla-arvo (ei vain 1) merkityksellä HIGH. Ilmeisesti julkaisun shiftOut() kirjoittaja ei halunnut luottaa tähän käyttäytymiseen ja halusi sen sijaan aina kutsua digitalWrite() jommallakummalla 0 (eli LOW) tai 1 (HIGH).

Vastaa

Sähköpostiosoitettasi ei julkaista. Pakolliset kentät on merkitty *