[size=+2]Cómo Construir Un Letrero Matricial De LEDs[/size]
Un panel matricial es uno de los proyectos más atractivos en el mundo de la electrónica. Su elaboración puede ser sencilla por su funcionamiento, aunque algo complicada por la implementación del hardware.
En esta oportunidad aprenderemos a diseñar un panel de 8 filas y de 64 columnas, es decir, de 512 LEDs, pero verás que ampliar o reducir el tamaño será tan simple como añadir o quitar registros en el hardware o cambiar un solo número en el software.
Este es el primer artículo que escribo para forosdeelectronica pero espero publicar otros periódicamente, ya no pensando en los PIC sino en los AVR.
[size=+2]El hardware[/size]
Sabemos que para encender un LED necesitamos de una señal de control, aparte de la alimentación (Vcc o GND), ¿cierto? Con esto en mente deberíamos suponer que para un letrero de 515 LEDs se necesitarían de 512 señales saliendo del microcontrolador, más o menos como en la siguiente figura:
Pero no es así. Podemos resolver parte de este problema multiplicando las señales del microcontrolador con ayuda de dispositivos como multiplexores, decodificadores o registros serie-paralelo como el 74164, 74595 o el CD4094. Los dos últimos son muy parecidos y son a la vez mejores que los primeros porque cuentan con doble buffer. Uno para almacenar internamente los datos seriales que van ingresando al registro y otro que se conecta al exterior. Más adelante veremos los beneficios de esta arquitectura.
Todos estos registros son de 8 bits pero tienen la característica de poder ser montados en cascada para multiplicar sus salidas. Por ejemplo, en la siguiente figura se muestra cómo conectar varios registros 74595 en cascada. Se pueden ir añadiendo tantos registros como salidas paralelas se desee.
Por otro lado, si nos basamos solo en este mecanismo para ampliar nuestras señales, para controlar los 512 LEDs tendríamos que usar 512/8 = 64 registros de 8 bits, lo cual nos llevaría a un circuito muy difícil de implementar además de bastante costoso. La técnica para salvar este segundo inconveniente es un artificio que consiste en encender grupos de LEDs en tiempos diferentes pero con la suficiente frecuencia como para dar la impresión de que estuvieran encendidos todos al mismo tiempo.
Obviamente, en un letrero matricial los LEDs quedan mejor agrupados en filas y/o columnas. En la siguiente figura los ánodos de los LEDs se unen formando las columnas y los cátodos se unen formando las filas (rows). También se puede armar una configuración alternativa invirtiendo la polaridad de todos los LEDs. En ese caso los transistores serán de tipo PNP.
Los valores de las resistencias R1 a R64 dependen de la corriente que tiene que fluir por los LEDs, la cual a su vez depende de los mismos LEDs. Hay que tener en cuenta que los LEDs no estarán prendidos al 100 % sino la octava parte (por las ocho filas) y también que la corriente promedio no siempre es proporcional al brillo del LED prendido, es decir, que un LED esté prendido la octava parte no significa que vaya a brillar ocho veces menos
Por otro lado, los transistores deben tener la capacidad de controlar la corriente proveniente de todos los LEDs de cada fila. En algunos casos bastará con usar el ULN2803.
[size=+2]Los barridos[/size]
Una vez estructurado el hardware de la matriz de LEDs nos damos cuenta de que podemos encender los LEDs que queramos de cualquier fila o de cualquier columna simplemente activando las coordenadas de dichos LEDs. Por ejemplo, si queremos prender los LEDs de las columnas 0, 3, 4, 7 y 63 de la fila 5 se vería así:
Sin embargo, no es posible encender varios LEDs que pertenezcan a diferentes filas y diferentes columnas al mismo tiempo. Es aquí donde entra a jugar el software.
Por ejemplo en la siguiente animación se muestra como para visualizar la letra G se encienden los LEDs correspondientes pero en tiempos diferentes.
La primera figura muestra la secuencia del barrido en cámara lenta pero en la práctica los barridos serán tan rápidos que los LEDs se verán como en la segunda figura.
[size=+2]Los caracteres[/size]
De lo visto anteriormente queda claro que encendiendo los LEDs convenientemente podemos formar en el letrero la figura que deseemos. Será el microcontrolador quien de acuerdo con su programa se encargue de generar los barridos activando las filas y columnas adecuadamente según un patrón establecido. Este patrón corresponde a letras, figuras o números que queramos y se puede estructurar de diversas formas.
Vamos a representar el patrón con una matriz de datos, donde cada dato represente una columna del panel de LEDs. De esta forma, si asignamos un 0 a un LED apagado y un 1 a un LED prendido, podemos establecer a partir de cada columna un byte de dato. Luego podremos agrupar ordenadamente todos estos datos y escribirlos en un formato conocido.
Por ejemplo, para el pequeño texto de arriba la matriz escrita en lenguaje C quedaría algo así:
Esta matriz puede tener cualquier nombre pero de aquí en adelante me referiré a ella como matrix.
[size=+2]Generación automática de matrix[/size]
Ya vimos que para generar nuestra matrix que se visualizará en el panel de LEDs hace falta conocer el sistema binario y/o hexadecimal. Pero para quienes no tengan la paciencia de componerla manualmente sobre todo si quieren experimentar con textos grandes, les presento una de varias herramientas que encontré en Internet. Se llama LCD font maker y, aunque fue diseñado para componer patrones de caracteres o gráficos para displays LCD o GLCD, también nos servirá para nuestro panel de LEDs. Su uso es bastante fácil de descubrir, así que no entraré en muchos detalles. Los pasos que debemos seguir son:
[size=+2]El código fuente[/size]
La elaboración del código dependerá de varios factores, como el tamaño del panel, la forma cómo se presenta el texto (efecto), la longitud de los mensajes, de si los mensajes son estáticos o si se programan en tiempo de ejecución, etc. En esta práctica el panel solo muestra un mensaje en desplazamiento.
Por tanto el código fuente será muy simple y se podrá adaptar para compilarlo para cualquier microcontrolador. Yo ya estoy harto de usar los PICs pero veo que siguen siendo los más populares, así que lo volveré a hacer. Usaré el PIC16F84A porque es el más fácil de conseguir.
´
El código está hecho en lenguaje C y se compila con BoostC. Una limitación de este compilador es que las matrices constantes (en rom) admiten como máximo 256 bytes.
Si se presentan los suficientes interesados, también podría escribir una versión en lenguaje ensamblador y hasta en Basic, pero confío en la extensa explicación de este código y creo que eso no hará falta.
[size=+2]Descripción del programa[/size]
[size=+2]La simulación[/size]
Dudo que todos los lectores de este artículo consigan implementar en la práctica real un letrero matricial completo debido a la relativa complejidad del hardware, pero creo que al menos podrán ver su diseño en una buena simulación gracias a Proteus.
Debemos notar que para la simulación en Proteus no es necesario armar el circuito completamente. Para este diseño por ejemplo he ignorado las resistencias y los transistores de las columnas y filas del panel.
Se puede (o debe) editar el parámetro Minimum Trigger Time de las matrices de LEDs para mejorar la visualización de los LEDs sobre todo si se cambia la frecuencia del XTAL.
El realismo de simulación también dependerá de la potencia de ordenador. En ordenadores lentos el contenido del panel se desplaza más lentamente, aunque se puede mejorar la animación modificando algunos parámetros, como la cantidad de barridos por frame en el código fuente, solo para fines de la simulación.
[size=+2]Descargas[/size]
En el siguiente enlace podrás encontrar todos los archivos relacionados con esta práctica: el circuito, el código fuente, el archivo .hex, el archivo .cof, el archivo .dsn para Proteus y hasta un diseño que trabaja con un microcontrolador AVR.
Descargar archivos
Y así, amigos, hemos llegado al final de este artículo. Si tienen comentarios o inquietudes al respecto, no duden en escribirlos. Hasta la próxima.
Un panel matricial es uno de los proyectos más atractivos en el mundo de la electrónica. Su elaboración puede ser sencilla por su funcionamiento, aunque algo complicada por la implementación del hardware.

En esta oportunidad aprenderemos a diseñar un panel de 8 filas y de 64 columnas, es decir, de 512 LEDs, pero verás que ampliar o reducir el tamaño será tan simple como añadir o quitar registros en el hardware o cambiar un solo número en el software.
Este es el primer artículo que escribo para forosdeelectronica pero espero publicar otros periódicamente, ya no pensando en los PIC sino en los AVR.
[size=+2]El hardware[/size]
Sabemos que para encender un LED necesitamos de una señal de control, aparte de la alimentación (Vcc o GND), ¿cierto? Con esto en mente deberíamos suponer que para un letrero de 515 LEDs se necesitarían de 512 señales saliendo del microcontrolador, más o menos como en la siguiente figura:

Pero no es así. Podemos resolver parte de este problema multiplicando las señales del microcontrolador con ayuda de dispositivos como multiplexores, decodificadores o registros serie-paralelo como el 74164, 74595 o el CD4094. Los dos últimos son muy parecidos y son a la vez mejores que los primeros porque cuentan con doble buffer. Uno para almacenar internamente los datos seriales que van ingresando al registro y otro que se conecta al exterior. Más adelante veremos los beneficios de esta arquitectura.
Todos estos registros son de 8 bits pero tienen la característica de poder ser montados en cascada para multiplicar sus salidas. Por ejemplo, en la siguiente figura se muestra cómo conectar varios registros 74595 en cascada. Se pueden ir añadiendo tantos registros como salidas paralelas se desee.

Por otro lado, si nos basamos solo en este mecanismo para ampliar nuestras señales, para controlar los 512 LEDs tendríamos que usar 512/8 = 64 registros de 8 bits, lo cual nos llevaría a un circuito muy difícil de implementar además de bastante costoso. La técnica para salvar este segundo inconveniente es un artificio que consiste en encender grupos de LEDs en tiempos diferentes pero con la suficiente frecuencia como para dar la impresión de que estuvieran encendidos todos al mismo tiempo.
Obviamente, en un letrero matricial los LEDs quedan mejor agrupados en filas y/o columnas. En la siguiente figura los ánodos de los LEDs se unen formando las columnas y los cátodos se unen formando las filas (rows). También se puede armar una configuración alternativa invirtiendo la polaridad de todos los LEDs. En ese caso los transistores serán de tipo PNP.

Los valores de las resistencias R1 a R64 dependen de la corriente que tiene que fluir por los LEDs, la cual a su vez depende de los mismos LEDs. Hay que tener en cuenta que los LEDs no estarán prendidos al 100 % sino la octava parte (por las ocho filas) y también que la corriente promedio no siempre es proporcional al brillo del LED prendido, es decir, que un LED esté prendido la octava parte no significa que vaya a brillar ocho veces menos
Por otro lado, los transistores deben tener la capacidad de controlar la corriente proveniente de todos los LEDs de cada fila. En algunos casos bastará con usar el ULN2803.
[size=+2]Los barridos[/size]
Una vez estructurado el hardware de la matriz de LEDs nos damos cuenta de que podemos encender los LEDs que queramos de cualquier fila o de cualquier columna simplemente activando las coordenadas de dichos LEDs. Por ejemplo, si queremos prender los LEDs de las columnas 0, 3, 4, 7 y 63 de la fila 5 se vería así:

Sin embargo, no es posible encender varios LEDs que pertenezcan a diferentes filas y diferentes columnas al mismo tiempo. Es aquí donde entra a jugar el software.
Por ejemplo en la siguiente animación se muestra como para visualizar la letra G se encienden los LEDs correspondientes pero en tiempos diferentes.

La primera figura muestra la secuencia del barrido en cámara lenta pero en la práctica los barridos serán tan rápidos que los LEDs se verán como en la segunda figura.
[size=+2]Los caracteres[/size]
De lo visto anteriormente queda claro que encendiendo los LEDs convenientemente podemos formar en el letrero la figura que deseemos. Será el microcontrolador quien de acuerdo con su programa se encargue de generar los barridos activando las filas y columnas adecuadamente según un patrón establecido. Este patrón corresponde a letras, figuras o números que queramos y se puede estructurar de diversas formas.
Vamos a representar el patrón con una matriz de datos, donde cada dato represente una columna del panel de LEDs. De esta forma, si asignamos un 0 a un LED apagado y un 1 a un LED prendido, podemos establecer a partir de cada columna un byte de dato. Luego podremos agrupar ordenadamente todos estos datos y escribirlos en un formato conocido.

Por ejemplo, para el pequeño texto de arriba la matriz escrita en lenguaje C quedaría algo así:
Código:
const char matrix[] = {0x00, 0xFF, 0x10, 0x28, 0x44, 0x82, 0x00, 0xFF, 0x11, 0x31, 0x51, 0x8E, 0x00, 0x00, 0x00};
[size=+2]Generación automática de matrix[/size]
Ya vimos que para generar nuestra matrix que se visualizará en el panel de LEDs hace falta conocer el sistema binario y/o hexadecimal. Pero para quienes no tengan la paciencia de componerla manualmente sobre todo si quieren experimentar con textos grandes, les presento una de varias herramientas que encontré en Internet. Se llama LCD font maker y, aunque fue diseñado para componer patrones de caracteres o gráficos para displays LCD o GLCD, también nos servirá para nuestro panel de LEDs. Su uso es bastante fácil de descubrir, así que no entraré en muchos detalles. Los pasos que debemos seguir son:
- Presiona el botón Choose font y escoge la fuente que desees. Yo escogí Verdana-Negrita-11 porque he visto que produce un tipo de letra que se ajusta bien a la altura del letrero. Puedes probar por tu cuenta para ver otros resultados.
- En Char input ingresa el texto que mostrará tu letrero; Yo dejé unos espacios al principio para que el texto empiece a aparecer desde el costado derecho. Con "Offset" puedes centrar y ajustar vertical y horizontalmente el patrón del texto. Hay que establecer "Height" (altura) a 8 y "Width" (ancho) lo ajustamos hasta que cubra todo el texto, en mi caso fue de 230.
- Ahora presiona el botón "Step 2: open the fonts dialog parameters" y en la ventana que se abre escoge los parámetros que indica la siguiente figura.
- Presiona el botón "Step 3: Making a single fonts with the current graphics" para generar la matriz hexadecimal. El resultado aparecerá como se muestra en la siguiente figura. Puedes seleccionarlo y copiarlo manualmente o mediante el botón "Copy all".
- Guarda la matriz generada para usarla en el código fuente. Esta matriz está por defecto declarada como "unsigned char code Bmp001" pero lo cambiaremos luego.
[size=+2]El código fuente[/size]
La elaboración del código dependerá de varios factores, como el tamaño del panel, la forma cómo se presenta el texto (efecto), la longitud de los mensajes, de si los mensajes son estáticos o si se programan en tiempo de ejecución, etc. En esta práctica el panel solo muestra un mensaje en desplazamiento.
Por tanto el código fuente será muy simple y se podrá adaptar para compilarlo para cualquier microcontrolador. Yo ya estoy harto de usar los PICs pero veo que siguen siendo los más populares, así que lo volveré a hacer. Usaré el PIC16F84A porque es el más fácil de conseguir.
´
El código está hecho en lenguaje C y se compila con BoostC. Una limitación de este compilador es que las matrices constantes (en rom) admiten como máximo 256 bytes.
Si se presentan los suficientes interesados, también podría escribir una versión en lenguaje ensamblador y hasta en Basic, pero confío en la extensa explicación de este código y creo que eso no hará falta.
PHP:
1
2 // ***************************************************************
3 // *** Letrero matricial V1.0 ***
4 // *** Written By Shawn Johnson ***
5 // *** Website: www.cursomicros.com ***
6 // *** Compiled for PIC16F84A with BoostC compiler ***
7 // ***************************************************************
8
9 #include <system.h>
10
11 #pragma DATA _CONFIG, _CP_OFF & _PWRTE_ON & _WDT_OFF & _HS_OSC
12 #pragma CLOCK_FREQ 10000000
13
14 #define DS porta.0 // 74595 serial data input
15 #define SH_CP porta.1 // 74595 shift register clock input
16 #define ST_CP porta.2 // 74595 storage register clock input
17
18 #define WIDTH 64 // LED panel width
19
20 rom char * matrix = // El contenido de esta matrix se puede reemplazar
21 {
22 /*------------------------------------------------------------------------------
23 ; Source file / text : www.cursomicros.com
24 ; Width x Height (pixels) :230X8
25 ------------------------------------------------------------------------------*/
26 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
27 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
28 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
29 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x1F,0xFC,0xE0,
30 0x7C,0x0F,0x0F,0x7C,0xE0,0xFC,0x1F,0x03,0x00,0x03,0x1F,0xFC,0xE0,0x7C,0x0F,0x0F,
31 0x7C,0xE0,0xFC,0x1F,0x03,0x00,0x03,0x1F,0xFC,0xE0,0x7C,0x0F,0x0F,0x7C,0xE0,0xFC,
32 0x1F,0x03,0x00,0x00,0xE0,0xE0,0x00,0x00,0x3C,0x7E,0xC3,0x81,0x81,0x81,0x42,0x00,
33 0x7F,0xFF,0x80,0x80,0x80,0x40,0xFF,0xFF,0x00,0xFF,0xFF,0x02,0x03,0x03,0x03,0x00,
34 0x4E,0x9F,0x99,0x99,0x99,0xF9,0x72,0x00,0x3C,0x7E,0xC3,0x81,0x81,0xC3,0x7E,0x3C,
35 0x00,0xFF,0xFF,0x02,0x01,0x01,0xFF,0xFE,0x02,0x01,0x01,0xFF,0xFE,0x00,0x00,0xFF,
36 0xFF,0x00,0x00,0x3C,0x7E,0xC3,0x81,0x81,0x81,0x42,0x00,0xFF,0xFF,0x02,0x03,0x03,
37 0x03,0x00,0x3C,0x7E,0xC3,0x81,0x81,0xC3,0x7E,0x3C,0x00,0x4E,0x9F,0x99,0x99,0x99,
38 0xF9,0x72,0x00,0x00,0xE0,0xE0,0x00,0x00,0x3C,0x7E,0xC3,0x81,0x81,0x81,0x42,0x00,
39 0x3C,0x7E,0xC3,0x81,0x81,0xC3,0x7E,0x3C,0x00,0xFF,0xFF,0x02,0x01,0x01,0xFF,0xFE,
40 0x02,0x01,0x01,0xFF,0xFE,0x00,
41 };
42
43 const unsigned int LEN = 230; // sizeof(matrix);
44
45 void main()
46 {
47 unsigned int bad; // Base index
48 unsigned int idx; // Index
49 unsigned char dato; // dato
50 unsigned char row; // Fila
51 unsigned char col; // Columna
52 unsigned char i;
53
54 trisa = 0x00; // Configurar puertos A
55 trisb = 0x00; // y B como salidas
56
57 porta = 0x00; // Inicializar puertos A
58 portb = 0x00; // y B a 0x00
59
60 while(1) // Bucle infinito
61 {
62 for(bad=0; bad<LEN; bad++) // Bucle para LEN "frames"
63 {
64 for(i=0; i<8; i++) // Bucle de 8 barridos por "frame"
65 {
66 for(row=1; row; row<<=1) // Cada barrido pasa por las 8 filas (23288 ciclos)
67 {
68 for(col=WIDTH; col; col--) // Cada fila iene WIDTH columnas (2911 ciclos)
69 {
70 idx = bad + col - 1; // Calcular índice de elemento en matrix
71
72 if(idx < LEN) // Si está dentro del rango
73 dato = matrix[idx]; // Extraer dato
74 else
75 dato = 0x00; // si no, asumir 0x00
76
77 if(dato & row) // Si el bit de row es 1
78 DS = 1; // colocar 1 en DS
79 else
80 DS = 0; // o, colocar 0
81
82 SH_CP = 0; //
83 SH_CP = 1; // Pulso de reloj para
84 SH_CP = 0; // validar el dato colocado
85 }
86 portb = 0x00; // Desactiva todas las filas temporalmente
87
88 ST_CP = 1; // Pulso para sacar todos
89 ST_CP = 0; // los datos cargados
90
91 portb = row; // Activar la fila actual
92 }
93 }
94 }
95 }
96 }
97
[size=+2]Descripción del programa[/size]
- La línea 9 incluye el archivo system.h, propio del compilador BoostC.
- La línea 11 establece los fuses o Bits de Configuración. Son 4 para el PIC16F84A y pueden ser más si se usa otro PIC.
- La línea 12 establece la frecuencia a tomar en cuenta para generar las funciones de delay, si se usan.
- La línea 14 define con el nombre DS el pin porta.0 (RA0) del PIC. Este será el pin por donde se sacarán los datos serialmente y se depositarán en los registros 74595.
- La línea 15 define con SH_CP el pin RA1 del PIC. También debe ir conectado a los pines SH_CP de los registros 74595.
- La línea 16 define con ST_CP el pin RA2 del PIC. Debe ir conectado a los pines ST_CP de los 74595.
- La línea 18 define la constante WIDHT (ancho) como 64. Este es el ancho del panel y lo puedes cambiar si en tu diseño es mayor o menor.
- Las líneas 20 a 41 declaran la matriz llamada matrix que contiene el patrón del mapa de bits que se visualizará en el panel de LEDs. Puedes reemplazar el contenido hexadecimal por los datos de tu mensaje que generaste hace dos apartados.
- La línea 43 declara la constante LEN como el tamaño de matrix. Este dato aparece con el nombre Width en los comentarios de la matriz generada automáticamente.
- Las líneas 47 a 52 declaran las variables bad, idx, row, col, i y dato.
- Las líneas 54 a 55 configuran los puertos A y B como salidas.
- Las líneas 57 a 58 inicializan los puertos a 0x00.
- La línea 62 es un bucle for cuyo contenido se ejecutará LEN veces. ¿Para qué?
Un panel matricial puede mostrar contenido de diferentes formas según lo programemos. El efecto que realiza el código presentado es visualizar un texto que se desplaza de derecha a izquierda, el más esperado. Este efecto se consigue visualizando secuencialmente diferentes segmentos o bloques de datos de matrix.
En la siguiente figura LEN es la longitud de matrix, cuyo contenido completo se mostrará en desplazamiento, y WIDTH es la longitud del panel de LEDs, en mi diseño vale 64 pero ya vimos donde modificarlo.
Si llamamos frame a la visualización en el panel de cada segmento de datos de matrix, ¿cuántos frames tendrá que haber para ver el texto desplazado por completo? La respuesta es LEN porque el contenido se desplaza una columna de LEDs cada vez.
Así que ya sabemos que el primer bucle for sirve para ejecutar LEN frames.
- La línea 64 es otro bucle for. Este bucle cuenta 8 ciclos porque cada frame se forma con 8 barridos de filas de LEDs. A mayor cantidad de barridos más lento será el desplazamiento del contenido.
- La línea 66 es el bucle for que se encarga de ejecutar los barridos. En cada barrido se activan las 8 filas del panel, una a continuación de otra. Row (fila) empieza en 1 (LSbit) y en cada ciclo se desplaza un bit a la izquierda gracias al operador <<.
- La línea 68 es un bucle for para serialmente cargar todos los registros 74595. Todos estos registros juntos y en cascada se comportan como un "mega-registro" serie-paralelo de WIDTH bits, es decir que sacarán en paralelo y al mismo tiempo los WIDTH bits que hayamos cargado serialmente.
Este bucle se ejecuta WIDTH veces pero con la variable col avanzando en modo descendente. Esto es porque los primeros bits en salir deberán ir a los registros que controlan las últimas columnas del panel de LEDs.
- La línea 70 calcula la posición del dato de matrix que se extraerá. En cada frame se empieza desde el elemento número bad y se toman los datos subsiguientes según el valor de col. Por eso la suma bad + col. Se resta 1 para compensar que col no llega a 0, sino hasta 1.
- La línea 70 empieza una sentencia if-else que evalúa si idx corresponde a un elemento de matrix. De ser así se extrae el dato, de lo contrario se asumirá que el dato es 0x00. Esto servirá para que al finalizar su desplazamiento el texto el texto siga su recorrido mostrando columnas vacías (0x00) en vez de terminar súbitamente.
- La línea 77 empieza una sentencia if-else que evalúa si el bit que marca row es 1 ó 0 para colocar dicho bit en el pin DS, el cual está conectado a la entrada serial de datos de nuestro "mega-registro".
- La líneas 82 a 84 generan un pulso en el pin SH_CP del PIC. Este debe ir conectado a todos los pines SH_CP de todos los registros 74595. Este pulso de reloj servirá para que el bit de dato presente en las entradas de los registros ingresen en ellos. Los datos se irán almacenando en los buffers internos de los registros, un bit por pulso de reloj.
- Las líneas 88 a 89 generan un pulso en el pin ST_CP, que está conectado a todos los pines ST_CP de los registros 74595. Mediante este pulso todos los datos que ingresaron serialmente y que están almacenados en los buffers internos salgan a los pines paralelos externos de los registros 74595 al mismo tiempo.
- La línea 91 activa la fila correspondiente del barrido.
- Como el bucle más interno se ejecuta en 982us, cada barrido se completa en 7,86 ms (7908 en la práctica) y como cada frame tiene 8 barridos, durará cerca de 60ms. En consecuencia, la imagen del panel se desplaza una columna de LEDs cada 60ms. Para medir estos tiempos puedes utilizar el Stopwatch de MPLAB o el Counter/Timer de Proteus.
[size=+2]La simulación[/size]
Dudo que todos los lectores de este artículo consigan implementar en la práctica real un letrero matricial completo debido a la relativa complejidad del hardware, pero creo que al menos podrán ver su diseño en una buena simulación gracias a Proteus.
Debemos notar que para la simulación en Proteus no es necesario armar el circuito completamente. Para este diseño por ejemplo he ignorado las resistencias y los transistores de las columnas y filas del panel.
Se puede (o debe) editar el parámetro Minimum Trigger Time de las matrices de LEDs para mejorar la visualización de los LEDs sobre todo si se cambia la frecuencia del XTAL.
El realismo de simulación también dependerá de la potencia de ordenador. En ordenadores lentos el contenido del panel se desplaza más lentamente, aunque se puede mejorar la animación modificando algunos parámetros, como la cantidad de barridos por frame en el código fuente, solo para fines de la simulación.

[size=+2]Descargas[/size]
En el siguiente enlace podrás encontrar todos los archivos relacionados con esta práctica: el circuito, el código fuente, el archivo .hex, el archivo .cof, el archivo .dsn para Proteus y hasta un diseño que trabaja con un microcontrolador AVR.
Descargar archivos
Y así, amigos, hemos llegado al final de este artículo. Si tienen comentarios o inquietudes al respecto, no duden en escribirlos. Hasta la próxima.