Seguro que has escuchado más de una vez, hasta en las películas, hablar del sistema de numeración binario. Es el lenguaje de las máquinas, que son extraños unos y ceros (1 y 0), la forma de comunicación de los ordenadores, y muchas cosas más. Es difícil imaginarse el por qué un uno (1) y un cero (0) o un conjunto de ellos, pueden lograr las maravillas que la electrónica y la programación nos ofrecen actualmente. El código binario permite entender y diseñar sistemas electrónicos digitales. Su sistema de numeración es de vital importancia para la electrónica.
¿Qué es el Código Binario?
Los códigos binarios son un arreglo de dos caracteres, 1 y 0. Entonces, con sólo estos dos dígitos se pueden representar a todo el conjunto de números. También se pueden realizar operaciones lógicas y aritméticas. Incluso se pueden representar números imaginarios y reales. Dicha numeración se puede representar o medir en bits de información.
Sistema de Numeración Binario vs. Código Binario
Es importante aclarar algo antes de entrar en materia y es la diferencia entre sistema de numeración binario y código binario. En la imagen superior observamos un conjunto de unos y ceros, no encontramos otros dígitos ya que un sistema de numeración binario solo puede usar dos dígitos, en este caso el uno (1) y el cero (0). Un código binario y su sistema de numeración tienen dos características: la posición y el valor que se le asigna a esa posición. Si detallamos la imagen, podemos ver la letra R formada por una serie de unos y ceros. Los códigos binarios son un conjunto de símbolos y reglas que permiten construir todos los números válidos.
Importancia del Código Binario en la Electrónica
Todos los sistemas electrónicos digitales funcionan bajo el principio del código binario. Existen dos posibles estados llamados: verdadero-falso, alto-bajo ó 1-0. Estos dos estados son representaciones abstractas de regiones de voltajes específicos. Por ejemplo, para los circuitos integrados que operan a 5VDC, un 0 representa un voltaje entre -0.5V y 1.2V. Mientras que el 1 es representado por valores entre 2.2 y 5.5V.
Las compuertas lógicas utilizan el código binario para poder representar valores en sus entradas y proporcionar resultados. Las compuertas lógicas son los bloques con los que están construidos los flip-flops, sumadores, multiplexores, multiplicadores, decodificadores, registros (memorias), registros de desplazamiento (módulos de comunicación serial), etc. A su vez, estos bloques más complejos forman sistemas como procesadores, memorias, periféricos y unidades de control que son el principio de funcionamiento de los microprocesadores y los microcontroladores.
Lea también: ¿Qué es el Acuse de Recibo de la Declaración?
Para la electrónica, en especial en los sistemas embebidos como los microcontroladores o los microprocesadores, se utiliza el código binario para codificar información digital. Dicha información se puede transportar mediante pines de entrada/salida de estos dispositivos digitales. Algunos ejemplos de puertos de comunicación serial son: puerto serial, I2C, SPI, CAN, USB o JTAG. Entonces, conocer como funciona y se codifican/decodifican los números binarios en bits/bytes, etc, es importante para entender los protocolos de comunicación digitales.
Representación de Valores Binarios
Bits, Nibbles y Bytes
Los códigos binarios se agrupan para poder ser manejados de una mejor manera. Por ejemplo, la cantidad mínima de información que se puede representar en un sistema binario es el bit.
- bit: Un bit es la cantidad mínima de información que se puede representar en un sistema digital. Sólo puede valer 0 o 1. Verdadero o Falso.
- nibble: Un nibble es la agrupación de 4 bits. Este puede representar a todas las combinaciones con 4 bits, que son 16 combinaciones posibles.
- byte: Un byte es la agrupación binaria más común y ocurre cuando se agrupan 8 bits. Si agrupamos 8 bit o 2 nibble, ya se llama byte y así sucesivamente. Un byte es muy importante debido a que al inicio, los procesadores eran de 8 bits (hubo incluso procesadores de 4 bits). Por lo tanto, la información o los resultados se guardaban en memorias de 8 bits para ser más eficientes. En un byte de información se pueden guardar variables del tipo char.
Un kbyte es la agrupación de 1000 bytes. Aunque algunos autores incluso mencionan que son 1024 bytes. Dependiendo de la agrupación, ambas consideraciones pueden ser igualmente validas. Un Mbyte es la agrupación de 1 millón u 8 millones de bits. Hay que tener en cuenta que cuando se habla de kb (kilobits) o de kB (kilobytes), por tratarse del sistema de numeración binario y no del decimal, el prefijo kilo no significa 1000, sino la potencia de 2 más cercana a ese valor, 210 (1024).
El Kbit es distinto al kbyte, en el sentido que representa sólo 1000 bits. Es una métrica utilizada en los protocolos de comunicación digital que son seriales. Dado que los datos se transportan uno a la vez, es más recomendable agruparlos en bits, en lugar de bytes. Esta medida se utiliza mucho por ejemplo para medir la velocidad del internet. Generalmente pensamos que los kbits son 1000 bytes, pero esto es incorrecto. Cuando nuestros planes de internet dicen que tenemos 4GB, pensamos en 4 mil millones de bytes, pero en realidad son 4 mil millones de bits.
Representación con Signo
Por ejemplo, 8 bits de información permiten representar hasta 28 = 256 combinaciones, desde 0 hasta 255. Cuando se crea un número con signo, el bit 7 se usa para representar al signo, 0 en el último bit representaría el + y 1 el menos. Por lo tanto un número con signo de 8 bits, puede representar valores desde -127 hasta +127.
Lea también: Aprende a declarar el IVA correctamente
Códigos Binarios Específicos
Código 8421
El código 8421 permite formar números binarios de forma muy sencilla. Sólo se requiere recordar a estos cuatro números decimales. Con estos se pueden formar todos los números de 0 a 15. Por ejemplo, si queremos formar el número 7 en binario, sería: 4+2+1, por lo tanto el número que representa al 8 sería 0 y el número quedaría como: 0111. Ejemplo-2. Formar el número 12 en binario. El doce es la combinación o suma de 8+4. Entonces el 1 que representa al 8 y al 4 se colocan y el resto se pone en ceros. El resultado es: 1100.
Código BCD
La codificación BCD es muy utilizada para poder representar a los números de un reloj de tiempo real (en la electrónica de sistemas embebidos). Es una codificación similar a la 8421 en agrupaciones de 4 bits. Por ejemplo, el siguiente número binario, en la codificación normal, representa al 55: 0011 0111. Por el contrario, en la codificación BCD se representa al 5 en cuatro bits en 8421 y queda como: 0101, por lo tanto, en BCD quedaría como: 0101 0101.
Código ASCII
El código ASCII es una forma de representar caracteres de un sistema de escritura. Para las regiones donde utilizamos un abecedario de caracteres occidentales, se llama UTF-8. Consiste de 8 bits que representan a los caracteres. Un ejemplo que probablemente hayas escuchado es el código ASCII (American Standard Code for Information Interchange), que es un método de traducción de letras y símbolos a números. El código ASCII (American Standard Code for Information Interchange) se creó para representar los caracteres de la lengua inglesa. La letra A está representada por 8 bits. También podemos decir que está representada por 2 nibbles o un byte. 0100 0001 leído como un número binario, sería el número decimal 65. El código ASCII ha sufrido modificaciones a lo largo del tiempo, pero es considerado como el primer estándar que impulsó la computación.
Conversión entre Sistemas de Numeración
Podemos realizar conversiones de un sistema de numeración a otro. Recordarán por ejemplo, cuando aprendíamos los números decimales, que había unidades, decenas, centenas, millares, etc. Entonces de la misma forma, los códigos binarios o también llamados sistemas de numeración binario, presentan un arreglo similar. Por ejemplo, las posiciones se generan de derecha a izquierda comenzando por el cero. Cada posición representa el exponente de una base 2.
De Decimal a Binario
Ya sabemos que en el sistema de numeración binario solo podemos utilizar los dígitos 0 y 1; entonces, cómo hacemos para pasar nuestros números decimales a números binarios. Dividimos el número a convertir, 100 en este caso entre dos. El cociente es 50 y el resto o residuo es 0. Observamos si podemos continuar la división entre 2 logrando un cociente entero. En este caso se puede, cociente 25, residuo 0. Continuamos la división hasta donde sea posible, en este caso al llegar al cociente 1, ya no podemos dividir entre 2 y obtener un cociente entero. El resultado se obtiene colocando de izquierda a derecha, primero el último cociente obtenido, en este caso 1 y luego todos los residuos hasta el primero.
Lea también: SAT: Anulación y Corrección
De Binario a Decimal
Para poder decodificar un número binario debemos colocar sobre cada bit, la base del sistema elevada a una potencia. Y sobre ellas se han colocado las potencias de 2. Nos piden decodificar a decimal el número binario 11001011. Realmente primero hay que multiplicar 8*1, 4*0, 2*1 y 1*1, pero al multiplicar por la unidad obtenemos los mismos números y al multiplicar por cero, pues da cero y no afecta la suma.
El Sistema de Numeración Hexadecimal
El sistema de numeración hexadecimal lo utilizamos cuando programamos para reducir la cantidad de dígitos. Los números binarios se componen de gran cantidad de dígitos, y a medida que el sistema de numeración incrementa su base, la cantidad de dígitos disminuye. Por ejemplo 1000002 que es nuestro 32 decimal, en hexadecimal se representa como 2016. Cuando estamos programando y queremos representar un dígito hexadecimal, anteponemos 0x. Por ejemplo, el número hexadecimal A9, lo podemos separar en sus cuatro bits, A = 1010 y 9 = 1001. Luego formamos un solo número binario 10101001 y corresponde al hexadecimal A9. Puedes corroborarlo manualmente si lo deseas, o utilizar un convertidor de decimal a binario en Internet.
Variables y su Relación con el Código Binario en C para AVR
Vamos a ver la relación que hay entre el sistema de numeración binario y la programación. El lenguaje de las máquinas digitales se basa en el sistema de numeración binario. También se utiliza en la codificación de las variables en cualquier lenguaje de programación. Como por ejemplo, C/C++, el lenguaje Arduino, el lenguaje MBED, etc.
Tipos de Variables en C
En C, se pueden definir variables con tamaños que van desde los 8 bits hasta los 64 bits, ya sea en representación con o sin signo. Además de tipos de datos enteros, el compilador es capaz de manejar otros tipos, como float, double, char, etc. Los tipos básicos de variables en C serían:
| Tipo de Variable en C | Tamaño (bits) | Signo | Rango de Valores |
|---|---|---|---|
| char | 8 | Con signo | Desde -127 hasta +128 |
| unsigned char | 8 | Sin signo | De 0 a 255 |
| int | 16, 32, 64 | Con signo | Dependiendo del procesador |
| unsigned int | 16, 32, 64 | Sin signo | Dependiendo del procesador |
Acceso a Bits en Registros de Hardware con C (Bit-Fields en AVR)
En la programación de microcontroladores es bastante frecuente el chequeo y cambio de las variables, ya sea en todos sus bytes, un bit o grupo de bits en específico. A menudo, usamos una variable para almacenar el estado lógico de un proceso (0 o 1), por lo que si usamos una variable del tipo unsigned char, estaremos desperdiciando 7 bits, ya que esta variable solo toma valores de 0 y 1, alterando únicamente el valor del bit menos significativo. Puede representar números como valores binarios o hexadecimales. En algunos contextos, estas representaciones de números son más prácticas. Por ejemplo, se pueden representar los bits de un registro de hardware usando valores binarios.
Pero el lenguaje C tiene una potente y útil herramienta que nos permite definir un nombre para cada bit de una variable, con lo cual, por ejemplo, en una variable de unsigned char, podremos definir 8 variables que hagan referencia a cada bit del dato, incluso un bit puede no tener una referencia asociada, es decir, ese bit no se implementa. La estructura ocupa en memoria 1 byte, lo que hace es reservar un espacio de memoria correspondiente al número de bits usados dentro de la estructura, en el caso anterior se dice que son 5 variables unsigned char de 1 bit y 1 variable unsigned char de 3 bits, lo que nos da 1 byte de total. Ahora, para ver el uso de esta característica y aplicándola a los micros AVR, programemos un pequeño ejemplo en C, ¿qué les parece si hacemos una estructura BitField para acceder y modificar individualmente a cada bit del Registro DDRx, PORTx y PINx?
Primero que nada se debe saber que los registros de los puertos (y los demás registros) están mapeadas en el mapa de direcciones de memoria, es decir, son una dirección de memoria más. Se usa la macro definida en <sfr_defs.h> _SFR_MEM_ADDR(SFR) para obtener la dirección de cualquier variable o registro en memoria, en estos casos se obtienen las direcciones de DDRB, PORTB y PINB, las cuales son mapeadas en la estructura correspondiente. Utilice valores binarios y operaciones bit a bit para representar determinados bits y acceder a ellos. Por ejemplo, para obtener o establecer los valores de determinados bits, se pueden utilizar operaciones bit a bit.
