Kysymys:
Mitä vikaa tässä AVR: n C-koodin suoratoistossa?
user54579
2012-09-18 21:41:55 UTC
view on stackexchange narkive permalink

Määritin kaksi muuttujaa:

  uint8_t a [2]; uint16_t b;  

Seuraavaksi haluan käyttää a tyypin uint16_t muuttujana, e. g.

  b = (uint16_t) a;  

Mutta tämä on väärin! Ohjelmani eivät toimi oikein tällaisen koodin kanssa. Kaikki on kunnossa, kun vaihdan b -merkiksi uint8_t b [2] ja käytän elementwise-toimintoja.

Miksi?

Miksi et heitä joitain arvoja esimerkkiin ja kerro meille, mikä on odotuksesi "oikeasta", jotta voimme todella auttaa spekuloimalla semanttisesta tarkoituksestasi.
Tämä sopisi paljon paremmin Stack Overflow -sovellukseen.
Viisi vastused:
vicatcu
2012-09-18 22:15:38 UTC
view on stackexchange narkive permalink

a on osoitin tavujärjestelmälle. Jos heität sen uint16_t-tiedostoon ja määrität sen kohtaan b , b sisältää taulukon (johon se on tallennettu) pohjan osoitteen SRAM: ssä. Jos haluat käsitellä taulukon a kahta tavua kokonaislukuna, käytä sitten käyttäjän14284 ehdottamaa liittoa, mutta muista, että unioni edustaa tavujärjestystä muistin tavujärjestyksessä arkkitehtuuri (AVR: ssä se olisi vähän endiaa, mikä tarkoittaa, että tavu 0 on vähiten merkitsevä tavu). Tapa kirjoittaa koodi koodiin on:

  union {uint8_t a [2]; uint16_t b;} x; xb [0] = 0x35; xb [1] = 0x4A; // kahden edellisen tehtävän perusteellax.a == 0x4A35 // on totta  

Toinen tapa tehdä tämä ilman unionia on heittää a uint16_t-osoittimeen ja tehdä siitä poikkeama näin:

  uint8_t a [2] = {0x35, 0x4A }; uint16_t b = * ((uint16_t *) a); b == 0x4A35; // koska AVR on vähän endian  

Jos käytät puskuria isojen endiantietojen (esim. verkon tavujärjestys) tallentamiseen, sinun on vaihdettava tavu vaihtamalla kumpaakin näistä tekniikat. Tapa tehdä se ilman haaroja tai väliaikaisia ​​muuttujia on:

  uint8_t a [2] = {0x35, 0x4A}; a [0] ^ = a [1]; a [1] ^ = a [0]; a [0] ^ = a [1]; a [0] == 0x4A; // truea [1] == 0x35; // true  

Muuten tämä ei ole AVR tai edes upotettu ongelma. PC-tietokoneille kirjoitettu sovellustason verkkokoodi kutsuu yleensä toimintoja nimeltä htonl , htons (isäntä verkkoon, 32- ja 16-bittiset variantit) ja ntohl , ntohs (verkko isäntään, 32- ja 16-bittiset variantit), joiden toteutukset ovat kohdearkkitehtuurista riippuvaisia ​​siitä, vaihtavatko ne tavut vai eivät (olettaen, että tavut lähetetään "langalla") ovat aina suurikokoisia, kun ne ovat osa monitavuisia sanoja).

Tämä on hieno vastaus. Avaimen ollessa yksinään on osoitin.
* "Toinen tapa tehdä tämä ilman unionia on heittää a uint16_t-osoittimeen ja sen jälkeen tehdä siitä poikkeavuus" * - Itse asiassa tämäntyyppinen heitto rikkoo usein tiukkoja aliaksisääntöjä. Sinun ei pitäisi tehdä sitä, ellet käännä tiedostoa `-fno-tight-aliasing`.
Joe Hass
2012-09-18 21:47:25 UTC
view on stackexchange narkive permalink

Jos aiot yhdistää kaksi 8-bittistä muuttujaa 16-bittiseksi muuttujaksi, käytä -yhdistelmää . Jos haluat heittää yhden a -jäsenen b -sarjaan, määritä haluamasi taulukon elementti.

Bruno Ferreira
2012-09-18 22:15:46 UTC
view on stackexchange narkive permalink

Koodissasi syötät vain osoitinta taulukkoon.

Sinun on heitettävä arvo, jota osoittaa a.

  b = (uint16_t) * a;  

En ole koskaan käyttänyt AVR: ää, mutta jos työskentelet 16-bittisen arkkitehtuurin kanssa, sinun on varmistettava, että a on sana tasattu. Tämän tekemättä jättäminen voi johtaa poikkeukseen.

... tämä ei todellakaan ole hänen aikomuksensa ... hän haluaa, että b liittyy a: n molempiin elementteihin (tämä jätä täysin huomiotta a: n [1]), eikä myöskään ole poikkeuksia tai rajoituksia sille, mitä voit suoratoistaa avr-gcc: llä
gbarry
2012-09-18 22:16:53 UTC
view on stackexchange narkive permalink

Jokainen a : n jäsen on 8-bittinen luku. Siinä ei ole mitään suurempaa. Sen lähettäminen 16-bittiseksi ei tee mitään a : lle. Se vain poimii minkä tahansa arvon, jota a pystyy pitämään, ja muuntaa sen 16 bitiksi niin, että se vastaa b -muotoa, kun arvo tallennetaan sinne. / p>

Et edes viitannut a : n jäseneen. Sinun on käytettävä [0] tai [1] (eikä [2]!). Jos käytät itse a : ta, saat vain sen osoitteen. (Hyvä saalis, Bruno).

A : n julistaminen kahdeksan 8-bittisen numeron taulukoksi ei tee siitä myöskään 16-bittistä lukua. Voit tallentaa joitain asioita ohjelmallisesti 16-bittisten arvojen tallentamiseksi ja noutamiseksi käyttämällä 8-bittisiä sekvenssejä, mutta et siten kuin ajattelit.

starblue
2012-09-18 23:54:48 UTC
view on stackexchange narkive permalink

Jos haluat muuntaa a -tavut 16-bittiseksi arvoksi ja esitys on vähän endiaaninen (arvon alemmat 8 bittiä tulevat ensimmäiseen tavuun), tee

  uint16_t b = a [0] | (a [1] << 8);  

Jos kyseessä on iso endiaani, tee

  uint16_t b = (a [0] << 8) | a [1];  

Vältä osoittimen heittoja tai liittoja käyttämästä tätä, koska se johtaa siirrettävyysongelmiin.



Tämä Q & A käännettiin automaattisesti englanniksi.Alkuperäinen sisältö on saatavilla stackexchange-palvelussa, jota kiitämme cc by-sa 3.0-lisenssistä, jolla sitä jaetaan.
Loading...