Código de Programación de una matriz de LEDS con lenguaje C

Como están amigos, en esta ocasión compartiré con ustedes el proyecto de la programación de una matriz de leds con lenguaje C.

Una matriz de leds es un arreglo físico de una determinada cantidad de estos diodos dispuestos de tal forma que los podamos controlar mediante la técnica de multiplexado.

Componentes de la matriz de leds.

Nuestro proyecto requiere de los siguientes elementos básicos:

  • 1 microcontrolador PIC 16f628
  • 4 Matrices de leds de 7×8
  • 4 registros de desplazamiento 74hc164

Principio de funcionamiento de la Matriz de Leds.

Esta matriz de leds funciona haciendo un barrido o escaneo por columnas, no por filas como otras matrices. Para esto requerimos los registro de desplazamiento, los cuales mediante un pulso enviado desde el MICRO activara columna por columna nuestra matriz.

Las columnas se activan una a la vez mostrando un patrón de columnas, en este caso cada caracter estará representado por 6 columnas.

A la velocidad de reloj de 10 MHZ cada columna se enciende aproximadamente 23 veces por segundo con una duración aproximada de 1.2 mili segundos. Esta velocidad es suficiente para engañar a nuestra vista y hacer parecer que vemos un mensaje luminoso completo desplazándose.

El efecto que generaría nuestra matriz es el mismo que este caballo que en realidad es una secuencia de fotografías.

La programación de la matriz de LEDS.

La programación de la matriz se ha realizado en lenguaje C usando el compilador CCS C compiler.

El principio de funcionamiento de la programación es el siguiente:

  1. Se escribe el mensaje que se desea mostrar en una variable del tipo CHAR
  2. Luego calculamos el ancho del mensaje.
  3. A continuación selecciona una determinada cantidad de caracteres del mensaje y se los descompone en columnas.
  4. Todas las columnas del los caracteres se almacenan en un BUFER.
  5. Mediante el escaneo de columnas se muestran una a una todas las columnas del BUFER.
  6. El BUFER luego es desplazado una cierta cantidad de columnas, lo que genera el efecto de desplazamiento del mensaje. SCROLLING.
  7. Al terminar el SCROLLING se seleccionan nuevamente una cantidad de caracteres del mensaje mediante un puntero que inicia desde el numero de caracteres desplazados en el SCROLLING anterior.
  8. El ciclo se repite hasta que se muestran todos los caracteres del mensaje.
#include "16f628.h"
// Variables del programa

unsigned int longitud;           //variable para guardar la longitud del mensaje
int BELO;                        // Velocidad de la matriz
int bf=0;                       //bf es el elemento del arreglo pf[]
int i;                          //variable índice malla principal 
int k;                          //variable índice para arreglo pf[]
int bo;
int jota,omega=0;              //variables indice para arreglo pf[]

const char mensaje[97]="Hola amigos de TECNOCIENCIA PERU 12345  "; // MENSAJE 
char pf[54];   // el Bufer PF es el bufer principal, almacena las 54 columnas de los 9 (5 que se ven y 4 que se desplazaran) Caracteres descompuestos mediante la fuwncion SWATCH

#include "LETRASCCS4.h"   // Archivo que contiene las letras 

void renglones(void);           //Funcion de rutina, no retorna nigun valor por ser void.
void reset(void);               // Funcion de rutina no retorna ningun valor por ser void.
void pulso(void);               // Funcion de rutina no retorna ningun valor por ser void

void main()
{ 
BELO=3;                   // Este valor comanda la velocidad
TRISA=0;                
TRISB=0;
PORTA=0x00;
PORTB=0X00;               // probar con transistor sin transistor 00 o ff
             
delay_us(5);              // SE DEBERIA ACTIVAR AL MOMENTO DE HACER LA PRUEBA DE LA SENTENCIA PULLUPS
reset();                  // EL RESET ES MUY IMPORTANTE SIN ESTE PIN DE RESET LA MATRIZ ES INESTABLE....

longitud=36;


while (1){



             for(omega=0;omega<longitud;omega=omega+4)    // Omega es un puntero de caracteres que avanza de 4 en 4 ya que el mensaje se desplaza 4 caracteres    
             {
            jota=0;
// ******** INICIA EL FOR QUE ACUMULA 9 CARACTERES EN EL BUFER PF (54 COLUMNAS )MEDIANTE LA FUNCION SWATCH  *********************************************
            for(k=0;k<9;k++)   
             {
             swatch(mensaje[k+omega]); // Llamamos a la funcion SWATCH que acomoda patrón de columnas del caracter Nro K+Omega en el arreglo  pf[] letra por letra en cada for
             continue;
             }
// ******** INICIA EL FOR QUE ACUMULA 9 CARACTERES EN EL BUFER PF (54 COLUMNAS )MEDIANTE LA FUNCION SWATCH  *********************************************             
             
 
          for(bf=0;bf<24;bf++)               // ACTIVA EL SCROLLING: Desplzamaiento a la izquierda de 4 caracteres equivalentes a 24 columnas
             {
               for(k=0;k<BELO;k++)          //RETRASA EL SCROLLING REPITIENDO EL BARRIDO K VECES
                 {
                    RA2=1;                     //0 CON TRANSISTOR ; 1 SIN TRANSISTOR,    ingresa DATO al 74hc164 'EL BIT QUE ACTIVA LAS COLUMNAS'
                    pulso();                   //libera Dato=1 por la primera columna
                    RA2=0;                     //1 CON TRANSISTOR ; 0 SIN TRANSISTOR.    ingresa DATO al 74hc164 'EL BIT QUE APAGA LAS COLUMNAS'
                   for (i=0;i<32;i++)         
                      {
                        bo=pf[bf+i];               //BO toma el valor en bits de cada una de las 54 columnas del BUFER PF.
                        renglones();               //La funcion renglones saca por el puerto B el valor de cada columna cargda en BO por medio de PF
                        delay_ms(1);               //activa siguiente columna
                        pulso();                   //se deja listo el 74hc164 para recibir la siguiente columna
                        PORTB=0X00;                //evita que encienda brevemente siguiente columna; 0x00= anodo con transistor;0xff anodo sin transistor
                        RA3=1;                    //0 CON TRANSISTOR ; 1 SIN TRANSISTOR
                       }
              }}}}    
}

//ASIGNA DATO EN RENGLON A BIT DE PUERTOS:
//R0=RB0,R1=RB1,R2=RB3,R3=RB4,R4=RB6,R5=RB7,R6=RA4
//RB2 Y RB5 SE RESERVAN PARA EL PUERTO SERIAL.


void renglones(void)
{
   PORTB=0Xff;                  //0x00 CON TRANSISTOR;0xff SIN TRANSISTOR
   RA3=1;                       //0 CON TRANSISTOR ; 1 SIN TRANSISTOR
   if (bit_test(bo,1)==1)      //asigna valores a bits. ==1, rbx=1 CON TRANSISTOR, rbx=0 SIN TRANSISTOR; 
   {RB0=0;}   
   if (bit_test(bo,2)==1)
   {RB1=0;}
   if (bit_test(bo,3)==1)      
   {RB3=0;}
   if (bit_test(bo,4)==1)      
   {RB4=0;}
   if (bit_test(bo,5)==1)      
   {RB6=0;}
   if (bit_test(bo,6)==1)      
   {RB7=0;}
   if (bit_test(bo,7)==1)      
   {RA3=0;}   
}

void reset(void)
{
RA0=0;
delay_ms(100);
RA0=1;
}

void pulso(void)
{
RA1=0; //CLK 0 RECIBE EL PRIMER DATO Y BLOKEA ENTRADA DE UN SEGUNDO DATO 
RA1=1; //CLK 1 LIBERA EL PRIMER DATO Y HABILITA ENTRADA DE SEGUNDO DATO
}

A continuación se muestra la librería de la tabla de los caracteres donde ademas se tienen las funciones que descomponen los caracteres en columnas y la función que almacena las columnas en el BUFER PF.

// Explicacion: la funcion Swatch identifica cada letra y la descompone en 6 columnas, la funcion letra coge esas 6 columnas y las 
// coloca en el arreglo pf hasta que se termina de llenar el arreglo pf con el numero de columnas declaradas en el programa proncipal.
void swatch(char bor);
void letra(char ro[]);               

//***TABLA DE CARACTERES Y SUS COLUMNAS******** 
// ******** Letras Minusculas *****************

const char AM[]={0x40,0XA8,0XA8,0XA8,0XF0,0X00};
const char BM[]={0XFC,0XA0,0XA0,0XA0,0X40,0X00};
const char CM[]={0X70,0x88,0x88,0x88,0x88,0X00};
const char DM[]={0x60,0x90,0X90,0X90,0XFE,0X00};
const char EM[]={0X70,0xA8,0xA8,0xA8,0xB0,0X00};
const char FM[]={0X00,0X10,0XFC,0X12,0X04,0X00};
const char GM[]={0X90,0XA8,0XA8,0XA8,0X78,0X00};
const char HM[]={0XFE,0X10,0X10,0X10,0XE0,0X00};
const char IM[]={0X00,0X00,0XF4,0X00,0X00,0X00};
const char JM[]={0X40,0X80,0X80,0X7A,0X00,0X00};
const char KM[]={0x00,0XFE,0X20,0X50,0X88,0X00};
const char LM[]={0X00,0X82,0XFE,0X80,0X00,0X00};
const char MM[]={0XF8,0X08,0X70,0X08,0XF8,0X00};
const char NM[]={0XF8,0X10,0X08,0X08,0XF0,0X00};
const char ENEM[]={0XFA,0X12,0X0A,0X0A,0XF2,0X00};
const char OM[]={0x70,0X88,0X88,0X88,0X70,0X00};
const char PM[]={0XF8,0X28,0X28,0X28,0X10,0X00};
const char QM[]={0X10,0X28,0X28,0X28,0XF8,0X00};
const char RM[]={0XF8,0X10,0X08,0X08,0X10,0X00};
const char SM[]={0X90,0XA8,0XA8,0XA8,0X48,0X00};
const char TM[]={0x08,0X08,0X7E,0X88,0X48,0X00};
const char UM[]={0X78,0X80,0X80,0X80,0X78,0X00};
const char VM[]={0X38,0X40,0X80,0X40,0X38,0X00};
const char XM[]={0X88,0X50,0X20,0X50,0X88,0X00};
const char YM[]={0x08,0X90,0X60,0X10,0X08,0X00};
const char ZM[]={0X88,0XC8,0XA8,0X98,0X88,0X00};


// *********** LETRAS MAYUSCULAS ************* 
const char A[]={0xFC,0X12,0X12,0X12,0XFC,0X00}; 
const char B[]={0xFE,0X92,0X92,0X92,0X6C,0X00};
const char C[]={0x7C,0X82,0X82,0X82,0X44,0X00};
const char D[]={0xFE,0X82,0X82,0X82,0X7C,0X00};
const char E[]={0xFE,0X92,0X92,0X92,0X82,0X00};
const char F[]={0xFE,0X12,0X12,0X12,0X02,0X00};
const char G[]={0x7C,0X92,0X92,0X92,0X74,0X00};
const char H[]={0xFE,0X10,0X10,0X10,0XFE,0X00};
const char RI[]={0x00,0X82,0XFE,0X82,0X00,0X00};
const char J[]={0x70,0X80,0X80,0X80,0X7E,0X00};
const char KA[]={0xFE,0X10,0X28,0X44,0X82,0X00};
const char L[]={0xFE,0X80,0X80,0X80,0X80,0X00};
const char M[]={0xFE,0X04,0X18,0X04,0XFE,0X00};
const char N[]={0xFE,0X08,0X10,0X20,0XFE,0X00};
const char O[]={0x7C,0X82,0X82,0X82,0X7C,0X00};
const char P[]={0xFE,0X12,0X12,0X12,0X0C,0X00};
const char Q[]={0x7C,0X82,0XA2,0X42,0XBC,0X00};
const char R[]={0xFE,0X12,0X32,0X52,0X8C,0X00};
const char S[]={0x4C,0X92,0X92,0X92,0X64,0X00};
const char T[]={0x02,0X02,0XFE,0X02,0X02,0X00};
const char U[]={0x7E,0X80,0X80,0X80,0X7E,0X00};
const char V[]={0x3E,0X40,0X80,0X40,0X3E,0X00};
const char X[]={0xC6,0X28,0X10,0X28,0XC6,0X00};
const char Y[]={0x06,0X08,0XF0,0X08,0X06,0X00};
const char Z[]={0xC2,0XA2,0X92,0X8A,0X86,0X00};

// ********* LOS NUMEROS **********************
const char CERO[]={0x7C,0X82,0X82,0X82,0X7C,0X00};
const char UNO[]={0x00,0X84,0XFE,0X80,0X00,0X00};
const char DOS[]={0x84,0XC2,0XA2,0X92,0X8C,0X00};
const char TRES[]={0x44,0X82,0X92,0X92,0X6C,0X00};
const char CUATRO[]={0x1E,0X10,0X10,0X10,0XFE,0X00};
const char CINCO[]={0x5E,0X92,0X92,0X92,0X62,0X00};
const char SEIS[]={0x7C,0X92,0X92,0X92,0X64,0X00};
const char SIETE[]={0x82,0X42,0X22,0X12,0X0E,0X00};
const char OCHO[]={0x6C,0X92,0X92,0X92,0X6C,0X00};
const char NUEVE[]={0x4C,0X92,0X92,0X92,0X7C,0X00};

// ********* SIMBOLOS ****************************
const char SPACE[]={0X00,0X00,0X00,0X00,0X00,0X00};
const char PUNTO[]={0X00,0X00,0X00,0X00,0X80,0X00};
const char ASTER[]={0x28,0X10,0X7C,0X10,0X28,0X00};
const char COMA[]={0X00,0XA0,0X60,0X00,0X00,0X00};



//******* FUNCION LETRA recive el contenido del bufer BU y lo acomoda en el BUFER PF 
//******* el bufer PF es el bufer de 

void letra(char ro[])  // Se recibe el contenido de BU (6 columnas) y se le denomina RO  
		       // el objetivo es acumular todas las columnas en un bufer llamdo PF

{int i;                
for(i=0;i<6;i++)
pf[jota+i]=ro[i];     // PF acumula los 6 patrones de cada caracter y los almacena
jota=jota+6;          // al terminar de acumular El puntero JOTA avanza 6 posiciones
}



//******* FUNCION SWATCH recibe el caracter (char bor) que se envia del programa principal        ****
//******* lo compara con la tabla de caracteres y lo descompone en sus 6 columnas                 ****
//******* luego estas columnas se guardan en el bufer TEMPORAL BU para pasarlo a la funcion LETRA ****

void swatch(char bor) // se recibe el caracter del programa principal y se le denomina bor 
{
int i;               //variable local para el SWITCH CASE de cada LETRA
char bu[6];          //BUFFER TEMPORAL que almacenara las columnas del caracter
for(i=0;i<6;i++)     // for que recorre las 6 columnas de cada caracter de la TABLA de caracteres
{
switch(bor)          //Este SWITCH busca el caracter (bor) en la tabla y lo descompone en columnas
{

case 'A':bu[i]=A[i];break;
case 'B':bu[i]=B[i];break;
case 'C':bu[i]=C[i];break;
case 'D':bu[i]=D[i];break;
case 'E':bu[i]=E[i];break;
case 'F':bu[i]=F[i];break;
case 'G':bu[i]=G[i];break;
case 'H':bu[i]=H[i];break;
case 'I':bu[i]=RI[i];break;
case 'J':bu[i]=J[i];break;
case 'K':bu[i]=KA[i];break;
case 'L':bu[i]=L[i];break;
case 'M':bu[i]=M[i];break;
case 'N':bu[i]=N[i];break;
case 'O':bu[i]=O[i];break;
case 'P':bu[i]=P[i];break;
case 'Q':bu[i]=Q[i];break;
case 'R':bu[i]=R[i];break;
case 'S':bu[i]=S[i];break;
case 'T':bu[i]=T[i];break;
case 'U':bu[i]=U[i];break;
case 'V':bu[i]=V[i];break;
case 'X':bu[i]=X[i];break;
case 'Y':bu[i]=Y[i];break;
case 'Z':bu[i]=Z[i];break;



case 'a':bu[i]=AM[i];break;
case 'b':bu[i]=BM[i];break;
case 'c':bu[i]=CM[i];break;
case 'd':bu[i]=DM[i];break;
case 'e':bu[i]=EM[i];break;
case 'f':bu[i]=FM[i];break;
case 'g':bu[i]=GM[i];break;
case 'h':bu[i]=HM[i];break;
case 'i':bu[i]=IM[i];break;
case 'j':bu[i]=JM[i];break;
case 'k':bu[i]=KM[i];break;
case 'l':bu[i]=LM[i];break;
case 'm':bu[i]=MM[i];break;
case 'n':bu[i]=NM[i];break;
case 'ñ':bu[i]=ENEM[i];break;
case 'o':bu[i]=OM[i];break;
case 'p':bu[i]=PM[i];break;
case 'q':bu[i]=QM[i];break;
case 'r':bu[i]=RM[i];break;
case 's':bu[i]=SM[i];break;
case 't':bu[i]=TM[i];break;
case 'u':bu[i]=UM[i];break;
case 'v':bu[i]=VM[i];break;
case 'x':bu[i]=XM[i];break;
case 'y':bu[i]=YM[i];break;
case 'z':bu[i]=ZM[i];break;

case '0':bu[i]=CERO[i];break;
case '1':bu[i]=UNO[i];break;
case '2':bu[i]=DOS[i];break;
case '3':bu[i]=TRES[i];break;
case '4':bu[i]=CUATRO[i];break;
case '5':bu[i]=CINCO[i];break;
case '6':bu[i]=SEIS[i];break;
case '7':bu[i]=SIETE[i];break;
case '8':bu[i]=OCHO[i];break;
case '9':bu[i]=NUEVE[i];break;


case '*':bu[i]=ASTER[i];break;
case ',':bu[i]=COMA[i];break;
case '.':bu[i]=PUNTO[i];break;
case ' ':bu[i]=SPACE[i];break;

}
}
letra(bu);         // cuando se termina de descomponer el caracter bor se llama a la funcion LETRA 
		   // y se le transfiere todo el contenido del bufer BU que contiene las 6 columnas
		   // del caracter
}

Los caracteres de la Matriz .

Puedes crear tus propios caracteres mediante una herramienta que te permitirá de forma visual ir armando las columnas de tus letras o simbolos.

En este caso te muestro como forme la letra A que esta definida en la tabla de esta manera:

const char A[]={0xFC,0X12,0X12,0X12,0XFC,0X00}; 
Matriz de Leds Letra A

Simulación de la matriz de leds en PROTEUS

Este proyecto lo puedes simular en PROTEUS de manera que puedas ir haciendo tus cambios o mejoras probando su funcionamiento antes de llevarlo a la realidad.

En nuestro caso también compartiremos contigo la simulación.

Los Links del proyecto Matriz de leds:

Link del código de la programación:

http://raboninco.com/21375611/matriz-led-ccs

Link de la simulación:

http://raboninco.com/21375611/simu-matriz-led-ccs

Eso seria todo por ahora amigos en el post Programación de una matriz de LEDS con lenguaje C. Espero que podamos ir mejorando esta publicación con tus ideas y comentarios.

Recuerda que si esta publicación te fue de alguna utilidad puedes ayudarnos a mantenerlo en linea visitando la publicidad que aparece a lo largo de este post. Gracias !

Puedes también visitar todas nuestras demás publicaciones en :

https://www.tecnocienciaperu.com/blog/

puedes ademas ver nuestro canal de youtube:

https://www.youtube.com/channel/UC7UGXaGmuYYZCogU5owLqAQ?view_as=subscriber

3 Replies to “Código de Programación de una matriz de LEDS con lenguaje C

  1. Hola buenas tardes, antes que nada muchas felicitaciones, es impresionante lo que se puede hacer con eso.
    copie el codigo tal y cual esta en este post, pero a la hora de compilarlo en ccs compiler me salia que hay que declarar TRISA=0;TRISB=0;PORTA=0x00; PORTB=0X00; esas variables, al igual que RA0, RA1, RA2, RA3; y RB0, RB1, RB3, RB4, RB6, RB7; por lo cual estas ultimas les asigne a enteros, y ya no marco error al compilarlo,

    los de tris y port las declare de la siguiente manera

    #BYTE TRISA=0x85
    #BYTE TRISB=0x86
    #BYTE PORTA=0x05
    #BYTE PORTB=0x06

    genere el código hexadecimal, y a la hora de hacer la simulacion no funcion.
    podrias ayudarme a revisar donde esta la falla?

    gracias

    1. Hola Mario,
      gracias por escribirnos,
      al código de la pagina le faltan algunas líneas que no se han colocado intencionalmente para que la persona interesada realice ese pequeño esfuerzo.
      para que los puertos funcionen de forma correcta sin hacer modificaciones crea un archivo llamado 16f628.h dentro de la carpeta donde estas compilando dentro de ese archivo coloca este contenido:

      #include <16F628A.h>

      #FUSES NOWDT //No Watch Dog Timer
      #FUSES NOBROWNOUT //No brownout reset
      #FUSES NOLVP //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O

      #use delay(crystal=4000000)

      #byte TRISA=0X85
      #byte TRISB=0X86
      #byte PORTA=0X05
      #byte PORTB=0X06
      #byte CMCON=0X9C
      #byte CVRCON=0X9D
      #byte ANSEL=0X98
      #byte RCSTA=0X18
      #byte RCREG=0X1A

      #bit RA0=5.0
      #bit RA1=5.1
      #bit RA2=5.2
      #bit RA3=5.3
      #bit RA4=5.4
      #bit RB0=6.0
      #bit RB1=6.1
      #bit RB2=6.2
      #bit RB3=6.3
      #bit RB4=6.4
      #bit RB5=6.5
      #bit RB6=6.6
      #bit RB7=6.7
      #bit RBPU=0X81.7 //BIT RBPU=(OPTION,7)
      #bit SPEN=0X18.7 //bit de registro RCSTA
      #bit CREN=0X18.4 //bit de registro RCSTA
      //*****************FIN DEL ARCHIVO INCLUDE***************

      CON ESTA LIBRERIA YA NO TENDRIAS PROBLEMAS CON LOS PUERTOS, RECUERDA QUE DEBES TAMBIEN SETEAR LOS FUSES DEL PIC QUE ESTES UTILIZANDO.
      SUERTE.

      1. hola mksdgo, te agradezco mucho por tu apoyo, si ya me funciono.

        solo para comentarte, apenas en esta semana empece en el mundo de la electrónica, es por ello que no tengo nada de experiencia, pero con esto ya se me aclararon muchas dudas.

        saludos y muchas gracias nuevamente.

Agregue un comentario

Su dirección de correo no se hará público. Los campos requeridos están marcados *