Fabrication industrielle
Internet des objets industriel | Matériaux industriels | Entretien et réparation d'équipement | Programmation industrielle |
home  MfgRobots >> Fabrication industrielle >  >> Industrial Internet of Things >> Embarqué

Conseils sur le micrologiciel intégré :comment initialiser des tableaux en C avec des formes d'onde de signal et d'autres données de fichier

Cet article montre comment initialiser des tableaux dans un programme C avec des valeurs de fichiers texte.

Cet article montre comment initialiser des tableaux dans un programme C avec des valeurs de fichiers texte. Les données ne sont pas stockées dans les fichiers source. Les fichiers sont lus lors de la compilation du programme. Les tableaux unidimensionnels et multidimensionnels sont considérés. Des exemples montrent également comment contrôler la mise des tableaux dans la RAM ou la mémoire non volatile et sélectionner les fichiers de données à utiliser pour l'initialisation.

Le compilateur utilisé pour les exemples est GCC pour ARM avec un microcontrôleur 32 bits comme cible. Tous les exemples utilisent le C standard et fonctionnent avec ce compilateur.

Bases de l'initialisation d'un tableau

Un tableau peut être initialisé avec des valeurs lorsqu'il est « déclaré ». Une déclaration type est présentée ici. Les valeurs entre les accolades sont appelées « initialiseurs ».


Si la taille du tableau n'est pas spécifiée entre parenthèses, la taille sera le nombre d'initialiseurs. S'il y a moins d'initialiseurs que la taille du tableau, les éléments supplémentaires sont mis à 0. C'est une erreur d'avoir plus d'initialiseurs que la taille du tableau.

Espace blanc

Les initialiseurs doivent être séparés par des virgules. L'ajout d'un « espace blanc » est OK. Dans ce cas, l'espace blanc est des « blancs » ou des espaces. Le jeu de caractères d'espacement comprend le blanc (ou l'espace), la tabulation, le saut de ligne, le retour chariot, la tabulation verticale et le saut de page. La nouvelle ligne et le retour chariot sont utilisés pour indiquer la fin d'une ligne dans le code source C. Je connais le flux de formulaire mais l'onglet vertical ?

En général, C ne se soucie pas si une instruction contient des espaces blancs ou se poursuit sur une autre ligne. La déclaration ici est équivalente à celle ci-dessus. Il est courant de voir de très nombreuses lignes d'initialiseurs pour les grands tableaux. Peut-être même des pages. À un moment donné, nous pourrions dire :« Y a-t-il un meilleur moyen ? »


Initialisation d'un tableau à partir d'un fichier

Le code source C est exécuté via un préprocesseur avant la compilation. Une caractéristique couramment utilisée des préprocesseurs C est « l'inclusion de fichiers ». Voici une citation du célèbre livre "The C Programming Language" de Kernighan et Ritchie.

« L'inclusion de fichiers facilite la gestion des collections de #defines et déclarations (entre autres )."

J'ai ajouté les italiques pour "entre autres choses". Alors que nous incluons généralement les fichiers ".c" et ".h", le préprocesseur ne se soucie pas de l'extension de nom d'un fichier. Tout fichier texte est OK. Ainsi, la syntaxe suivante fonctionne pour initialiser un tableau.


Le fichier ne doit pas contenir de caractères spéciaux qui sont parfois masqués pour la mise en forme d'un document. Rester simple. Pas de format de texte riche. Aucun en-tête de colonne. Uniquement des chiffres, des virgules et des espaces blancs. Voici un fichier créé avec le Bloc-notes de Windows.


Voici le tableau en mémoire affiché avec un débogueur. Dans ce cas, le tableau est en RAM comme indiqué par les adresses hautes dans la colonne Emplacement.


Stockage d'un tableau dans la mémoire non volatile et sélection d'un fichier de données

Dans l'exemple ci-dessus, le tableau est une variable globale et rien ne précise où placer le tableau. Le compilateur et l'éditeur de liens supposent que le tableau peut être modifié par le programme et qu'il est placé dans la RAM. Les valeurs initiales sont en mémoire non volatile (« NVM », typiquement mémoire Flash), et le tableau en RAM est initialisé à partir de ces données par un code qui s'exécute avant le programme principal. Ces données dans NVM ne sont pas accessibles par le programme. Si le tableau ne sera pas modifié (c'est une "constante") il est mis uniquement dans NVM et accessible directement par le programme. Cela permet d'économiser de la RAM qui est souvent insuffisante. Dire au compilateur et à l'éditeur de liens qu'un tableau ne va pas être modifié et le localiser dans NVM se fait généralement avec le "const ” qualificatif. Voici un exemple et un aperçu du résultat. La colonne Emplacement l'indique en bas de la carte mémoire qui, pour ce microcontrôleur, est la mémoire Flash.


Le #définir et #if Les instructions de prétraitement peuvent être utilisées pour fournir des options de localisation du tableau et de sélection des fichiers de données à utiliser pour l'initialisation. Voici un exemple qui donne le choix de localiser un tableau en RAM ou en NVM.


Le #if est un exemple d'« inclusion conditionnelle ». Dans ce cas, il contrôle si le "const ” qualificateur est utilisé lors de la déclaration du tableau. Cela fonctionne parce que la déclaration peut être sur plus d'une ligne ou, autrement dit, l'espace blanc est OK.

Voici un exemple d'utilisation de l'inclusion conditionnelle pour sélectionner le fichier à initialiser.


Test avec un grand tableau

J'avais un gros fichier de données aléatoires représentant une forme d'onde de bruit et je l'ai utilisé pour tester l'initialisation d'un grand tableau dans NVM. Voici un graphique des données et de la déclaration.



Voici le début du fichier.


Le fichier csv d'origine n'avait pas de virgule après les valeurs. Ceux-ci ont été facilement ajoutés à l'aide d'un éditeur qui pouvait utiliser des expressions dans les opérations Rechercher/Remplacer. Dans ce cas, j'ai utilisé l'expression pour un délimiteur de ligne, "\R". La recherche était "\R" et le remplacement était ",\R". Une opération Rechercher/Remplacer a ajouté toutes les virgules pour 10 000 valeurs.

Tout a très bien fonctionné et a été compilé très rapidement ! Voici le début du tableau en mémoire. Le débogueur a joliment divisé l'affichage en groupes de 100 éléments chacun.


Tableaux multidimensionnels

Que se passe-t-il si les données sont organisées en deux dimensions ou plus ? Regardons un tableau à deux dimensions déclaré comme uint16_t test[2][3] . En C, l'indice de droite (3) est un tableau à une dimension avec des éléments contigus en mémoire. L'indice de gauche (2) signifie qu'il y a deux de ces tableaux à trois éléments. Voici l'arrangement mémoriel des six éléments :

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

L'ordre en mémoire est important car accéder à des éléments consécutifs en mémoire en incrémentant l'indice de droite est plus rapide que d'accéder aux éléments en incrémentant l'indice de gauche qui nécessite des « sauts » dans la mémoire. Si le tableau contenait deux vecteurs de 1 000 éléments, l'organisation devrait être test[2][1000] pour l'accès le plus rapide.

Voici un exemple d'initialisation d'un tableau à deux dimensions. Notez que les initialiseurs sont regroupés avec des accolades supplémentaires regroupant les initialiseurs pour les tableaux unidimensionnels de l'indice de droite.


Ce format crée un problème pour un fichier de données qui ne peut contenir que des chiffres, des virgules et des espaces. Que se passe-t-il si les accolades supplémentaires sont omises ?


Le compilateur remplit le tableau en parcourant les initialiseurs de gauche à droite avec l'indice de droite rempli en premier. Le compilateur que j'utilise donne un avertissement :"accolades manquantes autour de l'initialiseur ”. Il n'y a pas de problème si le nombre d'initialiseurs est exactement le même que le nombre d'éléments dans le tableau. Cependant, s'il n'est pas égal, il n'est pas clair comment remplir le tableau s'il n'y a pas d'accolades pour servir de guides.

Le tableau peut être rempli à partir de plusieurs fichiers avec plusieurs #include déclarations. Voici un exemple où l'initialisation est complètement encadrée par des paires d'accolades. Je laisse de côté les détails indiqués dans les exemples précédents.


Initialisation des tableaux dans les unions

Une union est une variable qui peut contenir des objets de différents types partageant la même mémoire et le compilateur garde une trace des objets comme s'il s'agissait de choses différentes. Cette disposition pourrait être utile pour une application embarquée à court de mémoire. Voici un exemple avec vector[6] avec une dimension et matrice[2][3] avec deux dimensions. Ce sont deux tableaux qui occupent les mêmes emplacements en mémoire.


La règle d'initialisation d'une union est la première chose dans l'union (vector[6] ) est rempli avec les initialiseurs. Si l'ordre des tableaux a été inversé, le compilateur donne un avertissement car les initialiseurs ne sont pas complètement encadrés d'accolades. Remarquez les accolades autour du #include sont doublés. Je pense que l'ensemble externe contient tous les initialiseurs pour l'union et l'ensemble interne est pour un type de tableau.

Voici le fichier. J'ai deux rangées mais ce n'est pas grave. Juste plus d'espace blanc.


Voici le tableau en mémoire. Notez l'emplacement de départ de vector[ ] et matrice[ ][ ] sont les mêmes.


Existe-t-il d'autres moyens d'initialiser des tableaux multidimensionnels à partir d'un seul fichier avec uniquement des nombres, des virgules et des espaces blancs ? Veuillez nous le dire en ajoutant un commentaire.

Astuce bonus : chaînes

Et les cordes ? Voici un exemple d'initialisation d'une chaîne.


Un #include entre guillemets ne fonctionne pas. Mon éditeur, qui connaît la syntaxe C, me donne beaucoup de points d'interrogation et de soulignements ondulés. Caractères pour les nouvelles lignes et le #include lui-même sont des initialiseurs ! Le pauvre éditeur est confus. Ce gâchis se compile mais la chaîne est remplie avec les caractères que nous voyons ici et non du fichier.


La solution est de mettre les guillemets dans le fichier.


Ensuite, utilisez une déclaration comme celle-ci.


Notez que les guillemets autour du nom du fichier font partie du #include syntaxe et ne contrôle pas les initialiseurs. Voici le résultat en RAM.


Il est important de noter que les exemples devraient tous fonctionner en théorie avec n'importe quel compilateur. Cependant, certains exemples peuvent être rares et pourraient provoquer des problèmes avec certains compilateurs. S'il vous plaît laissez-nous savoir dans les commentaires si vous rencontrez un problème.


Embarqué

  1. Le cloud et comment il change le monde informatique
  2. ST pilote l'IA vers les périphériques embarqués de périphérie et de nœud avec la boîte à outils de développement de réseau neuronal STM32
  3. MODULE DE DONNÉES :moniteurs à cadre ouvert de grande taille avec une luminosité élevée et une fonction easyTouch
  4. Micropuce :ADC 24 bits et 16 bits avec des débits de données jusqu'à 153,6 kSPS
  5. Contrinex :capteurs intelligents et barrières immatérielles de sécurité compatibles avec le cloud avec interface Bluetooth
  6. Tableaux en C++ | Déclarer | Initialiser | Pointeur vers des exemples de tableaux
  7. Allocation dynamique C++ de tableaux avec exemple
  8. Comment rendre l'IOT réel avec Tech Data et IBM Part 2
  9. Comment rendre l'IoT réel avec Tech Data et IBM Part 1