Industriële fabricage
Industrieel internet der dingen | Industriële materialen | Onderhoud en reparatie van apparatuur | Industriële programmering |
home  MfgRobots >> Industriële fabricage >  >> Industrial Internet of Things >> Ingebed

Leer de Embedded C-programmeertaal:het Union Data Object begrijpen

Meer informatie over gegevensobjecten die unions worden genoemd in ingesloten C-taal.

Meer informatie over gegevensobjecten die vakbonden worden genoemd in de ingesloten C-taal.

Het verschil tussen structuur en unie in Embedded C

In een eerder artikel van deze serie hebben we besproken dat structuren in embedded C ons in staat stellen variabelen van verschillende datatypes te groeperen en deze als een enkel data-object te behandelen.

Naast structuren ondersteunt de C-taal een andere dataconstructie, een unie genaamd, die verschillende datatypes kan groeperen als een enkel data-object. Dit artikel geeft wat basisinformatie over vakbonden. We bekijken eerst een inleidend voorbeeld van het aankondigen van een vakbond, daarna bekijken we een belangrijke toepassing van dit data-object.

Inleidend voorbeeld

Het uitroepen van een vakbond lijkt veel op het afkondigen van een structuur. We hoeven alleen het trefwoord "struct" te vervangen door "union". Beschouw de volgende voorbeeldcode:

union-test { uint8_t c; uint32_t i;}; 

Dit specificeert een sjabloon met twee leden:"c", die één byte nodig heeft, en "i", die vier bytes in beslag neemt.

Nu kunnen we een variabele van deze uniesjabloon maken:

verenigingstest u1; 

Met behulp van de ledenoperator (.), hebben we toegang tot de leden van de vakbond "u1". De volgende code wijst bijvoorbeeld 10 toe aan het tweede lid van de bovenstaande unie en kopieert de waarde van "c" naar de variabele "m" (die van het type uint8_t moet zijn).

u1.i=10;m=u1.c; 

Hoeveel geheugenruimte wordt er toegewezen om de variabele "u1" op te slaan? Terwijl de grootte van een structuur minstens zo groot is als de som van de grootte van haar leden, is de grootte van een vakbond gelijk aan de grootte van haar grootste variabele. De geheugenruimte die aan een vakbond is toegewezen, wordt gedeeld door alle vakbondsleden. In het bovenstaande voorbeeld is de grootte van "u1" gelijk aan de grootte van uint32_t, d.w.z. vier bytes. Deze geheugenruimte wordt gedeeld tussen "i" en "c". Daarom zal het toewijzen van een waarde aan een van deze twee leden de waarde van het andere lid veranderen.

U vraagt ​​zich misschien af:"Wat heeft het voor zin om dezelfde geheugenruimte te gebruiken om meerdere variabelen op te slaan? Is er een toepassing voor deze functie?" We zullen dit probleem in de volgende sectie onderzoeken.

Hebben we gedeelde geheugenruimte nodig?

Laten we eens kijken naar een voorbeeld waarin een unie een nuttig gegevensobject kan zijn. Neem aan dat, zoals weergegeven in Afbeelding 1 hieronder, er twee apparaten in uw systeem zijn die met elkaar moeten communiceren.

Figuur 1

"Apparaat A" moet status-, snelheids- en positie-informatie naar "Apparaat B" sturen. De statusinformatie bestaat uit drie variabelen die de batterijlading, de bedrijfsmodus en de omgevingstemperatuur aangeven. De positie wordt weergegeven door twee variabelen die de posities van de x- en y-as weergeven. Ten slotte wordt de snelheid weergegeven door een enkele variabele. Neem aan dat de grootte van deze variabelen is zoals weergegeven in de volgende tabel.

Variabelenaam Grootte (byte) Uitleg
kracht 1 Batterij opladen
op_mode 1 Werkwijze
temp 1 Temperatuur
x_pos 2 X-positie
y_pos 2 Y-positie
vel 2 Snelheid

Als "Apparaat B" constant al deze informatie nodig heeft, kunnen we al deze variabelen in een structuur opslaan en de structuur naar "Apparaat B" sturen. De structuurgrootte zal minstens zo groot zijn als de som van de grootte van deze variabelen, d.w.z. negen bytes.

Dus elke keer dat "Apparaat A" met "Apparaat B" praat, moet het een dataframe van 9 bytes overbrengen via de communicatieverbinding tussen de twee apparaten. Afbeelding 2 toont de structuur die "Apparaat A" gebruikt om de variabelen en het dataframe op te slaan dat door de communicatielink moet gaan.

Figuur 2

Laten we echter een ander scenario overwegen waarin we slechts af en toe de statusinformatie hoeven te verzenden. Stel ook dat het niet nodig is om op een bepaald moment zowel positie- als snelheidsinformatie te hebben. Met andere woorden, soms sturen we alleen positie, soms sturen we alleen snelheid en soms sturen we alleen statusinformatie. In deze situatie lijkt het geen goed idee om de informatie op te slaan in een structuur van negen bytes en deze via de communicatielink over te dragen.

Statusinformatie kan worden weergegeven door slechts drie bytes; voor positie en snelheid hebben we respectievelijk slechts vier en twee bytes nodig. Daarom is het maximale aantal bytes dat "Apparaat A" in één overdracht moet verzenden vier, en bijgevolg hebben we slechts vier bytes geheugen nodig om deze informatie op te slaan. Deze geheugenruimte van vier bytes wordt gedeeld door onze drie berichttypen (zie afbeelding 3).

Houd er bovendien rekening mee dat de lengte van het dataframe dat door de communicatieverbinding wordt gevoerd, is teruggebracht van negen bytes tot vier bytes.

Figuur 3

Om samen te vatten, als ons programma variabelen heeft die elkaar uitsluiten, kunnen we ze opslaan in een gedeeld geheugengebied om waardevolle geheugenruimte te behouden. Dit kan belangrijk zijn, vooral in de context van embedded systemen met beperkte geheugencapaciteit. In dergelijke gevallen kunnen we vakbonden gebruiken om de vereiste gedeelde geheugenruimte te creëren.

Het bovenstaande voorbeeld laat zien dat het gebruik van een unie voor het afhandelen van elkaar uitsluitende variabelen ons ook kan helpen om communicatiebandbreedte te besparen. Het besparen van communicatiebandbreedte is soms zelfs belangrijker dan het besparen van geheugen.

Unions gebruiken voor berichtenpakketten

Laten we eens kijken hoe we een unie kunnen gebruiken voor het opslaan van de variabelen van het bovenstaande voorbeeld. We hadden drie verschillende soorten berichten:status, positie en snelheid. We kunnen een structuur maken voor de variabelen van de status- en positieberichten (zodat de variabelen van deze berichten worden gegroepeerd en gemanipuleerd als een enkel gegevensobject).

De volgende structuren dienen dit doel:

struct { uint8_t power; unit8_t op_mode; uint8_t temp;} status; struct { uint16_t x_pos; unit16_t y_pos;} positie; 

Nu kunnen we deze structuren samen met de variabele "vel" in een unie plaatsen:

union {struct { uint8_t power; unit8_t op_mode; uint8_t temp;} status; struct { uint16_t x_pos; unit16_t y_pos;} positie; uint16_t vel;} msg_union; 

De bovenstaande code specificeert een union-sjabloon en maakt een variabele van deze sjabloon (genaamd "msg_union"). Binnen deze unie zijn er twee structuren (“status” en “positie”) en een variabele van twee bytes (“vel”). De grootte van deze unie zal gelijk zijn aan de grootte van zijn grootste lid, namelijk de "positie" -structuur, die vier bytes geheugen in beslag neemt. Deze geheugenruimte wordt gedeeld door de variabelen "status", "position" en "vel".

Hoe u het actieve lid van de vakbond kunt volgen

We kunnen de gedeelde geheugenruimte van de bovenstaande unie gebruiken om onze variabelen op te slaan; er blijft echter één vraag over:hoe moet de ontvanger bepalen welk type bericht is verzonden? De ontvanger moet het berichttype herkennen om de ontvangen informatie met succes te kunnen interpreteren. Als we bijvoorbeeld een "position"-bericht verzenden, zijn alle vier de bytes van de ontvangen gegevens belangrijk, maar voor een "velocity"-bericht moeten slechts twee van de ontvangen bytes worden gebruikt.

Om dit probleem op te lossen, moeten we onze vakbond koppelen aan een andere variabele, zeg "msg_type", die het berichttype aangeeft (of het vakbondslid waarnaar het laatst is geschreven). Een vakbond gekoppeld aan een discrete waarde die het actieve lid van de vakbond aangeeft, wordt een "gediscrimineerde vakbond" of een "gelabelde vakbond" genoemd.

Wat betreft het gegevenstype voor de variabele "msg_type", kunnen we het gegevenstype opsomming van de C-taal gebruiken om symbolische constanten te creëren. We gebruiken echter een teken om het berichttype te specificeren, om het zo eenvoudig mogelijk te houden:

struct { uint8_t msg_type;union {struct { uint8_t power; unit8_t op_mode; uint8_t temp;} status; struct { uint16_t x_pos; unit16_t y_pos;} positie; uint16_t vel;} msg_union;} bericht; 

We kunnen drie mogelijke waarden beschouwen voor de variabele "msg_type":'s' voor een "status" -bericht, 'p' voor een "position" -bericht en 'v' voor een "velocity" -bericht. Nu kunnen we de "bericht" -structuur naar "Apparaat B" sturen en de waarde van de "msg_type" -variabele gebruiken als een indicator van het berichttype. Als de waarde van het ontvangen 'msg_type' bijvoorbeeld 'p' is, weet 'Apparaat B' dat de gedeelde geheugenruimte twee 2-byte-variabelen bevat.

Houd er rekening mee dat we nog een byte moeten toevoegen aan het dataframe dat via de communicatielink is verzonden, omdat we de variabele "msg_type" moeten overdragen. Houd er ook rekening mee dat met deze oplossing de ontvanger niet van tevoren hoeft te weten wat voor soort bericht er binnenkomt.

De alternatieve oplossing:dynamische geheugentoewijzing

We zagen dat vakbonden ons in staat stellen een gedeeld geheugengebied aan te geven om zowel geheugenruimte als communicatiebandbreedte te besparen. Er is echter een andere manier om elkaar uitsluitende variabelen op te slaan, zoals die in het bovenstaande voorbeeld. Deze tweede oplossing gebruikt dynamische geheugentoewijzing om de variabelen van elk berichttype op te slaan.

Nogmaals, we hebben een variabele "msg_type" nodig om het berichttype aan zowel de zender als de ontvanger van de communicatieverbinding te specificeren. Als 'Apparaat A' bijvoorbeeld een positiebericht moet verzenden, wordt 'msg_type' op 'p' gezet en wordt vier bytes geheugenruimte toegewezen om de variabelen 'x_pos' en 'y_pos' op te slaan. De ontvanger zal de waarde van "msg_type" controleren en, afhankelijk van de waarde, de juiste geheugenruimte creëren voor het opslaan en interpreteren van het binnenkomende dataframe.

Het gebruik van dynamisch geheugen kan efficiënter zijn in termen van geheugengebruik, omdat we net genoeg ruimte toewijzen aan elk berichttype. Dit was niet het geval met de vakbondsoplossing. Daar hadden we vier bytes gedeeld geheugen om alle drie de berichttypen op te slaan, hoewel de "status"- en "snelheids"-berichten slechts drie en twee bytes nodig hadden. Dynamische geheugentoewijzing kan echter langzamer zijn en de programmeur moet code opnemen die het toegewezen geheugen vrijmaakt. Dat is de reden waarom programmeurs meestal de voorkeur geven aan de op vakbonden gebaseerde oplossing.

Volgende:toepassingen van vakbonden

Het lijkt erop dat het oorspronkelijke doel van vakbonden was om een ​​gedeeld geheugengebied te creëren voor elkaar uitsluitende variabelen. Verenigingen worden echter ook veel gebruikt voor het extraheren van kleinere delen van gegevens uit een groter gegevensobject.

Het volgende artikel in deze serie zal zich richten op deze toepassing van vakbonden, wat vooral belangrijk kan zijn in embedded toepassingen.

Ga naar deze pagina om een ​​volledige lijst van mijn artikelen te zien.


Ingebed

  1. De beste programmeertaal voor industriële Internet of Things-toepassingen
  2. Microprocessor-programmering
  3. Wat is embedded systeemprogrammering en de bijbehorende talen
  4. Wat moet ik doen met de gegevens?!
  5. Het IoT democratiseren
  6. 9 nieuwe programmeertalen om te leren in 2021
  7. C - Vakbonden
  8. De toekomst van datacenters
  9. De cloud in IoT
  10. Commentaar:de methoden van robotprogrammering begrijpen
  11. Dezelfde industriële taal spreken:inzicht in de algemene maateenheden van een compressor