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

Tipps zur eingebetteten Firmware:So initialisieren Sie Arrays in C mit Signalwellenformen und anderen Dateidaten

Dieser Artikel zeigt, wie man Arrays in einem C-Programm mit Werten aus Textdateien initialisiert.

Dieser Artikel zeigt, wie Sie Arrays in einem C-Programm mit Werten aus Textdateien initialisieren. Die Daten werden nicht in den Quelldateien gespeichert. Die Dateien werden beim Kompilieren des Programms gelesen. Berücksichtigt werden eindimensionale und mehrdimensionale Arrays. Beispiele zeigen auch, wie Sie das Einfügen von Arrays in den RAM oder nichtflüchtigen Speicher und die Auswahl der für die Initialisierung zu verwendenden Datendateien steuern.

Der für die Beispiele verwendete Compiler ist GCC für ARM mit einem 32-Bit-Mikrocontroller als Ziel. Alle Beispiele verwenden Standard-C und haben mit diesem Compiler gearbeitet.

Grundlagen der Initialisierung eines Arrays

Ein Array kann mit Werten initialisiert werden, wenn es „deklariert“ ist. Eine typische Deklaration wird hier gezeigt. Die Werte innerhalb der geschweiften Klammern werden als „Initialisatoren“ bezeichnet.


Wenn die Größe des Arrays nicht innerhalb der Klammern angegeben ist, entspricht die Größe der Anzahl der Initialisierer. Wenn weniger Initialisierer als die Größe des Arrays vorhanden sind, werden die zusätzlichen Elemente auf 0 gesetzt. Es ist ein Fehler, mehr Initialisierer als die Größe des Arrays zu haben.

Leerraum

Initialisierer müssen durch Kommas getrennt werden. Das Hinzufügen von "Leerzeichen" ist in Ordnung. In diesem Fall handelt es sich bei dem Leerraum um „Leerzeichen“ oder Leerzeichen. Zu den Leerzeichen gehören Leerzeichen (oder Leerzeichen), Tabulatoren, Zeilenumbrüche, Wagenrücklauf, vertikale Tabulatoren und Seitenvorschub. Newline und Carriage Return werden verwendet, um das Ende einer Zeile im C-Quellcode anzuzeigen. Ich kenne den Formular-Feed, aber den vertikalen Tab?

Im Allgemeinen ist es C egal, ob eine Anweisung Leerzeichen enthält oder in einer anderen Zeile fortgesetzt wird. Die Aussage hier entspricht der obigen. Es ist üblich, viele, viele Zeilen von Initialisierern für große Arrays zu sehen. Vielleicht sogar Seiten. Irgendwann sagen wir vielleicht:„Gibt es einen besseren Weg?“


Initialisierung eines Arrays aus einer Datei

C-Quellcode wird vor der Kompilierung durch einen Präprozessor ausgeführt. Eine häufig verwendete Funktion von C-Präprozessoren ist die „Dateieinbindung“. Hier ist ein Zitat aus dem berühmten Buch „The C Programming Language“ von Kernighan und Ritchie.

„Die Dateieinbindung erleichtert die Handhabung von Sammlungen von #defines und Erklärungen (unter anderem ).“

Ich habe die Kursivschrift für „unter anderem“ hinzugefügt. Während wir normalerweise „.c“- und „.h“-Dateien einschließen, kümmert sich der Präprozessor nicht um die Namenserweiterung einer Datei. Jede Textdatei ist OK. Die folgende Syntax funktioniert also, um ein Array zu initialisieren.


Die Datei darf keine Sonderzeichen enthalten, die bei der Formatierung eines Dokuments manchmal ausgeblendet werden. Halte es einfach. Kein Rich-Text-Format. Keine Spaltenüberschriften. Nur Zahlen, Kommas und Leerzeichen. Hier ist eine Datei, die mit Windows Notepad erstellt wurde.


Hier ist das Array im Speicher, das mit einem Debugger angezeigt wird. In diesem Fall befindet sich das Array im RAM, wie durch die hohen Adressen in der Spalte Location angezeigt.


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

Im obigen Beispiel ist das Array eine globale Variable und nichts gibt an, wo das Array abgelegt werden soll. Der Compiler und der Linker gehen davon aus, dass das Array möglicherweise vom Programm geändert wird, und wird im RAM abgelegt. Die Anfangswerte befinden sich im nichtflüchtigen Speicher („NVM“, typischerweise Flash-Speicher), und das Array im RAM wird aus diesen Daten durch Code initialisiert, der vor dem Hauptprogramm ausgeführt wird. Auf diese Daten in NVM greift das Programm nicht zu. Wenn das Array nicht geändert wird (es ist eine „Konstante“), wird es nur in NVM abgelegt und vom Programm direkt darauf zugegriffen. Das spart RAM, der oft knapp ist. Dem Compiler und Linker mitzuteilen, dass ein Array nicht geändert werden soll, und um es in NVM zu finden, erfolgt normalerweise mit dem Befehl „const . “-Qualifikation. Hier ein Beispiel und ein Blick auf das Ergebnis. Die Spalte Location zeigt es unten in der Speicherzuordnung an, die für diesen Mikrocontroller Flash-Speicher ist.


Das #define und #if Vorverarbeitungsanweisungen können verwendet werden, um Optionen zum Auffinden des Arrays und zur Auswahl der Datendateien, die für die Initialisierung verwendet werden, anzugeben. Hier ist ein Beispiel, das die Auswahl bietet, ein Array im RAM oder NVM zu lokalisieren.


Das #if Konstrukt ist ein Beispiel für „bedingte Inklusion“. In diesem Fall steuert es, ob die "const ” Qualifizierer wird verwendet, wenn das Array deklariert wird. Es funktioniert, weil die Deklaration in mehr als einer Zeile stehen kann oder, anders gesagt, Leerzeichen in Ordnung sind.

Hier ist ein Beispiel für die Verwendung der bedingten Einbindung, um die Datei für die Initialisierung auszuwählen.


Testen mit einem großen Array

Ich hatte eine große Datei mit Zufallsdaten, die eine Rauschwellenform darstellten, und verwendete sie, um die Initialisierung eines großen Arrays in NVM zu testen. Hier ist ein Diagramm der Daten und der Deklaration.



Hier ist der Anfang der Datei.


Die ursprüngliche CSV-Datei enthielt kein Komma nach den Werten. Diese wurden leicht mit einem Editor hinzugefügt, der Ausdrücke in Suchen/Ersetzen-Operationen verwenden konnte. In diesem Fall habe ich den Ausdruck für ein Zeilentrennzeichen „\R“ verwendet. Das Suchen war „\R“ und das Ersetzen war „,\R“. Ein Suchen/Ersetzen-Vorgang fügte alle Kommas für 10.000 Werte hinzu.

Hat alles super geklappt und sehr schnell kompiliert! Hier ist der Anfang des Arrays im Speicher. Der Debugger hat die Anzeige schön in Gruppen von jeweils 100 Elementen aufgeteilt.


Mehrdimensionale Arrays

Was ist, wenn die Daten in zwei oder mehr Dimensionen organisiert sind? Schauen wir uns ein zweidimensionales Array an, das als uint16_t test[2][3] deklariert ist . In C ist der rechte Index (3) ein eindimensionales Array mit im Speicher zusammenhängenden Elementen. Der linke Index (2) bedeutet, dass es zwei dieser Arrays mit drei Elementen gibt. Dies ist die Speicheranordnung der sechs Elemente:

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

Die Reihenfolge im Speicher ist wichtig, da der Zugriff auf aufeinanderfolgende Elemente im Speicher durch Inkrementieren des rechten Index schneller ist als der Zugriff auf Elemente durch Inkrementieren des linken Index, was „Sprung“ durch den Speicher erfordert. Wenn das Array zwei Vektoren mit 1.000 Elementen enthielt, sollte die Organisation test[2][1000] . sein für den schnellsten Zugriff.

Hier ist ein Beispiel für die Initialisierung eines zweidimensionalen Arrays. Beachten Sie, dass die Initialisierer mit zusätzlichen geschweiften Klammern gruppiert sind, die die Initialisierer für die eindimensionalen Arrays des rechten Indexes gruppieren.


Dieses Format verursacht ein Problem für eine Datendatei, die nur Zahlen, Kommas und Leerzeichen enthalten kann. Was passiert, wenn die zusätzlichen geschweiften Klammern weggelassen werden?


Der Compiler füllt das Array, indem er von links nach rechts durch die Initialisierer geht, wobei der rechte Index zuerst ausgefüllt wird. Der Compiler, den ich verwende, gibt eine Warnung aus:„fehlende geschweifte Klammern um den Initialisierer “. Es ist kein Problem, wenn die Anzahl der Initialisierer genau der Anzahl der Elemente im Array entspricht. Bei Ungleichheit ist es jedoch nicht klar, wie das Array gefüllt werden soll, wenn keine geschweiften Klammern als Hilfslinien vorhanden sind.

Das Array kann aus mehreren Dateien mit mehreren #include gefüllt werden Aussagen. Hier ist ein Beispiel, bei dem die Initialisierung vollständig mit geschweiften Klammern eingeklammert ist. Ich lasse die Details aus den vorherigen Beispielen weg.


Initialisierung von Arrays in Unions

Eine Union ist eine Variable, die Objekte unterschiedlichen Typs aufnehmen kann, die denselben Speicher teilen, und der Compiler verfolgt die Objekte, als ob es unterschiedliche Dinge wären. Diese Anordnung könnte für eine eingebettete Anwendung mit wenig Speicher nützlich sein. Hier ist ein Beispiel mit Vektor[6] mit einer Dimension und Matrix[2][3] mit zwei Dimensionen. Sie sind zwei Arrays, die die gleichen Speicherorte belegen.


Die Regel zum Initialisieren einer Union ist das Erste in der Union (Vektor[6] ) wird mit den Initialisierern gefüllt. Wenn die Reihenfolge der Arrays umgekehrt wurde, gibt der Compiler eine Warnung aus, da die Initialisierer nicht vollständig in geschweifte Klammern eingeschlossen sind. Beachten Sie die geschweiften Klammern um das #include werden verdoppelt. Ich denke, der äußere Satz umschließt alle Initialisierer für die Union und der innere Satz ist für einen Array-Typ.

Hier ist die Datei. Ich habe zwei Reihen, aber das spielt keine Rolle. Nur mehr Leerraum.


Hier ist das Array im Speicher. Beachten Sie die Startposition von vector[ ] und matrix[ ][ ] sind gleich.


Gibt es andere Möglichkeiten, mehrdimensionale Arrays aus einer einzigen Datei mit nur Zahlen, Kommas und Leerzeichen zu initialisieren? Bitte teilen Sie uns dies mit, indem Sie einen Kommentar hinzufügen.

Bonustipp:Strings

Was ist mit Saiten? Hier ist ein Beispiel für die Initialisierung eines Strings.


Ein #include innerhalb der Anführungszeichen funktioniert nicht. Mein Editor, der die C-Syntax kennt, gibt mir viele Fragezeichen und verschnörkelte Unterstreichungen. Zeichen für die neuen Zeilen und das #include selbst sind Initialisierer! Der arme Redakteur ist verwirrt. Dieses Durcheinander wird kompiliert, aber der String wird mit den Zeichen gefüllt, die wir hier sehen und nicht aus der Datei.


Die Lösung besteht darin, die Anführungszeichen in die Datei zu setzen.


Verwenden Sie dann eine Anweisung wie diese.


Beachten Sie, dass die Anführungszeichen um den Dateinamen Teil von #include . sind Syntax und steuern keine Initialisierer. Hier ist das Ergebnis im RAM.


Es ist wichtig zu beachten, dass die Beispiele alle theoretisch funktionieren sollten mit jedem Compiler. Einige Beispiele können jedoch ungewöhnlich sein und Probleme mit einigen Compilern auslösen. Bitte lass es uns in den Kommentaren wissen, wenn du ein Problem findest.


Eingebettet

  1. Cloud und wie sie die IT-Welt verändert
  2. ST treibt KI zu Edge- und Node-Embedded-Geräten mit STM32 Neural-Network Developer Toolbox
  3. DATENMODUL:Großformatige Open-Frame-Monitore mit hoher Helligkeit und easyTouch-Funktion
  4. Mikrochip:24-Bit- und 16-Bit-ADCs mit Datenraten bis zu 153,6 kSPS
  5. Contrinex:Cloud-fähige intelligente Sensoren und Sicherheits-Lichtvorhänge mit Bluetooth-Schnittstelle
  6. Arrays in C++ | Erklären | Initialisieren | Zeiger auf Array-Beispiele
  7. C++ Dynamische Zuordnung von Arrays mit Beispiel
  8. Java BufferedReader:Lesen von Dateien in Java mit Beispiel
  9. Wie Sie IOT mit Tech Data und IBM Teil 2 verwirklichen können
  10. Wie Sie das IoT mit Tech Data und IBM Teil 1 verwirklichen