Industrielle Fertigung
Industrielles Internet der Dinge | Industrielle Materialien | Gerätewartung und Reparatur | Industrielle Programmierung |
home  MfgRobots >> Industrielle Fertigung >  >> Industrial Internet of Things >> Eingebettet

Eingebettete Firmware: Best Practices für C-Array-Initialisierung mit externen Dateidaten und Signalformen

Erfahren Sie, wie Sie C-Arrays mit externen Textdateien initialisieren.

Dieser Leitfaden erklärt, wie Sie Arrays in einem C-Programm mit Daten füllen, die in separaten Textdateien gespeichert sind. Die Werte sind nicht im Quellcode eingebettet, sondern werden zur Kompilierzeit geladen. Wir behandeln eindimensionale und mehrdimensionale Arrays, zeigen, wie Sie steuern können, ob das Array im RAM oder im nichtflüchtigen Speicher liegt, und veranschaulichen, wie Sie zwischen mehreren Datendateien für die Initialisierung wählen können.

Die Beispiele zielen auf einen 32-Bit-ARM-Mikrocontroller ab und werden mit GCC kompiliert. Alle Codeausschnitte verwenden Standard-C und funktionieren mit diesem Compiler.

Grundlagen der Array-Initialisierung

Wenn Sie ein Array in C deklarieren, können Sie eine Liste von Werten – bekannt als Initialisierer – in geschweiften Klammern angeben. Zum Beispiel:


Eingebettete Firmware: Best Practices für C-Array-Initialisierung mit externen Dateidaten und Signalformen

Wenn Sie die Größe in Klammern weglassen, leitet der Compiler sie aus der Anzahl der Initialisierer ab. Wenn das Array größer deklariert wird als die Initialisiererliste, werden die verbleibenden Elemente standardmäßig auf null gesetzt. Mehr Initialisierer als die deklarierte Größe lösen einen Kompilierfehler aus.

Leerzeichen

Initialisierer werden durch Kommas getrennt, und Sie können frei Leerzeichen – Leerzeichen, Tabs, Zeilenumbrüche, Wagenrückläufe, vertikale Tabs oder Formfeeds – zwischen ihnen hinzufügen. In C können Anweisungen mehrere Zeilen umfassen; dies ist besonders nützlich für große Arrays, die mehrere Seiten Quellcode füllen können.


Eingebettete Firmware: Best Practices für C-Array-Initialisierung mit externen Dateidaten und Signalformen

Initialisierung eines Arrays aus einer Datei

Der C-Präprozessor kann beliebige Textdateien mit der #include-Direktive einbinden. Diese Funktion ist nicht auf Header- oder Quelldateien beschränkt; jede Plain-Text-Datei ist akzeptabel. Eine einfache Datei mit Zahlen, Kommas und Leerzeichen kann zur Initialisierung eines Arrays verwendet werden:


Eingebettete Firmware: Best Practices für C-Array-Initialisierung mit externen Dateidaten und Signalformen

Die eingebundene Datei muss reiner Text sein – keine Rich-Text-Formatierung, Header oder andere Artefakte. Ein schnelles Beispiel, erstellt mit Windows Editor, sieht so aus:


Eingebettete Firmware: Best Practices für C-Array-Initialisierung mit externen Dateidaten und Signalformen

Beim Kompilieren erscheint das Array im Speicher wie im Debugger-Screenshot gezeigt. In diesem Fall liegt das Array im RAM, angezeigt durch die hohen Adressen in der "Location"-Spalte.


Eingebettete Firmware: Best Practices für C-Array-Initialisierung mit externen Dateidaten und Signalformen

Speichern eines Arrays im nichtflüchtigen Speicher und Auswählen einer Datendatei

Im obigen Beispiel ist das Array eine globale Variable ohne explizite Platzierung. Der Compiler geht davon aus, dass sie zur Laufzeit geändert werden kann, und platziert die Variable im RAM. Die Initialwerte liegen im nichtflüchtigen Speicher (typischerweise Flash) und eine Boot-up-Routine kopiert sie in den RAM. Wenn das Array wirklich konstant ist, weist die Deklaration mit const den Compiler an, es nur im Flash zu behalten, was wertvollen RAM spart. Der folgende Screenshot zeigt den Effekt: der "Location"-Wert des Arrays zeigt auf niedrige Flash-Adressen.


Eingebettete Firmware: Best Practices für C-Array-Initialisierung mit externen Dateidaten und Signalformen

Sie können #define und #if Direktiven verwenden, um zwischen RAM- und Flash-Speicher zu wechseln oder verschiedene Datendateien für die Initialisierung auszuwählen. Der folgende Code ermöglicht die Wahl des Speicherorts zur Kompilierzeit:


Eingebettete Firmware: Best Practices für C-Array-Initialisierung mit externen Dateidaten und Signalformen

Das #if-Konstrukt ist ein klassisches Beispiel für bedingte Einbindung. Es bestimmt, ob der const-Qualifizierer basierend auf einem Kompilierzeit-Flag angewendet wird.

Ähnlich können Sie bedingt auswählen, welche Datei die Initialdaten liefert:


Eingebettete Firmware: Best Practices für C-Array-Initialisierung mit externen Dateidaten und Signalformen

Testen mit einem großen Array

Zur Validierung der Technik habe ich ein 10.000-Sample-Rauschwellenform in einer CSV-Datei verwendet. Das untenstehende Diagramm zeigt die Wellenform, während die Deklaration demonstriert, wie die Daten in das Programm eingebunden werden:


Eingebettete Firmware: Best Practices für C-Array-Initialisierung mit externen Dateidaten und Signalformen

Eingebettete Firmware: Best Practices für C-Array-Initialisierung mit externen Dateidaten und Signalformen
 

Die ursprüngliche CSV-Datei hatte keine Kommas nach jedem Wert. Mit einem regulären Ausdruck Suchen/Ersetzen (Suche nach \R und Ersetzen mit ,\R) wurden Kommas zu allen 10.000 Einträgen in einem einzigen Vorgang hinzugefügt.

Das resultierende Array ist im Debugger sichtbar, ordentlich in Gruppen von 100 Elementen angeordnet.


Eingebettete Firmware: Best Practices für C-Array-Initialisierung mit externen Dateidaten und Signalformen

Mehrdimensionale Arrays

Bei der Arbeit mit zwei- oder dreidimensionalen Daten denken Sie daran, dass C Arrays in Zeilen-Hauptreihenfolge speichert. Ein uint16_t test[2][3] Array liegt im Speicher so:

[0,0] [0,1] [0,2] [1,0] [1,1] [1,2]

Der Zugriff auf aufeinanderfolgende Elemente entlang des rechtesten Index ist schneller, da die Daten zusammenhängend sind. Wenn Sie zwei Vektoren von 1.000 Samples benötigen, deklarieren Sie test[2][1000] für maximale Cache-Freundlichkeit.

Der Initialisierer für ein zweidimensionales Array wird normalerweise mit verschachtelten Klammern gruppiert:


Eingebettete Firmware: Best Practices für C-Array-Initialisierung mit externen Dateidaten und Signalformen

Sie können jedoch die äußeren Klammern weglassen; der Compiler füllt das Array dann links-nach-rechts. Er gibt eine Warnung aus: missing braces around initializer. Solange die Gesamtzahl der Werte der Array-Größe entspricht, kompiliert der Code.


Eingebettete Firmware: Best Practices für C-Array-Initialisierung mit externen Dateidaten und Signalformen

Um die Daten auf mehrere Dateien zu verteilen, binden Sie einfach jede Datei nacheinander ein und umschließen die gesamte Liste mit einem Paar Klammern:


Eingebettete Firmware: Best Practices für C-Array-Initialisierung mit externen Dateidaten und Signalformen

Initialisierung von Arrays in Unions

union ermöglicht es verschiedenen Typen, denselben Speicher zu teilen. Zum Beispiel belegt eine Union, die einen eindimensionalen Vektor und eine zweidimensionale Matrix enthält, denselben Adressraum:


Eingebettete Firmware: Best Practices für C-Array-Initialisierung mit externen Dateidaten und Signalformen

Bei der Initialisierung füllt der Compiler das erste Mitglied zuerst. Wenn die Reihenfolge umgekehrt ist, können Sie eine Warnung sehen, weil die Initialisiererliste nicht vollständig geklammert ist. Doppelte Klammern um das #include stellen die korrekte Gruppierung sicher:

Die Datendatei für die Union sieht so aus:


Eingebettete Firmware: Best Practices für C-Array-Initialisierung mit externen Dateidaten und Signalformen

Im Speicher beginnen sowohl vector als auch matrix an derselben Position, wie im Debugger gezeigt:


Eingebettete Firmware: Best Practices für C-Array-Initialisierung mit externen Dateidaten und Signalformen

Kennen Sie eine andere Methode, ein mehrdimensionales Array aus einer einzelnen numerischen Datei zu initialisieren? Teilen Sie Ihre Ideen in den Kommentaren.

Bonus-Tipp: Strings

Die Initialisierung eines Strings aus einer externen Datei erfordert, dass die Anführungszeichen in der Datei selbst stehen. Ein direktes #include innerhalb des String-Literals bricht den Compiler. Stattdessen platzieren Sie die Anführungszeichen in der Datei und binden sie so ein:


Eingebettete Firmware: Best Practices für C-Array-Initialisierung mit externen Dateidaten und Signalformen

Der resultierende String liegt im RAM, wie im Screenshot illustriert.

Eingebettete Firmware: Best Practices für C-Array-Initialisierung mit externen Dateidaten und Signalformen


Diese Beispiele sind theoretisch und sollten mit jedem Standard-C-Compiler funktionieren. Wenn Sie compiler-spezifische Eigenheiten feststellen, lassen Sie es uns in den Kommentaren wissen.

Quelle bereitgestellt.

Eingebettet

  1. Die Cloud-Revolution: Wie Cloud Computing IT, Sicherheit und Karrieren transformiert
  2. STMicroelectronics stellt STM32Cube.AI vor: Edge-Geräte mit eingebetteten Neural Networks befähigen
  3. DATA MODUL bringt ultra-helle 21,5" & 31,5" Open-Frame Monitore mit EasyTouch für Outdoor & Indoor
  4. Microchip führt 24-bit & 16-bit Delta-Sigma ADCs mit 153,6 kSPS Datenraten
  5. Contrinex 2020: Cloud-Ready Sensoren & Bluetooth Light Curtains für Safety
  6. C++ Arrays verstehen: Deklaration, Initialisierung und Pointer‑Techniken
  7. C++ Dynamische Array‑Allokation: Praktischer Leitfaden mit Code‑Beispielen
  8. Dateien in Java mit BufferedReader lesen – Praktischer Leitfaden mit Beispielen
  9. IoT mit IBM & Tech Data zum Leben erwecken – Teil 2
  10. IoT in die Realität umsetzen: Tech Data & IBM Insights – Teil 1