Categories: NoticiasTecnología

Consejos de firmware integrados: Cómo inicializar matrices en C con formas de onda de señal y otros datos de archivo

Este artículo muestra cómo inicializar matrices en un programa en C con valores de archivos de texto.

Este artículo muestra cómo inicializar matrices en un programa en C con valores de archivos de texto. Los datos no se almacenan en los archivos de origen. Los archivos se leen cuando se compila el programa. Se consideran matrices unidimensionales y multidimensionales. Los ejemplos también muestran cómo controlar colocar matrices en RAM o memoria no volátil y seleccionar qué archivos de datos usar para la inicialización.

El compilador utilizado para los ejemplos es GCC para ARM con un microcontrolador de 32 bits como objetivo. Todos los ejemplos usan el estándar C y trabajaron con este compilador.

Conceptos básicos de la inicialización de una matriz

Una matriz se puede inicializar con valores cuando se "declara". Aquí se muestra una declaración típica. Los valores dentro de las llaves se llaman "inicializadores".

Si el tamaño de la matriz no se especifica dentro de los corchetes, el tamaño será el número de inicializadores. Si hay menos inicializadores que el tamaño de la matriz, los elementos adicionales se establecen en 0. Es un error tener más inicializadores que el tamaño de la matriz.

Espacio en blanco

Los inicializadores deben separarse con comas. Agregar "espacio en blanco" está bien. En este caso, el espacio en blanco es "espacios en blanco" o espacios. El conjunto de caracteres de espacio en blanco incluye espacio en blanco (o espacio), pestaña, nueva línea, retorno de carro, pestaña vertical y avance de formulario. La nueva línea y el retorno de carro se utilizan para indicar el final de una línea en el código fuente C. ¿Sé el formulario de alimentación pero la pestaña vertical?

En general, a C no le importa si una declaración contiene espacios en blanco o si continúa en otra línea. La declaración aquí es equivalente a la de arriba. Es común ver muchas, muchas líneas de inicializadores para matrices grandes. Quizás incluso páginas. En algún momento, podríamos decir: "¿Hay una mejor manera?"

Inicializar una matriz desde un archivo

El código fuente C se ejecuta a través de un preprocesador antes de la compilación. Una característica comúnmente utilizada de los preprocesadores C es la "inclusión de archivos". Aquí hay una cita del famoso libro "El lenguaje de programación C" de Kernighan y Ritchie.

"La inclusión de archivos facilita el manejo de colecciones de # define y declaraciones (entre otras cosas) ".

Agregué la cursiva para "entre otras cosas". Aunque comúnmente incluimos archivos ".c" y ".h", al preprocesador no le importa la extensión del nombre de un archivo. Cualquier archivo de texto está bien. Entonces, la siguiente sintaxis funciona para inicializar una matriz.

El archivo no debe contener caracteres especiales que a veces están ocultos para formatear un documento. Mantenlo simple. Sin formato de texto enriquecido. No hay encabezados de columna. Solo números, comas y espacios en blanco. Aquí hay un archivo creado con el Bloc de notas de Windows.

Aquí está la matriz en la memoria que se muestra con un depurador. En este caso, la matriz está en RAM como lo indican las direcciones altas en la columna Ubicación.

Almacenar una matriz en memoria no volátil y seleccionar un archivo de datos

En el ejemplo anterior, la matriz es una variable global y nada especifica dónde colocar la matriz. El compilador y el enlazador suponen que el programa puede modificar la matriz y se coloca en la RAM. Los valores iniciales están en la memoria no volátil ("NVM", típicamente memoria Flash), y la matriz en RAM se inicializa a partir de estos datos mediante un código que se ejecuta antes del programa principal. El programa no accede a estos datos en NVM. Si la matriz no se modificará (es una "constante"), se coloca solo en NVM y el programa accede directamente a ella. Esto ahorra RAM, que a menudo es escasa. Decirle al compilador y al vinculador que una matriz no se va a cambiar y que la ubique en NVM generalmente se hace con el "const" Calificatorio. Aquí hay un ejemplo y un vistazo al resultado. La columna Ubicación lo muestra bajo en el mapa de memoria, que para este microcontrolador es la memoria Flash.

los #definir y #Si las declaraciones de preprocesamiento se pueden usar para dar opciones para ubicar la matriz y seleccionar qué archivos de datos se usan para la inicialización. Aquí hay un ejemplo que ofrece la opción de ubicar una matriz en RAM o NVM.

los #Si construir es un ejemplo de "inclusión condicional". En este caso, controla si el "const"Calificador se utiliza al declarar la matriz. Funciona porque la declaración puede estar en más de una línea o, dicho de otra manera, el espacio en blanco está bien.

Aquí hay un ejemplo del uso de la inclusión condicional para seleccionar el archivo para la inicialización.

Prueba con una matriz grande

Tenía un gran archivo de datos aleatorios que representaban una forma de onda de ruido y lo usé para probar la inicialización de una gran matriz en NVM. Aquí hay una gráfica de los datos y la declaración.

Aquí está el comienzo del archivo.

El archivo csv original no tenía la coma después de los valores. Estos se agregaron fácilmente mediante el uso de un editor que podría usar expresiones en las operaciones Buscar / Reemplazar. En este caso, utilicé la expresión para un delimitador de línea, " R". El Buscar fue " R" y el Reemplazar fue ", R". Una operación de Buscar / Reemplazar agregó todas las comas para 10,000 valores.

¡Todo funcionó muy bien y se compiló muy rápido! Aquí está el comienzo de la matriz en la memoria. El depurador separó muy bien la pantalla en grupos de 100 elementos cada uno.

Matrices multidimensionales

¿Qué pasa si los datos están organizados en dos o más dimensiones? Veamos una matriz bidimensional declarada como Prueba uint16_t[2][3]. En C, el subíndice derecho (3) es una matriz unidimensional con elementos contiguos en la memoria. El subíndice izquierdo (2) significa que hay dos de estos conjuntos de tres elementos. Esta es la disposición de la memoria de los seis elementos:

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

El orden en la memoria es importante porque acceder a elementos consecutivos en la memoria al incrementar el subíndice derecho es más rápido que acceder a los elementos al incrementar el subíndice izquierdo que requiere "saltos" a través de la memoria. Si la matriz contiene dos vectores de 1,000 elementos, la organización debería ser prueba[2][1000] para el acceso más rápido

Aquí hay un ejemplo de inicialización de una matriz bidimensional. Observe que los inicializadores se agrupan con llaves adicionales que agrupan los inicializadores para las matrices unidimensionales del subíndice correcto.

Este formato crea un problema para un archivo de datos que solo puede tener números, comas y espacios en blanco. ¿Qué sucede si se omiten las llaves adicionales?

El compilador llena la matriz yendo de izquierda a derecha a través de los inicializadores con el subíndice correcto llenando primero. El compilador que estoy usando me da una advertencia: "faltan llaves alrededor del inicializador". No hay problema si la cantidad de inicializadores es exactamente la misma que la cantidad de elementos en la matriz. Sin embargo, si no es igual, no está claro cómo llenar la matriz si no hay llaves para actuar como guías.

La matriz se puede llenar desde múltiples archivos con múltiples #incluir declaraciones. Aquí hay un ejemplo donde la inicialización está completamente entre corchetes con pares de llaves. Dejo de lado los detalles que se muestran en los ejemplos anteriores.

Inicializando matrices en uniones

Una unión es una variable que puede contener objetos de diferentes tipos que comparten la misma memoria y el compilador realiza un seguimiento de los objetos como si fueran cosas diferentes. Esta disposición podría ser útil para una aplicación incrustada con poca memoria. Aquí hay un ejemplo con vector[6] con una dimensión y matriz[2][3] con dos dimensiones Son dos matrices que ocupan las mismas ubicaciones en la memoria.

La regla para inicializar una unión es lo primero en la unión (vector[6]) se llena con los inicializadores. Si se invirtió el orden de las matrices, el compilador da una advertencia porque los inicializadores no están completamente entre corchetes. Observe las llaves alrededor del #incluir se duplican Creo que el conjunto externo encierra cualquier inicializador para la unión y el conjunto interno es para un tipo de matriz.

Aquí está el archivo. Tengo dos filas pero no importa. Simplemente más espacio en blanco.

Aquí está la matriz en la memoria. Observe la ubicación inicial de vector[ ] y matriz[ ][ ] son lo mismo.

¿Hay otras formas de inicializar matrices multidimensionales desde un solo archivo con solo números, comas y espacios en blanco? Por favor díganos agregando un comentario.

Consejo adicional: cuerdas

¿Qué pasa con las cuerdas? Aquí hay un ejemplo de inicialización de una cadena.

Un #incluir dentro de las comillas no funciona. Mi editor, que conoce la sintaxis de C, me da muchos signos de interrogación y subrayados ondulados. Caracteres para las nuevas líneas y el #incluir en sí son inicializadores! El pobre editor está confundido. Este desastre se compila pero la cadena se llena con los caracteres que vemos aquí y no del archivo.

La solución es poner las comillas en el archivo.

Luego, usa una declaración como esta.

Tenga en cuenta que las comillas alrededor del nombre del archivo son parte de #incluir sintaxis y no controlan inicializadores. Aquí está el resultado en RAM.


Es importante tener en cuenta que todos los ejemplos deberían funcionar En teoria con cualquier compilador Sin embargo, algunos ejemplos pueden ser poco comunes y podrían causar problemas con algunos compiladores. Por favor, háganos saber en los comentarios si encuentra un problema.

ga('create', 'UA-1454132-1', 'auto'); ga('require', 'GTM-MMWSMVL'); ga('require', 'displayfeatures'); ga('set',{'dimension1':'memory,computing,embedded,embedded-software,engineering-consulting'}); ga('set',{'contentGroup1':'memory,computing,embedded,embedded-software,engineering-consulting'});

ga('set',{'dimension3':"September 25, 2019"});

ga('set',{'dimension4':"Stephen Colley"});

ga('send', 'pageview');

!function(f,b,e,v,n,t,s){if(f.fbq)return;n=f.fbq=function(){n.callMethod? n.callMethod.apply(n,arguments):n.queue.push(arguments)};if(!f._fbq)f._fbq=n; n.push=n;n.loaded=!0;n.version='2.0';n.queue=[];t=b.createElement(e);t.async=!0; t.src=v;s=b.getElementsByTagName(e)[0];s.parentNode.insertBefore(t,s)}(window, document,'script','https://connect.facebook.net/en_US/fbevents.js'); fbq('init', '1808435332737507'); // Insert your pixel ID here. fbq('track', 'PageView'); fbq('track', 'ViewContent', { content_ids: ['memory','computing','embedded','embedded-software','engineering-consulting'], content_type: 'category'});

_linkedin_data_partner_id = "353081"; (function(){var s = document.getElementsByTagName("script")[0]; var b = document.createElement("script"); b.type = "text/javascript";b.async = true; b.src = "https://snap.licdn.com/li.lms-analytics/insight.min.js"; s.parentNode.insertBefore(b, s);})(); } if(jstz.determine().name().indexOf("Europe") === -1) { showSocialCode(); // NOT EU } else { showSocialCode(); window.addEventListener("load", function () { window.cookieconsent.initialise({ "palette": { "popup": { "background": "#252e39" }, "button": { "background": "#14a7d0" } }, "type": "opt-out", "content": { "message": "This website uses tracking cookies to ensure you get the best experience on our website.", "href": "https://www.allaboutcircuits.com/privacy-policy/", "dismiss": "OK, GOT IT" }, onInitialise: function (status) { var type = this.options.type; var didConsent = this.hasConsented(); if (type == 'opt-out' && didConsent) { console.log("eu"); //showSocialCode(); } },

onStatusChange: function (status, chosenBefore) { var type = this.options.type; var didConsent = this.hasConsented(); if (type == 'opt-out' && didConsent) { console.log("eu"); //showSocialCode(); } },

onRevokeChoice: function () { var type = this.options.type; if (type == 'opt-out') { console.log("eu"); //showSocialCode(); } },

}) }); }

Maria Montero

Me apasiona la fotografía y la tecnología que nos permite hacer todo lo que siempre soñamos. Soñadora y luchadora. Actualmente residiendo en Madrid.

Recent Posts

Máquina de mano Lean, Green, Raspberry Pi

Los días felices de la PDA y Blackberry han quedado definitivamente atrás, pero el factor…

2 years ago

Cómo pronosticar series de tiempo usando autorregresión

Tutorial sobre cómo pronosticar usando un modelo autorregresivo en PythonFoto de Aron Visuals en UnsplashForecasting…

2 years ago

Aquí están todas las formas en que puede cargar su AirPods Pro

Si tienes un iPhone, los AirPods Pro son la opción obvia para escuchar música, ¡aunque…

2 years ago

Las principales noticias tecnológicas del lunes: la prohibición de clientes de terceros de Twitter parece no ser un accidente

Ilustración de Alex Castro / The Verge Plus nuevos rumores sobre el quinto Galaxy Fold.…

2 years ago

AirPods Max 2: aquí están las características más solicitadas

Se rumorea que los auriculares premium de próxima generación de Apple, los AirPods Max 2,…

2 years ago

El remake de Dead Space continúa luciendo terriblemente genial en el nuevo tráiler de la historia

El desarrollador Motive Studio y el editor EA han lanzado un nuevo tráiler de la…

2 years ago