Por la cantidad de comentarios y pedidos que me han llegado para ampliar la matriz de 8x8 del siguiente post: http://electgpl.blogspot.com.ar/2013/11/matriz-8x8-mensaje-con-desplazamiento.html
He decidió darle una actualización y expandir la cantidad de matrices de 8x8 concatenadas para lograr un buen tamaño que se pueda leer bien.
En este caso he optado por 4 matrices de 8x8 multiplexadas, el núcleo del programa es el mismo que el del post de la matriz de 8x8, por lo que sigue con la misma simplicidad de código para su facilidad de compresión, solo que en este caso por un tema de cantidad de pines necesarios estamos obligados a expandir los puertos del microcontroaldor, por lo que he implementado el registro de desplazamiento 74595, es un registro con entrada serie y salida paralelo, funciona igual que el registro 74164 o CD4094 (podemos recordar en este post http://electgpl.blogspot.com.ar/2013/10/registro-de-desplazamiento-74164-con-ccs.html el funcionamiento del registro 74164). La diferencia del 74595 con los otros dos, es que ademas de ser un registro de desplazamiento el cual debemos ingresar un dato y sincronizarlo con un clock, se le suma un latch o memoria, el cual mantiene el dato en la salida independientemente de lo que suceda en los filpflop D del registro.
Esto nos juega a favor, ya que en el 74164 cuando queríamos enviar una serie de bits para convertirlos en un dato paralelo (por ejemplo para controlar displays de 7 segmentos), al no poseer el latch se podía ver en los leds de los segmentos el proceso de transición de bits desde el primero al ultimo ingresado de forma serial, hasta que se completara la conversión a paralelo y quedara estático.
Con el Latch realizamos la misma acción pero hasta que no se completa la conversión a paralelo no enviamos el valor a las salidas, por lo que los displays quedarían apagados y una vez que tenemos el valor paralelo activamos el latch y el valor pasa hacia la salida encendiendo correspondientemente los segmentos en lugar de que se vea el proceso de conversión mientras este sucede.
El latch también funciona como memoria, es decir una vez que se activa y el dato pasa a las salidas quedaran ahí indefinidamente hasta que cambiemos los datos en los flipflop de conversión y volvamos a activar nuevamente el latch.
Para esto tenemos un control mas que en el 74164 que es el Latch, por ende ahora tendremos Data, Clock y Latch, de todas formas siguen siendo pocos pines de control en el circuito.
El circuito como podremos ver es mas complejo producto de la necesidad de un integrado 74595 por cada matriz, estos 4 registros de desplazamiento se conectaran concatenados, es decís la salida del primero sera la entrada del segundo y así sucesivamente.
Luego el control de Clock y Latch sera común para todos los integrados.
Una característica extra de este registro de desplazamiento es que posee una mayor corriente de salida que los otros todos mencionados, por lo cual nos dará como resultado una matriz de leds mas brillante (este se debería acompañar de un driver de transistores a la salida del microcontrolador si quisiéramos aprovechar esta potencia).
Aquí les dejare un gif animado del firmware funcionando en la simulación (no tengo las matrices y todos los 74HC595). Tengan en cuenta que el gif no es muy fiel como un vídeo y por ende se pueden ver algunos parpadeos que en realidad no existen.
En este programa se han realizado algunas mínimas modificaciones de lo que era el programa de matriz de 8x8 que vimos anteriormente.
Se ha implementado el uso del registro de desplazamiento externo, por lo que he creado dos funciones, una para inicializar el 74595 y otra para incrementar el clock del mismo.
Como podemos ver se utilizan tres macros para asignar pines que en este caso he utilizado las primeras tres del puerto A, pero podríamos usar cualquiera.
Luego veremos la funcion f74595_init() que lo que hace es enviar un 1 al dato, luego un pulso de clock y luego un 0 al dato, esto es necesario porque recordemos que el registro de desplazamiento desplaza los bit que se ingresan de forma serie en un arreglo de flipflop concatenados, entonces con ingresar un solo bit en 1 y luego dejarlo a nivel bajo, con el uso del clock ese 1 se desplazara por todos los flipflop internos y por ende por todas las salidas, lo que creara un contador en anillo (similar al integrado 4017).
Esta función la llamaremos siempre que repitamos la función de refresco de pantalla, por ello se encuentra en el for de refresco. (este for realiza 24 refrescos de pantalla).
La función f74595_clock() lo único que hace es incrementar el clock y a su vez el latch ya que no solo queremos que el dato se desplace de un flipflop al otro sino también que pase a la salida sino no tendría sentido. Esta función se llamara en el lazo for donde barremos las columnas.
En el programa de la matriz de 8x8 realizábamos esta acción pero utilizando una mascara de bits que hacia referencia a un vector de 8 bit. En este caso no podemos usar esa mascara porque necesitaríamos 32bit y el microcontrolador solo maneja 8 en sus puertos.
Por ultimo, algo que habrán notado a primera vista, es que el vector donde se alojan los bits que se mostraran en la matriz para conformar una frace, ya no están en forma binaria "0b00000000" sino que están en forma decimal, que es lo mismo pero ocupa menos espacio en cuanto a la lectura nuestra, para el microcontrolador es lo mismo.
Por ello ahora como nuestra matriz tiene 32 columnas, necesitamos 32 espacios vacíos para que el mensaje comience desde la primera linea, para ello hay 32 ceros como podemos ver.
Luego viene el mensaje que esta también en decimal para que ocupe menos espacio y así le asignamos un renglón por cada letra.
Las letras están realizadas con tres columnas solamente para simplificar al máximo el programa, pero lo ideal seria usar por lo menos 5 columnas para que se pueda formar una letra como lo exija el estándar ascii.
Es un programa muy simple que no pasa el 10% de la memoria del PIC16F628A, por lo que es muy bueno para utilizar en casi cualquier microcontrolador.
Como en todo programa existen mejoras, en este caso podríamos realizar un vector de header y otro de trailer donde se alojen los primeros 32 columnas en cero, para que no moleste con nuestra frase, y luego llamarlos al inicio y al fin de la lectura del vector principal.
También podríamos crear las letras del alfabeto en forma de vectores o estructuras como para escribir la frase en un string y que automáticamente llame a las letras, esto nos ahorraría mucho código. Son algunas mejoras que se podrían implementar rápidamente pero que hacen al programa mas complejos, y lo principal es que uno logre entender la técnica de multiplexado, frames de pantalla, scroll y ahora sumamos registros de desplazamiento. Por ello me parece mejor dejar este programa hasta aqui, y mas adelante hacer uno con un alfabeto pre-grabado y demás.
La matriz a emplear es del tipo 8x8 con matriz de leds, es decir, estarán internamente conectados los ánodos por un lado y los cátodos por el otro formando filas y columnas.
Dependiendo del tipo de matriz, marca, color, tamaño, etc... es posible que el pinout difiera entre una y otra, por ende hay que tener en cuenta el datasheet de la matriz que tenemos disponible.
A continuación mostrare la interconexión interna de los leds en la matriz y el pinout correspondiente para una matriz de 2cm de lado.
He decidió darle una actualización y expandir la cantidad de matrices de 8x8 concatenadas para lograr un buen tamaño que se pueda leer bien.
En este caso he optado por 4 matrices de 8x8 multiplexadas, el núcleo del programa es el mismo que el del post de la matriz de 8x8, por lo que sigue con la misma simplicidad de código para su facilidad de compresión, solo que en este caso por un tema de cantidad de pines necesarios estamos obligados a expandir los puertos del microcontroaldor, por lo que he implementado el registro de desplazamiento 74595, es un registro con entrada serie y salida paralelo, funciona igual que el registro 74164 o CD4094 (podemos recordar en este post http://electgpl.blogspot.com.ar/2013/10/registro-de-desplazamiento-74164-con-ccs.html el funcionamiento del registro 74164). La diferencia del 74595 con los otros dos, es que ademas de ser un registro de desplazamiento el cual debemos ingresar un dato y sincronizarlo con un clock, se le suma un latch o memoria, el cual mantiene el dato en la salida independientemente de lo que suceda en los filpflop D del registro.
Esto nos juega a favor, ya que en el 74164 cuando queríamos enviar una serie de bits para convertirlos en un dato paralelo (por ejemplo para controlar displays de 7 segmentos), al no poseer el latch se podía ver en los leds de los segmentos el proceso de transición de bits desde el primero al ultimo ingresado de forma serial, hasta que se completara la conversión a paralelo y quedara estático.
Con el Latch realizamos la misma acción pero hasta que no se completa la conversión a paralelo no enviamos el valor a las salidas, por lo que los displays quedarían apagados y una vez que tenemos el valor paralelo activamos el latch y el valor pasa hacia la salida encendiendo correspondientemente los segmentos en lugar de que se vea el proceso de conversión mientras este sucede.
El latch también funciona como memoria, es decir una vez que se activa y el dato pasa a las salidas quedaran ahí indefinidamente hasta que cambiemos los datos en los flipflop de conversión y volvamos a activar nuevamente el latch.
Para esto tenemos un control mas que en el 74164 que es el Latch, por ende ahora tendremos Data, Clock y Latch, de todas formas siguen siendo pocos pines de control en el circuito.
El circuito como podremos ver es mas complejo producto de la necesidad de un integrado 74595 por cada matriz, estos 4 registros de desplazamiento se conectaran concatenados, es decís la salida del primero sera la entrada del segundo y así sucesivamente.
Luego el control de Clock y Latch sera común para todos los integrados.
Una característica extra de este registro de desplazamiento es que posee una mayor corriente de salida que los otros todos mencionados, por lo cual nos dará como resultado una matriz de leds mas brillante (este se debería acompañar de un driver de transistores a la salida del microcontrolador si quisiéramos aprovechar esta potencia).
Aquí les dejare un gif animado del firmware funcionando en la simulación (no tengo las matrices y todos los 74HC595). Tengan en cuenta que el gif no es muy fiel como un vídeo y por ende se pueden ver algunos parpadeos que en realidad no existen.
En este programa se han realizado algunas mínimas modificaciones de lo que era el programa de matriz de 8x8 que vimos anteriormente.
Se ha implementado el uso del registro de desplazamiento externo, por lo que he creado dos funciones, una para inicializar el 74595 y otra para incrementar el clock del mismo.
Como podemos ver se utilizan tres macros para asignar pines que en este caso he utilizado las primeras tres del puerto A, pero podríamos usar cualquiera.
Luego veremos la funcion f74595_init() que lo que hace es enviar un 1 al dato, luego un pulso de clock y luego un 0 al dato, esto es necesario porque recordemos que el registro de desplazamiento desplaza los bit que se ingresan de forma serie en un arreglo de flipflop concatenados, entonces con ingresar un solo bit en 1 y luego dejarlo a nivel bajo, con el uso del clock ese 1 se desplazara por todos los flipflop internos y por ende por todas las salidas, lo que creara un contador en anillo (similar al integrado 4017).
Esta función la llamaremos siempre que repitamos la función de refresco de pantalla, por ello se encuentra en el for de refresco. (este for realiza 24 refrescos de pantalla).
La función f74595_clock() lo único que hace es incrementar el clock y a su vez el latch ya que no solo queremos que el dato se desplace de un flipflop al otro sino también que pase a la salida sino no tendría sentido. Esta función se llamara en el lazo for donde barremos las columnas.
En el programa de la matriz de 8x8 realizábamos esta acción pero utilizando una mascara de bits que hacia referencia a un vector de 8 bit. En este caso no podemos usar esa mascara porque necesitaríamos 32bit y el microcontrolador solo maneja 8 en sus puertos.
Por ultimo, algo que habrán notado a primera vista, es que el vector donde se alojan los bits que se mostraran en la matriz para conformar una frace, ya no están en forma binaria "0b00000000" sino que están en forma decimal, que es lo mismo pero ocupa menos espacio en cuanto a la lectura nuestra, para el microcontrolador es lo mismo.
Por ello ahora como nuestra matriz tiene 32 columnas, necesitamos 32 espacios vacíos para que el mensaje comience desde la primera linea, para ello hay 32 ceros como podemos ver.
Luego viene el mensaje que esta también en decimal para que ocupe menos espacio y así le asignamos un renglón por cada letra.
Las letras están realizadas con tres columnas solamente para simplificar al máximo el programa, pero lo ideal seria usar por lo menos 5 columnas para que se pueda formar una letra como lo exija el estándar ascii.
Es un programa muy simple que no pasa el 10% de la memoria del PIC16F628A, por lo que es muy bueno para utilizar en casi cualquier microcontrolador.
Como en todo programa existen mejoras, en este caso podríamos realizar un vector de header y otro de trailer donde se alojen los primeros 32 columnas en cero, para que no moleste con nuestra frase, y luego llamarlos al inicio y al fin de la lectura del vector principal.
También podríamos crear las letras del alfabeto en forma de vectores o estructuras como para escribir la frase en un string y que automáticamente llame a las letras, esto nos ahorraría mucho código. Son algunas mejoras que se podrían implementar rápidamente pero que hacen al programa mas complejos, y lo principal es que uno logre entender la técnica de multiplexado, frames de pantalla, scroll y ahora sumamos registros de desplazamiento. Por ello me parece mejor dejar este programa hasta aqui, y mas adelante hacer uno con un alfabeto pre-grabado y demás.
- #include <16F628A.h>
- #FUSES NOWDT, HS, NOPUT, MCLR
- #use delay(clock=20000000)
- #define LARGO 56
- #define DATA PIN_A0
- #define CLOCK PIN_A1
- #define LATCH PIN_A2
- void f74595_init(){
- output_bit(DATA,1);
- output_bit(CLOCK,1);
- output_bit(DATA,0);
- }
- void f74595_clock(){
- output_bit(CLOCK,1);
- output_bit(CLOCK,0);
- output_bit(LATCH,1);
- output_bit(LATCH,0);
- }
- int const tabla[LARGO+64]={
- 0,0,0,0,0,0,0,0, //8 espacios
- 0,0,0,0,0,0,0,0, //8 espacios
- 0,0,0,0,0,0,0,0, //8 espacios
- 0,0,0,0,0,0,0,0, //8 espacios
- 255,137,129,0, //Letra E
- 255,128,128,0, //Letra L
- 255,137,129,0, //Letra E
- 126,129,129,0, //Letra C
- 1,255,1,0, //Letra T
- 126,129,241,0, //Letra G
- 254,17,14,0, //Letra P
- 255,128,128,0, //Letra L
- 0,0, //2 espacios
- 255,6,255,0, //Letra M
- 254,17,254,0 //Letra A
- 1,255,1,0, //Letra T
- 255,25,230,0, //Letra R
- 255,0, //Letra I
- 231,24,231,0, //Letra X
- 0,0,0,0,0,0,0,0, //8 espacios
- 0,0,0,0,0,0,0,0, //8 espacios
- 0,0,0,0,0,0,0,0, //8 espacios
- 0,0,0,0,0,0,0,0 //8 espacios
- };
- void main(){
- int i,j,k; //Variables contadores
- while(TRUE){ //Ciclo infinito
- for(i=0;i<LARGO+32;i++){ //Recorrido de tabla
- for(k=0;k<24;k++){ //Refresco de matriz
- f74595_init(); //Inicializa 74595
- for(j=0;j<32;j++){ //Barrido de Columnas
- f74595_clock(); //desplaza las columnas
- output_b(~tabla[j+i]); //Desplazamiento de tabla
- delay_us(20); //Demora de multiplexado
- }
- }
- }
- }
- }
La matriz a emplear es del tipo 8x8 con matriz de leds, es decir, estarán internamente conectados los ánodos por un lado y los cátodos por el otro formando filas y columnas.
Dependiendo del tipo de matriz, marca, color, tamaño, etc... es posible que el pinout difiera entre una y otra, por ende hay que tener en cuenta el datasheet de la matriz que tenemos disponible.
A continuación mostrare la interconexión interna de los leds en la matriz y el pinout correspondiente para una matriz de 2cm de lado.
Como podemos ver, hay dos diagramas, esto es otro punto a tener en cuenta, ya que se podría decir que en uno esta en Cátodo común y en otro en Ánodo común, aunque esto no es así ya que esa terminología aplica para los display de 7seg por ejemplo. En este caso vemos que los leds van para un lado o para el otro, esto nos juega a favor o en contra dependiendo del hardware que la controla, es decir. El 74HC595 soporta tanto un 0 como un 1 a su salida, ya que es a demanda por software, pero si queremos usar un driver ULN2803 por ejemplo, este es openColector, por ende debemos elegir bien la matriz a utilizar.
En mi caso me ha pasado que tras probar firmware con matrices de leds, algunas las tengo en "ánodo común" y otras en "cátodo común" y esto cambia todo, ya que la frase en lugar de ir de derecha a izquierda termina yendo de arriba hacia abajo y en negativo tal vez... para corregir esto, he re codificado el firmware para que solamente se cambie el programa y no exista la necesidad de modificar el hardware, es decir tengan la matriz que tengan les tiene que funcionar, al menos a mi me ha dado resultados.
- #include <16F628A.h>
- #FUSES NOWDT, HS, NOPUT, MCLR
- #use delay(clock=20000000)
- #define LARGO 56
- #define DATA PIN_A0
- #define CLOCK PIN_A1
- #define LATCH PIN_A2
- void f74595(int x){
- output_bit(DATA,x);
- output_bit(CLOCK,1);
- output_bit(CLOCK,0);
- output_bit(LATCH,1);
- output_bit(LATCH,0);
- }
- int const tabla[LARGO+64]={
- 0,0,0,0,0,0,0,0, //8 espacios
- 0,0,0,0,0,0,0,0, //8 espacios
- 0,0,0,0,0,0,0,0, //8 espacios
- 0,0,0,0,0,0,0,0, //8 espacios
- 255,137,129,0, //Letra E
- 255,128,128,0, //Letra L
- 255,137,129,0, //Letra E
- 126,129,129,0, //Letra C
- 1,255,1,0, //Letra T
- 126,129,241,0, //Letra G
- 254,17,14,0, //Letra P
- 255,128,128,0, //Letra L
- 0,0, //2 espacios
- 255,6,255,0, //Letra M
- 254,17,254,0 //Letra A
- 1,255,1,0, //Letra T
- 255,25,230,0, //Letra R
- 255,0, //Letra I
- 231,24,231,0, //Letra X
- 0,0,0,0,0,0,0,0, //8 espacios
- 0,0,0,0,0,0,0,0, //8 espacios
- 0,0,0,0,0,0,0,0, //8 espacios
- 0,0,0,0,0,0,0,0 //8 espacios
- };
- void main(){
- int i,j,k; //Variables contadores
- while(TRUE){ //Ciclo infinito
- for(i=0;i<LARGO;i++){ //Recorrido de tabla
- for(k=0;k<24;k++){ //Refresco de matriz
- f74595(0); //Posiciona la primer columna
- for(j=0;j<32;j++){ //Barrido de Columnas
- f74595(j); //desplaza las columnas
- output_b(tabla[j+i]); //Desplazamiento de tabla
- delay_us(50); //Demora de multiplexado
- }
- }
- }
- }
- }
Por ultimo les dejo un mapa de caracteres ASCII que les puede ser de utilidad a la hora de crear nuevos caracteres para formar palabras. Este mapa pertenece a los displays LCD de caracteres, y maneja el estándar de 5x7 puntos para crear el carácter.



