huborarduino.com

La web de Hubor para la simulación de Arduino con Proteus

Banner Guia Programacion Arduino Con Proteus

[Proteus versión 8.1]

Como hemos hecho otras veces durante este curso vamos a intercalar una lección más teórica en nuestra trayectoria. Este es un buen momento para aprovechar y hacer un repaso de los tipos de datos númericos que podemos utilizar en la programación de nuestro ARDUINO y aprender cuál es el que mejor se adapta a cada necesidad.

En lenguaje C es obligatorio declarar todas las variables y constantes que vamos a utilizar en nuestro código antes de escribir el código que se ejecutará. Por eso, en todos los ejemplos que hemos ido viendo a lo largo del curso, hemos empezado todos los programas declarando las variables con sentencias como:

Lec20 001

Para definir una variable la sintaxis que tenemos que utilizar es:

<tipo> <identificador>;

Los identificadores son los nombres que les asignamos a las variables para referirnos a ellas en el resto del código. Un identificador puede tener entre uno y treinta y dos caracteres. El primer carácter debe ser una letra o el signo de subrayado (el guión bajo '_'). El lenguaje C, a diferencia de otros lenguajes, distingue entre las mayúsculas y las minúsculas, por lo que los dos identificadores 'm1_fallo' y 'M1_fallo' son distintos y harán referencia a variables diferentes. Por último, no se pueden utilizar como identificadores ciertas palabras reservadas del lenguaje C, como, por ejemplo, 'for', 'function', 'while', 'boolean', etc.

Los tipos indican al compilador qué tipo de dato vamos a almacenar en esa variable. Hay cuatro tipos básicos: carácter, numérico entero, numérico de coma flotante y sin definir. Además cada uno de estos tipos básicos admiten los denominadores modificadores de tipo que nos permiten definir el tamaño del almacenamiento y si guardará números sólo positivos (sin signo) o servirá para manejar números positivos y negativos.

En este punto hay que hacer una salvedad importante. El lenguaje C define el tipo entero en función del microprocesador que estemos utilizando. Por lo tanto, si trabajamos con el ARDUINO UNO el tamaño de un entero es de 16 bits (dos bytes) pero si trabajamos con el ARDUINO DUE el tamaño será de 32 bits (cuatro bytes). Por eso a partir de ahora nos vamos a referir siempre a los tipos para el ARDUINO UNO y el lector deberá buscar las equivalencias en el caso de usar otro equipo ARDUINO:

Empezaremos por ver los tipos que podemos utilizar para contener números enteros sin signo. Según su tamaño tenemos los siguientes.

  • boolean puede almacenar un bit. Es decir que sólo podemos almacenar 0 ó 1.
  • unsigned char puede almacenar números de un byte. Números comprendidos entre 0 y 255
  • unsigned int puede almacenar números de dos bytes. Números comprendidos entre 0 y 65.535.
  • unsigned long puede almacenar números de cuatro bytes. Números comprendidos entre 0 y 4.294.967.295.
  • unsigned long long puede almacenar números de ocho bytes. Números comprendidos entre 0 y 18.446.744.073.709.551.615.

Realmente es difícil pensar que podamos necesitar números más grandes para el 99,999999% de los proyectos que vayamos a realizar.

Cuando no utilizamos el modificador 'unsigned' y podemos almacenar números positivos o negativos, los rangos de los números que se pueden almacenar serían:

  • char puede almacenar números de un byte. Números comprendidos entre -128 y 127
  • int puede almacenar números de dos bytes. Números comprendidos entre -32.768 y 32.767
  • long puede almacenar números de cuatro bytes. Números comprendidos entre -2.147.483.648 y 2.147.483.648
  • long long puede almacenar números de ocho bytes. Números comprendidos entre -9.223.372.036.854.775.807 y 9.223.372.036.854.775.807.

Sin embargo, la gestión de todos los tipos disponibles no es igual de sencilla. En concreto los números grandes (long long) son más complicados de utilizar en nuestro código cuando trabajamos con ellos. Veamos un ejemplo de código donde definimos una variable númerica entera de cada tamaño y luego tratamos de mandar los valores por el terminal virtual.

Lec20 002

Si compilamos, recibiremos el siguiente error:

Lec20 003

Es decir, que no tenemos una función print() que nos permita enviar este tipo de datos al terminal. Más adelante, veremos la solución a este problema. Por ahora, nos sirve con saber que podemos definir variables de todos estos tipos.

Es muy importante definir bien el tamaño para nuestras variables. Si utilizamos un tipo 'unsigned int' para una variable que puede contener números mayores de 65.535 nuestro programa no funcionará bien y dará errores. Y si abusamos de los tipos grandes podemos llegar a tener problemas de ocupación de memoria y haremos trabajar a nuestro procesador de forma innecesaria puesto que los cálculos donde se utilizan números de tipos más grandes (long o long long) necesitan más ciclos de ejecución para llevarlos a cabo que los que utilizan tipos menores (char o int).

Este es el momento adecuado para hablar de las uniones. Una unión es una posición de memoria que se usa por varias variables similares que pueden ser de tipos diferentes. Pongamos un ejemplo que nos ayude a entender su uso.

Lec20 004

Imaginemos que tenemos una variable de tipo 'int' que ocupa dos bytes y que queremos poder hacer referencia a cada uno de ellos por separado. El programa de ejemplo nos ofrece la solución. En las líneas 6 a 10, definimos una unión (a la que le daremos el nombre de num). Dentro de la unión definimos dos variables que ocuparán, como hemos visto, la misma posición de memoria. La primera, de nombre num16bits, es de tipo entero. La segunda, es una matriz de dos posiciones de nombre num8bits de tamaño char cada una de ellas. Luego, en la línea 12, declaramos una variable de tipo num (la nueva unión que acabamos de definir) con el nombre de prueba. En la línea 16 asignamos a la parte entera de la unión el valor en hexadecimal 0xFA5C. Observe que la forma de referirnos a cada uno de los elementos que forma una unión es mediante la sintaxis <nombre union>.<elemento union>.

El resultado de todo ello es el siguiente. 

Lec20 005

El compilador almacenará en la posición de memoria correspodiente el valor FA5C. La variable num16bits devuelve el numero entero de dos bytes. La variable Num8bits[0] devuelve el valor del byte de menor peso (5C) y la variable Num8bits[1] el byte de mayor peso (FA).

Si simulamos el programa, comprobaremos que el resultado es el explicado aquí.

Lec20 006

Veamos ahora, otro ejemplo que nos servirá para explicar cómo podemos utilizar la función print() para visualizar números 'long long' y para profundizar en el entendimiento de las uniones.

Lec20 007

En este caso utilizamos la unión para almacenar en una misma posición de memoria un número de ocho bytes, una matriz de dos posiciones de cuatro bytes cada una, una matriz de cuatro posiciones de dos bytes cada una y una matriz de ocho posiciones de un byte cada una.

Declaramos dos variables numPrueba y numPrueba2 de tipo igual a la union que acabamos de definir. Con la primera mostramos un ejemplo en hexadecimal para mostrar el número en formato de 64 bits, en dos partes de 32 bits, en cuatro partes de 16 bits y en ocho partes de 8 bits. Como vimos antes no podemos utilizar la función print() para imprimir el número completo de 64 bits.

Con la segunda tenemos un ejemplo de uso en decimal de un número de 64bits y la forma de mostrarlo utilizando la función print().

El resultado de la simulación es el siguiente:

Lec20 008

Es importante observar que los para ordenar bien los bytes tenemos que mostrar primero los de mayor peso.

El siguiente código de ejemplo nos permite comprobar como nuestro ARDUINO es capaz de trabajar con números muy grandes. Observe que para asignar el número de gran tamaño a la variable de 64 bits, hemos tenido que utilizar el sufijo LL para indicarle al compilador que queremos usar un número 'long long'.

Lec20 009

El resultado de la compilación es una cuenta incremental manejando números muy muy grandes.

Lec20 010

Y de esta manera, con la lección de hoy, ya hemos conseguido que nuestro ARDUINO maneje números realmente grandes.

 

Comparte este artículo en redes sociales

Submit to FacebookSubmit to Google PlusSubmit to TwitterSubmit to LinkedIn


Esta página es propiedad de Hubor.

2014.

¡Atención! Este sitio usa cookies y tecnologías similares. Si no cambia la configuración de su navegador, usted acepta su uso. Ampliar información