CODIFICACIÓN EN LENGUAJE C DE UN CONVERSOR HEXADECIMAL A 7-SEGMENTOS. Ing. Cosme Rafael Marcano Gamero, Msc, DEA. Profesor del Departamento de Ingeniería Electrónica – UNEXPO “Antonio José de Sucre” Puerto Ordaz . Estado Bolívar. cosmemarcano@gmail.com 1. INTRODUCCIÓN. Dentro del vasísimo campo de aplicaciones de la programación de computadoras se encuentra la emulación y simulación de procesos, máquinas, circuitos, etc. Dentro de las ventajas más resaltantes de l uso de simuladores/emuladores, está el hecho de que no se corre el riesgo de dañar componentes costosos a causa de errores inadvertidos de cableado o incluso de una mala conexión de la fuente de poder. Una vez depurado todo el diseño en el simulador/emulador, hay un mayor nivel de seguridad de lograr el éxito en su implementación fpisica. Por otra parte, no menos importante es el uso de este tipo de recursos para fines pedagógicos, ya que permiten explicar más a fondo el funcionamiento interno del recurso emulado o simulado. En este orden de ideas, se presenta en este trabajo la implementación en software de un simulador de un circuito digital conformado por un conversor de hexadecimal a 7 segmentos, como el 7447, perteneciente a la familia TTL (Transistor - Transistor Logic). 2. DESCRIPCIÓN DEL PROBLEMA. El circuito cuyo comportamiento se va a simular por software se muestra en la Figura 1. Fifura 1. Circuito digital cuyo funcionamiento se emula con la aplicación en C aquí presentada. Los detalles relacionados con el display de siete sementos se muestran en la Figura 2. El interruptor tipo dip que aparece en la Figura 1 puede ser implementado de varias maneras en el programa, como se verá más adelante. Figura 2. Detalles de un display de 7 segmentos. 2.1. SÍNTESIS DEL CIRCUITO 7447. El circuito TTL 7447 es un componente muy popular dentro del ámbito de los diseñadores y desarrolladores de circuitos digitales. Comprende, en una misma pastilla de silicio, de todos los elementos necesarisios para convertir un código binario en la combinación adecuada para mostrar el equivalente de ese códifo en uun display de siete segmentos (ver Figura 1). A continuación, aparece la Tabla de Verdad de un conversor de números headecinales (del 0 al 15 (0Fh)), de forma adecuada para ser desplegados en un Display de 7 segmentos, de manera semejante a como actúa un 7447 de la familia TTL, serie 74XXX, [1]. A 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 B 0 0 0 0 1 1 1 1 0 0 0 0 1 1 1 1 C 0 0 1 1 0 0 1 1 0 0 1 1 0 0 1 1 D 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 a 1 0 1 1 0 1 1 1 1 1 1 0 1 0 1 1 b 1 1 1 1 1 0 0 1 1 1 1 0 0 1 0 0 c 1 1 0 1 1 1 1 1 1 1 1 1 0 1 0 0 d 1 0 1 1 0 1 1 0 1 1 0 1 1 1 1 0 e 1 0 1 0 0 0 1 0 1 0 1 1 1 1 1 1 f 1 0 0 0 1 1 1 0 1 1 1 1 1 0 1 1 g 0 0 1 1 1 1 1 0 1 1 1 1 0 1 1 1 HEX 0 1 2 3 4 5 6 7 8 9 A b C d E F Figura 3. Tabla de verdad del 7447. Las expresiones simplificadas correspondientes a cada uno de los circuitos que controal siete segmentos se obtienen usando los Mapas de Karnaugh, como se muestra a continuación. . Segmento “a” ABVCD “00” “01” 11 10 “00” 1 0 1 1 “01” 0 1 0 1 11 1 1 1 0 10 1 1 1 1 ABVCD “00” “01” 11 10 “00” 1 1 0 1 “01” 1 0 1 1 11 1 1 0 0 10 1 0 0 1 ABVCD “00” “01” 11 10 “00” 1 1 0 1 “01” 1 1 1 1 11 1 1 0 1 10 0 1 0 1 ABVCD “00” “01” 11 10 “00” 1 0 1 1 “01” 0 1 1 1 11 1 0 0 1 10 1 1 1 0 ABVCD “00” “01” 11 10 “00” 1 0 1 1 “01” 0 0 1 0 11 0 0 1 1 10 1 1 1 1 ABVCD “00” “01” 11 10 “00” 1 1 1 1 “01” 0 1 0 1 11 0 0 1 1 10 0 1 1 1 ABVCD “00” “01” 11 10 “00” 0 1 0 1 “01” 0 1 1 1 11 1 0 1 1 10 1 1 1 1 a=CD'+A'C+BC+AD'+AB'C'+A'BD+B'D' Segmento “b” b=A'B'+B'C'+AC'D+A'C'D'+B'D'+A'CD Segmento “c” c=C'D+A'B+A'C'+A'D+AB'+B'C' Segmento “d” d=AC'+B'CD+A'CD'+BCD'+B'C'D'+AB'D+BC'D Segmento “e” e=AB+CD'+B'D'+AC Segmento “f” f=C'D'+AB'+AC+BD'+A'BC' Segmento “g” g=AB'+CD'+A'BC'+B'C+AD Figura 4. Mapas de Katnaugh para cada uno de los siete segmentos. Como muestra de los circuitos sintetizados por medio de los mapas de Karnaugh para controlar cada uno de los siete segmentos del display, la Figura 5 presenta el correspondiente al segmento e en forma de circuito digital, utilizando compuertas lógicas discretas [2]. La salida de este circuito es equivalente a la evaluzaciòn de la expresiòn lògica a nivel del programa en C, que se muestra más adelante. Figura 5, Diagrama del circuito que controla el segmento e del display 7 segmentos. 2.2. SÍNTESIS DEL PROGRAMA EN C. La codificación se efectuó en C/C++ Builder versión 6, de Borland, Inc., debido a la necesidad de utilizar la bliblioteca conio.h, la cual, aunque es soportada por este compilador, no es estándar ISO ni ANSI para el lenguaje C. Es menester recordar que esta biblioteca fue diseñada para poder hacer uso desde programas en C de las funcions asociadas a la int 21h del sistema de operación DOS (Disk Operating System), [3] , el cual, aunque fue muy popular durante los ochenta y sirvió de plataforma de desarrollo de Windows, ha sido reeplazado en popularidad y capacidades por éste último. El programa hace uso profuso de los operadores lógicos AND (&) y OR ( | ) que actúan sobre cada bit (bitwise operators), así como de aquellos de desplazamiento bit a bit, a la izquierda (<<) y a la derecha (>>), los cuales resultan muy útiles toda vez que, el desplazamiento a la derecha de un bit que forma parte de la representación binaria de un número entero equivale a dividir ese número por dos,mientras que un desplazamiento de un vit a la izquierda equivale a multiplicar el número por dos. Esta cualidad de los números binarios facilita el cálculo de potencias de dos. En principio, se generan los 16 números que serán tomados como hexadecimales, dentro de un lazo Repita Para. Cada dígito es convertido a binario, separando cada dígito binario como un elemento de un arreglo tipo entero, denominado b. Esto puede parecer dispendioso, pero resulta adecuado para fines pedagógicos. Seguidamente, el arreglo b es pasado como argumento de una función llamada _7447(), la cual implementa en software las operaciones de conversión de cada uno de los circuitos digitales que generan las señales para los siete segmentos del display. Esta función prepara una variable +unica, denominada sieteSeg, la cual contendrá los “encendidos” y “apagados” de cada segmento- Así, por ejemplo, cuando sieteSeg es igial a 63 en decimal, esto equivale a gfedcba = 0111111, es decir, todos los segmentos envendidos excepto el denominado g. La Figura 1 muestra la denominación estándar de los segmentos de un display de 7 segmentos. 3. ElL PROGRAMA. A continuación, se incluye el listado de instrucciones que conforman el programa en C, y que implmentan el circuito de la Figura 1. Nótese que los cuatro bits correspondientes a la representación en binario del número a convertir por parte del 7447 están identificados en la Tabla de Verdad y en los mapas de Karnaugh como A, B, C, y D- No obstante, dentro del programa, esos mismos bits son mapeados a ub areglo tipo entero , b, de la siguiente manera: A = b[3] B = b[3] C = b[3] D = b[0] de tal manera que, por ejemplo, la expresión correspondiente al segmento c del display, es decor, c = C'D+A'B+A'C'+A'D+AB'+B'C' viene a ser representada dentro del programa como: (!b[1] & b[0]) | (!b[3] & b[2]) | (!b[3] & !b[1]) | (!b[3] & b[0]) | (b[3] & !b[2]) | (!b[2] & !b[1]) El programa que a continuación se muestra puede ser copiado y pegado directamente en el editor de C/C++ Builder 6.0, para su compilación y ejecución. Obviamente, ninguna garantía, implícita o explícita, es exigible al autor en caso de presentarse algún problema durante la utilización de este programa. #include <conio.h> #include <stdio.h> int sieteSeg = 0; void Display7Seg(int _7Seg, int x, int y){ if (_7Seg & 1){ gotoxy(x,y); // a = CD'+A'C+BC+AD'+AB'C'+A'BD+B'D' printf("-a--"); } if (_7Seg & 2){ gotoxy(x+4, y+1); // b=A'B'+B'C'+AC'D+A'C'D'+B'D'+A'CD printf("|"); gotoxy(x+4, y+2); // b printf("b"); gotoxy(x+4, y+3); printf("|"); } if (_7Seg & 4){ gotoxy(x+4, y+5); printf("|"); gotoxy(x+4, y+6); // c printf("|"); gotoxy(x+4, y+7); // c printf("c"); gotoxy(x+4, y+8); // c printf("|"); } if (_7Seg & 8){ gotoxy(x, y+9); printf("-d--"); } if (_7Seg & 16){ gotoxy(x-1, y+5); printf("|"); gotoxy(x-1, y+6); printf("|"); gotoxy(x-1, y+7); printf("e"); gotoxy(x-1, y+8); printf("|"); } if (_7Seg & 32){ gotoxy(x-1, y+1); printf("|"); gotoxy(x-1, y+2); printf("f"); gotoxy(x-1, y+3); printf("|"); } if (_7Seg & 64){ gotoxy(x, y+4); printf("-g--"); } } // fin de Display7Seg // e // e // e // f // f void _7447(int b[]){ clrscr(); for (int j=3; j>=0; j--) printf("%d", b[j]); printf("\n"); // a= b[1] & !b[0] | !b[3] & b[1] | b[2] & b[1] | b[3] & !b[0] | b[3] & !b[2] & !b[1] | !b[3] & b[2] & b[0] | !b[2] & !b[0] if (b[1] & !b[0] | !b[3] & b[1] | b[2] & b[1] | b[3] & !b[0] | b[3] & !b[2] & !b[1] | !b[3] & b[2] & b[0] | !b[2] & !b[0]) { sieteSeg = (sieteSeg | 1); } // b = A'B'+B'C'+AC'D+A'C'D'+B'D'+A'CD if ((!b[3] & !b[2]) | (!b[2] & !b[1]) | (b[3] & !b[1] & b[0]) | (!b[3] & !b[1] & !b[0]) | (!b[2] & !b[0]) | (!b[3] & b[1] & b[0])) { sieteSeg = (sieteSeg | 2); } // c = C'D+A'B+A'C'+A'D+AB'+B'C' if ((!b[1] & b[0]) | (!b[3] & b[2]) | (!b[3] & !b[1]) | (!b[3] & b[0]) | (b[3] & !b[2]) | (!b[2] & !b[1])) { sieteSeg = (sieteSeg | 4); } // d = AC'+B'CD+A'CD'+BCD'+B'C'D'+AB'D+BC'D if ((b[3] & !b[1]) | (!b[2] & b[1] & b[0]) | (!b[3] & b[1] & !b[0]) | (b[2] & b[1] & !b[0]) | (!b[2] & !b[1] & !b[0]) | (b[3] & !b[2] & b[0]) | (b[2] & !b[1] & b[0])) { sieteSeg = (sieteSeg | 8); } // e = AB+CD'+B'D'+AC if ((b[3] & b[2]) | (b[1] & !b[0]) | (!b[2] & !b[0]) | (b[3] & b[1])) { sieteSeg = (sieteSeg | 16); } // f = C'D'+AB'+AC+BD'+A'BC' if ((!b[1] & !b[0]) | (b[3] & !b[2]) | (b[3] & b[1]) | (b[2] & !b[0])) { sieteSeg = (sieteSeg | 32); } // g = AB'+CD'+A'BC'+B'C+AD if ((b[3] & !b[2]) | (b[1] & !b[0]) | (!b[3] & b[2] & !b[1]) | (!b[2] & b[1]) | (b[3] & b[0])) { sieteSeg = (sieteSeg | 64); } int dec = 1, aux; int seg = 97; // 'a' int pos = 3; aux = sieteSeg; for (int i=0; i<7; i++){ gotoxy(pos, 4); printf ("%c",seg+i); gotoxy(pos,5); if (aux & 1) printf("1");else printf("0"); aux = aux >> 1; pos = pos + 3; } // getch(); } // 7447 int main(void) { int b[4] = {0,0,0,0}; int dec = 7; int j; for (dec=0; dec<16; dec++){ b[0] = dec & 1; //2(int) pow(2, 0); b[1] = (dec & 2) >> 1; // (int) pow(2, 1)) >> 1; b[2] = (dec & 4) >> 2; // (i (int) pow(2, 2)) >> 2; b[3] = (dec & 8) >> 3; // (i(int) pow(2, 3)) >> 3; sieteSeg = 0; _7447(b); Display7Seg(sieteSeg, 35, 10); gotoxy(1,2); printf("sieteSeg = %d\n", sieteSeg); getch(); } } Figura 6. Listado de instrucciones del porgrama bits7447.cpp 4. CONCLUSIONES. Los resultados obtenidos corresponden totalmente con los esperados, es decir, el programa genera correctamente la combinación adecuada para mostrar en el display de siete segmentos la representación del código hezadecimal que se le da como entrada a la función _7447(). Obviamente, hay detalles que no lucen evidentes, como las conexiones del circuito 7447 a la fuente de poder (Vcc y tierra), pero esos no pasan de ser detalles de apariencia. El objetivo principal aquí es poder entender y explicar el funcionamiento lógico del circuito. Otros detalles como la posibilidad de que el coruito permita sólo la representación de números de 0 al 9, es decir, decimal codificado en binario (BCD: binary coded decimal), son fácilmente implementables en C. Las salidas de este programa pueden ser orientadas hacia una tarjeta electrñonica que maneje dispositivos de siete segmentos de gran tamaño, como los utilizados en los establecimientos en donde se atiende gran número de personas (bancos, farmacias, etc.) mediante la entrega de un número. La salida hacia tales dispositivos se puede realizar a través de un puerto USB (Universal Serial Bus), de manera semejante a como se hacía anteriormente con puertos RS-232C. Obviamente, la tarjeta deberá contemplar los niveles de corriente y voltaje requeridos por aquellos emisores de luz de mayor tamaño. La velocidad de transmisión y acrualización del display, en este caso, no es crítica, dado que el tiempo promedio de atención a cada cliente es considerablemente grande en comparación a los tiempos de respuesta de una computadora. De manera semejante, se puede implementar versiones en software de todos los circuitos integrados de la serie 74XXX [1], colocarlos en una biblioteca de funciones, digamos _74XXX.lib, con sus respectivos prototipos colocados en un archivo _74XXX.h, y ponerlos a la disposición de estudiantes y usuarios, en general. 5. REFFERENCIAS (en elaboración) [1] Signetics. Signetics Integrated Circuits Data Book. pp 2-52/2-54, Dallas, TX. USA. [2] Hewes, John. (2011). Logic Gates. The Electronics Club. Disponible en: http://www.kpsec.freeuk.com/gates.htm [Consultado el 12/12/2011] [3] Norton, Peter. Programmer's Guide to the IBM PC. Microsoft Press. Washington, 1985.