Programa cinco Encoder y un sólo PIC en CCS

A continuación se muestra el programa en CCS C para controlar cinco encoders con un sólo PIC, el 16F876A. El LCD está íntegramente controlado a través del puerto PORTA. Si haces clic aquí descargarás el código fuente y una librería llamada 'flex_lcd.c' para el manejo del LCD configurada para el esquema que puse anteriormente.

Más abajo explico cómo configurar los pines que van al LCD de la manera que desees usando la librería 'flex_lcd.c'.

#include <16F876A.h>
#FUSES NOWDT, XT, PUT, NOPROTECT, NODEBUG, NOBROWNOUT, NOLVP, NOCPD, NOWRT
#use delay(clock=4000000)

#byte porta = 0x05        // Asignamos porta.
#byte portb = 0x06        // Asignamos portb.
#byte portc = 0x07        // Asignamos portc.

#include <flex_lcd.c>

void main()
{
   port_b_pullups(FALSE);
   setup_adc_ports(NO_ANALOGS);
   setup_adc(ADC_CLOCK_DIV_2);
   setup_spi(SPI_SS_DISABLED);
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
   setup_timer_1(T1_DISABLED);
   setup_timer_2(T2_DISABLED,0,1);
   setup_comparator(NC_NC_NC_NC);
   setup_vref(FALSE);
   
   set_tris_a(0b000000);          //Todo el puerto A como salidas.
   set_tris_b(0b11111111);        //Todo el puerto B como entradas.
   set_tris_c(0b11111111);        //Todo el puerto C como entradas.
   
   int16   X1=0,   X2=0,   X3=0,   X4=0,   X5=0,  Q=0; 
   int8  Aux1=0, Aux2=0, Aux3=0, Aux4=0, Aux5=0; // Todas las variables son creadas
   int8  Enc1=0, Enc2=0, Enc3=0, Enc4=0, Enc5=0; // y puestas a cero.
   
   lcd_init(); 
    
   lcd_putc("\f");                               // Borra el contenido visual del LCD.
   lcd_gotoxy(6,1); printf(lcd_putc, "Hola!");   // Al comienzo veremos un saludo
   delay_ms (2000);                              // durante dos segundos.
   lcd_putc("\f");
   delay_ms (250);
   printf(lcd_putc, "%4lu %4lu %4lu\n", X1, X2, X3);  // Inicialmente escribe el valor
   printf(lcd_putc, "%4lu %4lu",        X4, X5);      // de todos los contadores.

   While (true)
   {
      Aux1 = Enc1;                               // Igualamos para luego saber si hay cambios en
                                                 // el encoder.
      Enc1 = portb & 3;                          // Aislamos los dos primeros bits de portb.
      Q=X1;                                      // Igualamos para luego saber si hay cambios en
                                                 // el contador.
      If ((Aux1 == 2) && (Enc1 == 3))    { X1++;}// Si hay flanco de subida, incrementa el contador.
      If ((Aux1 == 3) && (Enc1 == 2))    { X1--;}// Si hay flanco de bajada, decrementa el contador.
      If (X1 == 65535) { X1=9999;}               // Si es menor de cero, cargar el valor máximo
                                                 // 9999.
      If (bit_test(portc, 7) == 0)       { X1=0;}// Si se ha pulsado el encoder, poner a cero el
                                                 // contador.
      If (Q!=X1)                                 // Si hay cambios en el contador, visualizar el
                                                 // contador en el LCD.
      {
         lcd_gotoxy(1, 1);
         printf(lcd_putc, "%4lu", X1);
      }

      Aux2 = Enc2;                               // Se repite todo el proceso con diferentes
      Enc2 = portb & 12;                         // variables y valor de aislamiento de bits.
      Q=X2;
      If ((Aux2 ==  8) && (Enc2 == 12))  { X2++;}  
      If ((Aux2 == 12) && (Enc2 ==  8))  { X2--;}  
      If (X2 == 65535) { X2=9999;}          
      If (bit_test(portc, 6) == 0)       { X2=0;} 
      If (Q!=X2)
      {
         lcd_gotoxy(6, 1);
         printf(lcd_putc, "%4lu", X2);
      }

      Aux3 = Enc3;                              
      Enc3 = portb & 48;                       
      Q=X3;
      If ((Aux3 == 32) && (Enc3 == 48))  { X3++;}
      If ((Aux3 == 48) && (Enc3 == 32))  { X3--;}
      If (X3 == 65535) { X3=9999;}
      If (bit_test(portc, 5) == 0)       { X3=0;}
      If (Q!=X3)
      {
         lcd_gotoxy(11, 1);
         printf(lcd_putc, "%4lu", X3);
      }
      
      Aux4 = Enc4;                            
      Enc4 = portb & 192;
      Q=X4;                                  
      If ((Aux4 == 128) && (Enc4 == 192)) { X4++;}  
      If ((Aux4 == 192) && (Enc4 == 128)) { X4--;}  
      If (X4 == 65535) { X4=9999;}          
      If (bit_test(portc, 4) == 0)        { X4=0;} 
      If (Q!=X4)
      {
         lcd_gotoxy(1, 2);
         printf(lcd_putc, "%4lu", X4);
      }
      
      Aux5 = Enc5;
      Enc5 = portc & 3;
      Q=X5;
      If ((Aux5 == 2) && (Enc5 == 3))     { X5++;}
      If ((Aux5 == 3) && (Enc5 == 2))     { X5--;}
      If (X5 == 65535) { X5=9999;}
      If (bit_test(portc, 3) == 0)        { X5=0;}
      If (Q!=X5)
      {
         lcd_gotoxy(6, 2);
         printf(lcd_putc, "%4lu", X5);
      }
   }      
}

Cómo modificar el fichero 'flex_lcd.c'

Modifiqué los bits de salida para el LCD en el interior del fichero "flex_lcd.c", y así poderlo controlar íntegramente desde el PORTA. De hecho esta librería es una pequeña maravilla porque puedes configurar los pines que desees para controlar el LCD.

Dentro de la librería 'flex_lcd.c' verás la parte donde se asignan los pines. Como quiero poner el LCD al puerto A del PIC asigno esas patillas, es decir, del PIN_A0 al PIN_A5.

Ten presente que el bit RW del LCD en el esquema está configurado para ser siempre de escritura porque ese bit está puesto a masa. De esta manera ahorramos un pin del PIC. Cuando esto es así hay que comentar (poner //) en las definiciones #define LCD_RW y #define USE_LCD_RW. Pero si quieres usar RW por cualquier motivo (para otro hardware), entonces has de eliminar el '//' de ambas líneas y asignarle el pin correspondiente a #define LCD_RW. Sólo has de quitar los '//' si vas a hacer lectura del LCD, como por ejemplo, pedirle saber en qué posición está un carácter. Esto último no es frecuente porque casi siempre sólo usamos el LCD para representar, pero lo explico por si ese fuera tu caso.

#define LCD_D4 PIN_A0   // Bit D4 de datos del LCD será controlado por RA0. Puede ser cualquier otro pin del PIC.
#define LCD_D5 PIN_A1   // Bit D5 de datos del LCD será controlado por RA1.               "
#define LCD_D6 PIN_A2   // Bit D6 de datos del LCD será controlado por RA2.               "
#define LCD_D7 PIN_A3   // Bit D7 de datos del LCD será controlado por RA3.               "
#define LCD_RS PIN_A4   // Bit RS de control del LCD será controlado por RA4.             "
#define LCD_EN PIN_A5   // Bit EN de control del LCD será controlado por RA5.             "
//#define LCD_RW PIN_C2 // No usamos la patilla RW por tanto la "comentamos" (//). <---------- Aquí!
// If you only want a 6-pin interface to your LCD, then
// connect the R/W pin on the LCD to ground, and comment
// out the following line. 
//#define USE_LCD_RW 1  // No usamos la patilla RW por tanto la "comentamos" (//). <---------- Aquí!