#include <18f2550.h>
#device  adc = 10
#fuses   nowdt,hs, put
#use     delay(crystal = 20MHz)
#use     fast_io(d)
#define  punto pin_c7
// Arreglo para las variables de los dígitos.
int8 display[3] = {0,0,0};
float valor_adc;
void entero_a_bcd(int16 valor,int8 digitos_menos_1);
// Tabla para displays de 7 segmentos cátodo común.
int8 const tabla_7segs[10] = {0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};
#INT_TIMER1
// Servicio de interrupción por desborde del Timer 1
void sdi_timer1 (void)
{
   // Realizar la lectura del conversor análogo a digital.
   valor_adc = ((40.0 * read_adc()) / 65536);
   set_timer1(0xBDC);               // Recargar el Timer 1
}
void main (void)
{
   int16 voltaje;
   set_tris_d(0b11110000);
   
   enable_interrupts(INT_TIMER1);
   setup_timer_1(T1_INTERNAL | T1_DIV_BY_8);
   set_timer1(0xBDC); // Cargar el timer1 con 3036 (500Ms. Aprox. 0.001% Error)
   enable_interrupts(GLOBAL);
   setup_adc_ports(sAN0|VREF_VREF); // Seleccionar canal 0 y usar VRef = 2.5V
   setup_adc(ADC_CLOCK_INTERNAL);   // Reloj ADC = interno
   set_adc_channel(0);              // Establecer el canal 0
   delay_us(50);
      
   while (true)
   {  
      // Multiplicar por 100 el valor de "valor_adc"
      voltaje = (valor_adc * 100);
      // Obtener el valor para cada dígito, separando el número
      // y convirtiéndolo con la tabla para displays de 7 segmentos.
      entero_a_bcd(voltaje,3);
      
      // Multiplexar los displays. (Con 4 ms se consiguió menor transición en las unidades)
      output_d(1);   // Activar display 1 y desactivar display 2 y 3
      output_c(tabla_7segs[display[3]]);  // Mostrar unidades.
      delay_ms(2);   // Retardo para mostrar las unidades.
      output_d(2);   // Activar display 2 y desactivar Display 1 y 3
      output_c(tabla_7segs[display[2]]);  // Mostrar decenas.
      delay_ms(2);   // Retardo para mostrar las decenas.
      output_d(4);   // Activar display 3 y desactivar Display 1 y 2
      output_c(tabla_7segs[display[1]]);  // Mostrar las centenas.
      output_high(punto);  // Apagar el punto.
      delay_ms(2);   // Retardo para mostrar las centenas.
      output_d(8);
      output_c(tabla_7segs[display[0]]);  // Mostrar los millares.
      output_low(punto);   // Encender el punto.
      delay_us(700);
   }
}
// Subrutina para separar el número.
void entero_a_bcd(int16 valor, int8 digitos_menos_1)
{
int8 i;
   // Limpiar variables del arreglo "display[]".
   for(i=0;i<=digitos_menos_1;i++)
   {
      display[i] = 0;
   }
   i = digitos_menos_1;
   // Separar los números.
   while (valor > 0)
   {
      display[i--] = (valor % 10);
      valor /= 10;
   }
}