Matriz de 8x8 LED controlada con 2 shift register y PIC

Muchas personas experimentan a diario con arrays de 8x8 LED y un porcentaje de esas personas reflejan sus dudas en distintos sitios desperdigados por la red destinados a este mundillo de la electrónica y los microcontroladores.

Precisamente de una duda que se me planteó hace poco por correo electrónico surgió un pequeño proyecto a modo de ejemplo de un array de 8x8 LED; El cual funciona de maravillas tanto simulado como físicamente y es por eso que lo publico en esta ocación.

Dicho proyecto está basado en una serie de artículos anteriores dedicados a los shift register, en otras palabras es una implementación de los registros para usarlos con una matriz de LED.

Aquí presento el diagrama de conexión:


El PIC utilizado en esta ocación es el PIC16F88 por ser muy fácil de implementar y contar con oscilador interno.

La línea Load se conecta al pin B0 del PIC, Clk al B1, dClm a B2 y dLin a B3.

La lista de componentes es mas cuantiosa que variada pues esta compuesta por:
R1-R88 x Resistencias de 220Ω
R9-R168 x Resistencias de 3,9KΩ
Q1-Q88 x Transistores BC547 o similar

2 x 74HC595

64 x LED rojo de 5mm brillo standard

El código, escrito en CCS C, para probar el hardware es el que sigue a continuación, solo he dejado las letras pertinentes a PICROBOT, ya que sino se hace muy largo y repetitivo para mostrarlo como ejemplo, pero desde este link te puedes descargar el código completo con las letras en mayúsculas A-Z, el .HEX, el .COF para simularlo en el ISIS de Proteus y el .DSN con el diseño.

Hay dos versiones del código en este paquete, matriz8x8Q y matriz8x8. La primera es para cuando se usen los transistores a los cátodos de los LED y la segunda si los cátodos van directamente a las salidas del registro de desplazamiento encargado de controlar las columnas.

La única diferencia entre las dos versiones es que la primer versión (Q) no invierte y la segunda si lo hace, las salidas del registro encargado de controlar las filas.

Se podría haber solucionado el problema declarando o no una macro instrucción dirán algunos, después de todo lo único que varía es un caracter de una versión a otra, pero para no confundir, y como este es un ejemplo sencillo, decidí hacerlo así. En un futuro ejemplo de la implementación tal vez incluya una macro instrucción.

/*************************************************************************
**                                                                      **
**    Ejemplo básico para controlar una matriz de 8x8 LEDs con PIC.     **
**                                                                      **
**                      (c) 2010 Gerardo Ariel Ramírez                  **
**                            picblog@hotmail.com                       **
**                       http://picrobot.blogspot.com/                  **
**                                                                      **
**************************************************************************
**                                                                      **
**  Microcontrolador: PIC16F88           Oscilador: Interno - 8 MHz     **
**          Lenguaje: CCS C                                             **
**                                                                      **
*************************************************************************/

#include <16f88.h>      // Tipo de microcontrolador
#fuses INTRC_IO,MCLR    // Oscilador interno, MCLR activo
#fuses NOPUT,NOBROWNOUT // Sin Brownout reset ni Power up timer 
#use fast_io(all)       // La configuración de los puertos solo se hace al principio.
#use delay(clock=8M)    // Velocidad del oscilador interno 8 MHz

#define Load   PIN_B0   // Load (STCP ambos integrados) B0
#define Clk    PIN_B1   // Clock (SHCP ambos integrados) B1
#define dClm   PIN_B2   // Data para las columnas (DS integrado 1) BC2
#define dLin   PIN_B3   // Data para las lineas (DS integrado 2) B3

char  Memoria[96];      // 96 Bytes para la memoria (0 - 95)
char  Visor[8];         // 8 para el visor (8 columnas)

int1  flag;             // Flags de control
int1  flag2;
int   indx;             // Indice donde almacenará las nuevas columnas.
int   line;             // Linea que a mostrar.
int   time;             // Variables para el control de
int   ptime;            // la velocidad de desplazamiento.
int   t;                // Variable auxiliar.

void CargaMem(char Ascii);
void GuardaClm(char c);

#int_rtcc
void isr(){
   int Mul=128;         // Cada vez que ocurre la interrupcion
   if(++line>7)Line=0;  // selecciona la siguiente linea, si se pasa de 7 vuelve a 0.
   
   if(++ptime>5){      // Suma 1 a ptime. Si se pasa de 20
      ptime=0;          // lo pone en 0 y suma 1 a time.
      if(++time>200){   // Si se pasa de 200
         time=0;        // lo pone en 0
         Flag=true;     // y activa el flag.
      }
   }
   
   
   for(t=0;t<8;t++){    // Bucle 0 - 7 (Lineas)
      
      output_bit(dLin,!!(Visor[Line]&Mul));  // dLin es seteado con el valor
                                             // del bit de la fila actual.     
      if (Line==t)output_high(dClm);         // Si Line es igual a t
                                             // activa el bit correspondiente
      else  output_low(dClm);                // a la columna, sino lo desactiva.
      
      output_low(Clk);  // 
      output_high(Clk); // Rota el contenido interno del 74HC595.
      
      Mul>>=1;          // Divide la mascara que compara con Visor[] (128,64,32...)
   }
      output_low(Load);
      output_high(Load);// El contenido interno del integrado pasa a las salidas.
   
}
void main(){
   int k;   
   set_tris_a(0x00);
   set_tris_b(0x00);
   for (k=0;k<8;k++){
      Visor[k]=0;
   }
   for (k=0;k<96;k++){
      Memoria[k]=0;
   }                    // Limpia la memoria y el visor
   
   flag=true;           // Activo el flag para que cargue la memoria
   
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);  // Configuración del Timer0
   enable_interrupts(int_rtcc);              // Interrupcion por Timer0
   enable_interrupts(global);                // Interrupciones globales
   
   do{
      if (Flag){                 // Si el flag está activado
         flag2=true;             // Activa el flag2
         
         for (k=0;k<8;k++){      // Pasa el contenido de las primeras 8
            visor[k]=Memoria[k]; // columnas en memoria al visor
         }
         
         for (k=0;k<95;k++){        // Rota el contenido de toda la memoria
            Memoria[k]=Memoria[k+1];// a la izquierda 1=1+1, 2=2+1, n=n+1...
            
            if (Memoria[k]!=0){Flag2=false;} // Si hay alguna columna que no
                                             // esté vacía desactiva el flag2
         }         
         Memoria[95]=0;             // Limpia la ultima columna de la memoria
        
        if (Flag2){                 // Si flag2 está activo            
            indx=7;                 // a partir de la columna 7 
            CargaMem("PICROBOT");   // escribe PICROBOT            
         }
         Flag=false;                // Desactiva el flag
         
      }
   }while (true);    // Bucle infinito


}

void GuardaClm(char c){
   if (indx<94){
      Memoria[indx]=c;     // Guarda la columna en la ubicación actual de memoria
      indx++;              // y aumenta el indice
   }
}


void CargaMem(char ascii){    // Carga la memoria con el caracter deseado
   switch (ascii){    
      
      case('B'):
      GuardaClm(0b01111111);
      GuardaClm(0b01111111);
      GuardaClm(0b01001001);
      GuardaClm(0b01001001);
      GuardaClm(0b01111111);
      GuardaClm(0b00110110);      
      break;
      
      case('C'):
      GuardaClm(0b00111110);
      GuardaClm(0b01111111);
      GuardaClm(0b01000001);
      GuardaClm(0b01000001);
      GuardaClm(0b01100011);
      GuardaClm(0b00100010);     
      break;

      case('I'):
      GuardaClm(0b01000001);
      GuardaClm(0b01000001);
      GuardaClm(0b01111111);
      GuardaClm(0b01111111);
      GuardaClm(0b01000001);
      GuardaClm(0b01000001);      
      break;  

      case('O'):
      GuardaClm(0b00111110);
      GuardaClm(0b01111111);
      GuardaClm(0b01000001);
      GuardaClm(0b01000001);
      GuardaClm(0b01111111);
      GuardaClm(0b00111110);      
      break;      
      
      case('P'):      
      GuardaClm(0b01111111);
      GuardaClm(0b01111111);
      GuardaClm(0b00001001);
      GuardaClm(0b00001001);
      GuardaClm(0b00001111);
      GuardaClm(0b00000110);      
      break;
      
      case('R'):
      GuardaClm(0b01111111);
      GuardaClm(0b01111111);
      GuardaClm(0b00001001);
      GuardaClm(0b00011001);
      GuardaClm(0b01111111);
      GuardaClm(0b01100110);
      break;
      
      case('T'):
      GuardaClm(0b00000011);
      GuardaClm(0b00000001);
      GuardaClm(0b01111111);
      GuardaClm(0b01111111);
      GuardaClm(0b00000001);
      GuardaClm(0b00000011);
      break;      
   }
      GuardaClm(0b00000000);
}

39 comentarios:

  1. Anónimo7/9/10

    Muy buen articulo, muchas gracias por tus aportaciones.

    ResponderEliminar
    Respuestas
    1. Anónimo11/9/13

      muy buen ejemplo, solo un favor el link para el codigo y la descarga del esquema de coneccion esta roto en rapid sare no encuentra tu archivo podrias publicarlo de nuevo porfavor.

      Eliminar
  2. Anónimo26/9/10

    Magnifico articulo, muchisimas gracias

    ResponderEliminar
  3. Anónimo27/11/10

    excelente proyecto¡¡ y pues como menciona al inicio del proyecto que muchos tenemos dudas a la hora de encarar este proyecto y aun despues de leer y leer, y yo soy uno de ellos puesto que he leido y solo he podido comprender este tema con una matriz de 8x8 pero usando los puertos B y C del pic16F877A para filas y columnas.Ahora quiero realizar lo mismo pero con un shift register para controlar solo las 8 columnas y no he podido hacerlo.Realizo la programacion en proton ide.
    entonces si es posible que pusiera el codigo en este lenguaje o como hago funcionar el 74HC595 con el pic, me sera de muchisima ayuda . saludos¡¡¡

    ResponderEliminar
  4. Según entiendo necesitas hacer que el 74HC595 controle las columnas y, por otro lado, enviar el contenido de la fila por un puerto, ¿no?. Nunca he usado el Proton IDE, pero no creo que se diferencie mucho del BASIC, si me pasas el código a mi e-mail, puedo ver que se puede hacer.
    En teoría solo debes hacer la secuencia correcta para pasar los datos deseados al shift register, no tiene mas problema.

    Saludos.

    ResponderEliminar
  5. Anónimo31/1/11

    ¡Qué buen artículo mi hermano! Está muy bien documentado y lo mejor es que si posteas código fuente que FUNCIONA.
    Muchas gracias por el aporte...

    ResponderEliminar
  6. Anónimo28/2/12

    Hola como estas, podrias subir de nuevo el link con el codigo completo de todas las letras, el .HEX y el .COF. Mil gracias mi hermano !

    ResponderEliminar
  7. Anónimo21/4/12

    no se puede descargar... se puede cambiar el link para hacerlo. gracias

    ResponderEliminar
  8. Anónimo4/5/12

    Si aun no tienes el codigo me avisas para mandartelo

    ResponderEliminar
  9. Perdón por las demoras pero ahora estoy un poco liado y no tengo tiempo, pronto arreglaré los link y espero tener mas tiempo para hacer alguna nueva entrada.

    Saludos.

    ResponderEliminar
  10. Buen código. No lo he probado aun, pero parece ser lógico.
    Tenes buenos artículos dedicados al microcontrolado, me gusta.
    Un saludo desde Electgpl.

    ResponderEliminar
  11. Anónimo17/6/12

    Podrias por favor colocar un link en otro lado,desde donde se pueda descargar la simulacion.Gracias.
    dx8645@gmail.com

    ResponderEliminar
  12. Anónimo30/8/12

    por favor sube el ejemplo en otro lado
    megaupload esta cerrado por el FBI
    Gracias

    ResponderEliminar
  13. Ya está operativo el link con el ejemplo...

    Saludos.

    ResponderEliminar
    Respuestas
    1. Anónimo14/7/14

      Hola. No puedo abrir la página me podrías enviar los archivos a flomar2@prodigy.net.mx ? Por adelantado, muchas gracias

      Eliminar
  14. muy buen proyecto, pero por favor podrias arreglar el link de los esquematicos, esta roto otra vez, gracias.

    ResponderEliminar
  15. Cordial saludo muy buen tutorial, por favor podrias renovar el link de descarga conn la silumación en proteus, de antemano muchas gracias

    ResponderEliminar
  16. excelenta gracias por su contrubución

    ResponderEliminar
  17. Buen Aporte !!! .. oye un favor, podrías volver a subir el archivo, lo que pasa es que el link marca que ya no esta vigente .. de antemano gracias .. :D

    ResponderEliminar
  18. EXCELENTE AMIGO HE ESTADO BUSCNADO UN TUTO PARA HACER LETRAS CON UNA MATRIZ DE LED 8X8 EN CCS, NO SE SI PUEDAS VOLVER A SUBIR EL CODIGO O MANDARMELO AMI CORREO POR FAVOR, palerstuuns@hotmail.com

    ResponderEliminar
  19. Anónimo11/6/13

    hola!! es lo que andaba buscando pero ya no se encuentran los archivos en el link de descarga, los podrias volver a subir? saludos!
    o mandar a mi correo nbabigatronic@hotmail.com




    ResponderEliminar
  20. Anónimo21/7/13

    si porfa bor lo estoy buscando yo tmb podrias resubir el codigo, el link murio

    ResponderEliminar
  21. Saludos. El link está muerto.

    ResponderEliminar
  22. Favor enviar los archivos a jose5807@hotmail.com, si es posible. Gracias.

    ResponderEliminar
  23. Excelente me puedes enviar a esquivelchero@hotmail.com. Gracias

    ResponderEliminar
  24. Me lo podrías mandar por correo?! principal1414@gmail.com.mx

    ResponderEliminar
  25. Excelente artículo, podrías por favor actualizar el Link de descarga

    mares.250@hotmail.com

    ResponderEliminar
  26. Anónimo28/12/13

    me lo mandas a:
    jorgelui8@hotmail.com

    ResponderEliminar
  27. excelente proyecto envíame a mi correo los datos HectorGomezCartagena@gMail.com

    ResponderEliminar
  28. Please, could yo send me the project to my email (rolorh@gmail.com), the link is broken. Thanks very much.

    ResponderEliminar
  29. me puedes pasar los datos tanto de conexión de proteus como la programación te lo agradeceria mucho mi correo es omarhizaki15@hotmail.com

    ResponderEliminar
  30. buenas, lo estoy simulando con proteus, pero no me manda la carga a dLin, a alguien mas le paso?

    ResponderEliminar
  31. disculpa para agregar otras 3 matrices solo debo conectarlas en serie, los shif registrer.

    ResponderEliminar
  32. muy buen proyecto amigo gracias por tu publicacion me sirvio de mucho y si no es mucho pedir como haria el codigo si quisiera agregar mas matrices? gracias amigo

    ResponderEliminar
  33. Tienes que utilizar 8 lineas mas por cada matriz. Modificando el siguiente código, por ejemplo si quisieras utilizar dos matrices...

    for(t=0;t<8;t++)
    por:
    for(t=0;t<16;t++)

    Las salidas del integrado de abajo debes ponerlas a ambas matrices por medio de 16 transistores ( 2 por cada salida).

    El pin 9 del integrado que controla las lineas debes conectarlo a un tercer integrado que se conectará a la segunda matriz.

    Saludos.

    ResponderEliminar
  34. es exelecente amigo nadamas una pregunta como puedo manipular el tiempo de proyeccion aserlo q pase mas rapido o mas lento

    ResponderEliminar
  35. Hola Estimado gracias por mostrar tu trabajo, alguna vez has podido resolver el problema de no poder generar un arreglo mayor a los 96 elementos ?:
    Memoria[96];
    Usando los otros bancos de memoria restantes ? segun la hoja de datos este pic 16f88 cuenta con 368 Bytes repartidos en 4 bancos.

    saludos

    ResponderEliminar
  36. oye amigo, esta super excelente tu proyecto, yo apenas estoy empezando en la electrónica, podrías pasarme el código?

    mariovazquezc@gmail.com

    porfa. saludos

    ResponderEliminar


Tal vez le interese: