Volumen III Anexos DESARROLLO DE UNA UNIDAD DE ADQUISICIÓN Y MONITORIZACIÓN DE DATOS PARA UN VEHICULO DE AUTOMOCIÓN TFG presentado para optar al título de GRADO en INGENIERÍA ELECTRÓNICA INDUSTRIAL Y AUTOMÁTICA por Daniel Bassons González, Marc Mestre López Barcelona, 11 de Enero de 2016 Director: Manuel Manzanares Brotons Departamento de EEL (D710) Universitat Politècnica de Catalunya (UPC) Tabla de contenido de anexos 1. PROGRAMACIÓN DEL PROTOTIPO ...............................................................................2 2. LIBRERIA RELOJ EN TIEMPO REAL ..............................................................................17 Desarrollo de una unidad de adquisición y monitorización de datos para un vehículo de automoción Capítulo 1 Programación del prototipo #include <18F46j50.h> #device adc=10 #fuses NOWDT #fuses HS // No Watch Dog Timer // High speed clock #use delay(clock=16M) #include <DS1307.c> #include <24256.c> #include <LCD.C> #include <math.h> // Libreria para calculos matematicos #include <stddef.h> // Libreria para asignar tamaños #include <stdlib.h> // Libreria reloj interno real // Libreria eeprom 256kb // Libreria del display lcd // Libreria para gestion de memoria #define led_alert PIN_B3 // Led rojo para saber si la salida esta fuera del rango de trabajo #define led_start PIN_C2 // Led verde parpadeo cuando lee datos de los sensores #define led_power_on PIN_A5 // Led verde alimentacion #define led_parp PIN_A3 // Led amarillo, parpadea cuando el USB o el reset de eeprom esta funcionando #define led_on output_high // Led encendido #define led_off output_low // Led apagado #use i2c(master, sda=RTC_SDA, scl=RTC_SCL) // Asigna los pines del bus I2C #use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8) // Asigna los pines del puerto serie float rpm_out,ntc_temp,CO2_adc,CO2_out,map_consm,spd_out,data,out=0,tiempo=0 ; float epp_rpm=0,epp_ntc=0,epp_CO2=0,epp_consm=0,epp_spd=0,epp_tiempo=0; int32 segundos_total=0; int16 n=0,t=4,p=0,m=0,point=0,z=0,k=0,y=0,usb_start=0,usb_count=0,led_count= 0,lcd_count; int16 2 Desarrollo de una unidad de adquisición y monitorización de datos para un vehículo de automoción rpm_count=0,spd_count=0,rpm_cntd=0,rpm_vueltas=0,lcd_but=0,lcd_cntd=1, start=0,CO2_in=0; int16 spd_cntd=0,eeprom_count=0,main_count=0,spd_vueltas=0,eeprom_reset=0,fe cha_count=0,ntc_in=0; int8 lcd_flag=0,spd_flag=0,rpm_flag=0,flag_reset=0,flag_usb=0; int8 day,mth,interv=0,year,dow,hora,minuto,segundo,hr,min,sec,erase=0xFF; void void void void void void void NTC(); CO2(); SPD(); RPM(); MAP(); USB(); R232(); void usb_wait_for_enumeration(); void write_float_ext_eeprom(int16 m, float data); void read_float_ext_eeprom(int16 t); void write_point_ext_eeprom(int16 n, int16 p); void read_point_ext_eeprom(int16 k); void write_erase_ext_eeprom(int16 z, float erase); #int_rtcc void clock_isr() // Interrupcion del timer 0 { ++main_count; // 10 counts en 1s ++led_count; ++eeprom_count; ++rpm_count; ++spd_count; ++usb_count; ++lcd_count; ++fecha_count; set_timer0(15535); //0.25^-6(4/Fosc)*prescaler(8)*(65535-15535)= 0.1s = 10 ticks/s } void read_point_ext_eeprom(int16 k) { int i; for (i = 0; i < 4; i++) { *((int8*)&point + i) = read_ext_eeprom(i + k); delay_us(20); } } void write_point_ext_eeprom(int16 n, int16 p) { int i; for (i = 0; i < 4; i++) { write_ext_eeprom(i + n, *((int8*)&p + i) ); 3 Desarrollo de una unidad de adquisición y monitorización de datos para un vehículo de automoción delay_us(20); } } void read_float_ext_eeprom(int16 t) { int16 i; for (i = 0; i < 4; i++) { *((int8*)&out + i) = read_ext_eeprom(i + t); delay_us(20); } } void write_float_ext_eeprom(int16 m, float data) { int i; for (i = 0; i < 4; i++) { write_ext_eeprom(i + m, *((int8*)&data + i) ); delay_us(20); } } void write_erase_ext_eeprom(int16 z, int8 erase) { int16 j; for (j = 0; j < 1800; j++) { write_ext_eeprom(z + j, erase); // 1680 bytes de borrado para pruebas de 5min delay_us(20); y++; if (led_count<=1) { led_on(led_parp); } if ((led_count>1)&&(led_count<=2)) { led_off(led_parp); } if ((led_count>2)) { led_count=0; } } } void main() { setup_adc_ports(sAN0,sAN1|VSS_VDD); // Configuracion del micro + inicializacion 4 Desarrollo de una unidad de adquisición y monitorización de datos para un vehículo de automoción setup_adc(ADC_CLOCK_DIV_16); setup_spi(SPI_SS_DISABLED); setup_wdt(WDT_OFF); setup_timer_0(RTCC_INTERNAL | RTCC_DIV_8); setup_timer_1(T1_INTERNAL | T1_DIV_BY_4); setup_timer_2(T2_DISABLED,0,1); setup_ccp1(CCP_OFF); setup_comparator(NC_NC_NC_NC); set_timer0(15535); enable_interrupts(INT_RTCC); enable_interrupts(GLOBAL); ds1307_init(); lcd_init(); delay_us(20); // Configuracion del micro + inicializacion while (true) { delay_us(20); led_on(led_power_on); usb_start=input(Pin_D3); start=input(Pin_C1); eeprom_reset=input(Pin_C0); delay_us(20); if ((start==0)&&(eeprom_reset==0)&&(flag_reset==0)&&(usb_start==0)&&(flag _usb==0)) // Inicio S.A.D { int i,j; lcd_cntd=1; led_off(led_start); led_off(led_parp); printf(lcd_putc, "\f"); lcd_gotoxy(6,1); printf(lcd_putc, "S.A.D"); char lcd_ini[32] = "Pulse Start o Reset "; for (i=16;i>0;i--) // Movimiento derecha a izquierda hasta x=1 { lcd_gotoxy(i,2); printf(lcd_putc,"%s",lcd_ini); delay_ms(300); usb_start=input(Pin_D3); // Leemos cada 50ms para cortar bucle si es necesario start=input(Pin_C1); eeprom_reset=input(Pin_C0); if ((start==1)&&(flag_reset==0)&&(flag_usb==0)) // Condiciones de corte { printf(lcd_putc, "\f"); break; } if ((start==0)&&(eeprom_reset==1)&&(flag_reset==0)&&(usb_start==0)&&(flag _usb==0)) { 5 Desarrollo de una unidad de adquisición y monitorización de datos para un vehículo de automoción printf(lcd_putc, "\f"); break; } if ((start==0)&&(eeprom_reset==0)&&(flag_reset==0)&&(usb_start==1)&&(flag _usb==0)) { printf(lcd_putc, "\f"); break; } } for (j=1;j<20;j++) // Movimiento derecha a izquierda desde x=1 { lcd_gotoxy(1,2); printf(lcd_putc,"%s",lcd_ini+j); delay_ms(300); usb_start=input(Pin_D3); // Leemos cada 50ms para cortar bucle si es necesario start=input(Pin_C1); eeprom_reset=input(Pin_C0); if ((start==1)&&(flag_reset==0)&&(flag_usb==0)) // Condiciones de corte { printf(lcd_putc, "\f"); break; } if ((start==0)&&(eeprom_reset==1)&&(flag_reset==0)&&(usb_start==0)&&(flag _usb==0)) { printf(lcd_putc, "\f"); break; } if ((start==0)&&(eeprom_reset==0)&&(flag_reset==0)&&(usb_start==1)&&(flag _usb==0)) { printf(lcd_putc, "\f"); break; } } } if ((start==0)&&(eeprom_reset==1)&&(flag_reset==0)&&(usb_start==0)&&(flag _usb==0)) // Reset eeprom { printf(lcd_putc, "\f"); lcd_gotoxy(3,2); printf(lcd_putc,"Borrando..."); flag_reset=1; write_erase_ext_eeprom(z,erase); if (y>=1800) // 1680 bytes de borrado para pruebas de 5min (5040bytes = 15min) { printf(lcd_putc, "\f"); 6 Desarrollo de una unidad de adquisición y monitorización de datos para un vehículo de automoción lcd_gotoxy(4,2); printf(lcd_putc,"Listo!"); led_off(led_parp); delay_ms(1000); flag_reset=0; y=0; } } if ((start==0)&&(eeprom_reset==0)&&(flag_reset==0)&&(usb_start==1)&&(flag _usb==0)) // Habilitar USB o RS232 { flag_usb=1; printf(lcd_putc, "\f"); lcd_gotoxy(1,2); printf(lcd_putc,"Comunicando USB"); usb_count=0; //USB(); R232(); } if ((start==1)&&(flag_reset==0)&&(flag_usb==0)) // Funcionamiento datos ON { // ADQUISICION DE DATOS if (main_count<2) { NTC(); if (ntc_temp<=300.0) { led_off(led_alert); } else led_on(led_alert); } if ((main_count>=2)&&(main_count<4)) { CO2(); if (CO2_out<=10000.0) { led_off(led_alert); } else led_on(led_alert); } if (main_count==4) { spd_count=0; } if ((main_count>=4)&&(main_count<25)) { SPD(); if (spd_out<=250.0) { 7 Desarrollo de una unidad de adquisición y monitorización de datos para un vehículo de automoción led_off(led_alert); } else led_on(led_alert); } if (main_count==25) { rpm_count=0; } if ((main_count>=25)&&(main_count<46)) { RPM(); if (rpm_out<=8000.0) { led_off(led_alert); } else led_on(led_alert); } if ((main_count>=46)&&(main_count<48)) { MAP(); if (map_consm<=30.0) { led_off(led_alert); } else led_on(led_alert); } if (main_count>=50) { main_count=0; rpm_cntd=0; rpm_count=0; spd_cntd=0; spd_count=0; } // Led parpadeo start (adquisicion de datos) if (led_count<=1) { led_on(led_start); } if ((led_count>1)&&(led_count<=2)) { led_off(led_start); } if ((led_count>2)) { led_count=0; } // EEPROM Escritura if (eeprom_count==48) 8 Desarrollo de una unidad de adquisición y monitorización de datos para un vehículo de automoción // Write/read puntero, write datos { if (p<4) // Incializacion puntero ( 4 bytes para puntero) { p=4; write_point_ext_eeprom(n,p); delay_us(5); } if ((p>=4)&&(p<1680)) // rango de almacenamiento de las direcciones (5min=300s // 300s/5s*28bytes = 1680 bytes) { delay_us(5); ds1307_get_time(hr,min,sec); // lee tiempo actual tiempo=((hr*3600)+(min*60)+(sec)); // tiempo actual en segundos totales // // // // delay_us(5); read_point_ext_eeprom(k); lee puntero m=point; delay_us(5); m pasa a ser puntero write_float_ext_eeprom(m,tiempo); escribimos temp ntc en eeprom posicion puntero m=m+4; cada float ocupa 4 bytes, avanzamos puntero 4 posiciones delay_us(5); write_float_ext_eeprom(m,ntc_temp); m=m+4; delay_us(5); write_float_ext_eeprom(m,CO2_out); m=m+4; delay_us(5); write_float_ext_eeprom(m,rpm_out); m=m+4; delay_us(5); write_float_ext_eeprom(m,spd_out); m=m+4; delay_us(5); write_float_ext_eeprom(m,map_consm); m=m+4; p=m; delay_us(5); write_point_ext_eeprom(n,p); delay_us(5); } } if (eeprom_count>=50) { eeprom_count=0; } // reset contador eeprom // LCD DISPLAY lcd_but=input(pin_B2); 9 Desarrollo de una unidad de adquisición y monitorización de datos para un vehículo de automoción if (lcd_but == 1) { lcd_flag=1; } // flanco de bajada evitando rebote mecanico if ((lcd_but == 0)&&(lcd_flag == 1)) bajada evitando rebote mecanico { lcd_cntd++; lcd_flag=0; printf(lcd_putc, "\f"); } // lee flanco de if (lcd_cntd == 1) { lcd_gotoxy(6,1); printf(lcd_putc, "S.A.D"); lcd_gotoxy(3,2); printf(lcd_putc,"Pulse 'Set'"); fecha_count=0; while (lcd_but == 1) { lcd_but=input(pin_B2); if (fecha_count==50) { day=21; mth=12; year=15; dow=1; hr=12; min=0; sec=0; ds1307_set_date_time(day,mth,year,dow,hr,min,sec); lcd_flag=0; fecha_count=0; printf(lcd_putc, "\f"); lcd_gotoxy(1,2); printf(lcd_putc,"Reloj programado"); delay_ms(800); printf(lcd_putc, "\f"); } } } If (lcd_count>=2) { ds1307_get_time(hr,min,sec); if (lcd_cntd == 2) { if (ntc_in <=0) { lcd_gotoxy(9,1); printf(lcd_putc,"%02u:%02u:%02u ",hr,min,sec); lcd_gotoxy(1,2); printf(lcd_putc,"T = -- C"); } else { 10 Desarrollo de una unidad de adquisición y monitorización de datos para un vehículo de automoción lcd_gotoxy(9,1); printf(lcd_putc,"%02u:%02u:%02u ",hr,min,sec); lcd_gotoxy(1,2); printf(lcd_putc,"T = %04.1f C",ntc_temp); } } if (lcd_cntd == 3) { if (CO2_adc>1.625) { lcd_gotoxy(9,1); printf(lcd_putc,"%02u:%02u:%02u ",hr,min,sec); lcd_gotoxy(1,2); printf(lcd_putc,"CO2 <400 ppm"); } if ((CO2_adc<=1.625)&&(CO2_adc>=1.325)) { lcd_gotoxy(9,1); printf(lcd_putc,"%02u:%02u:%02u ",hr,min,sec); lcd_gotoxy(1,2); printf(lcd_putc,"CO2 = %04.1f ppm",CO2_out); } if (CO2_adc<1.325) { lcd_gotoxy(9,1); printf(lcd_putc,"%02u:%02u:%02u ",hr,min,sec); lcd_gotoxy(1,2); printf(lcd_putc,"CO2 >10000 ppm"); } } if (lcd_cntd == 4) { lcd_gotoxy(9,1); printf(lcd_putc,"%02u:%02u:%02u ",hr,min,sec); lcd_gotoxy(1,2); printf(lcd_putc,"Vel = %04.1f Km/h",spd_out); } if (lcd_cntd == 5) { lcd_gotoxy(9,1); printf(lcd_putc,"%02u:%02u:%02u ",hr,min,sec); lcd_gotoxy(1,2); printf(lcd_putc,"RPM = %04.1f",rpm_out); } if (lcd_cntd == 6) { lcd_gotoxy(9,1); printf(lcd_putc,"%02u:%02u:%02u ",hr,min,sec); lcd_gotoxy(1,2); printf(lcd_putc,"Consm = %04.1f L/h",map_consm); } lcd_count=0; } if (lcd_cntd > 6) { 11 Desarrollo de una unidad de adquisición y monitorización de datos para un vehículo de automoción lcd_cntd=2; } } } } void NTC() { float ntc_adc,ntc_rt,ntc_x; setup_adc_ports(sAN0,sAN1|VSS_VDD); set_adc_channel(0); puerto queremos leer delay_us(20); ntc_in=read_adc(); delay_us(20); // para seleccionar que if (ntc_in <=0) { ntc_temp=999; } else { // FORMULA INICIO ntc_adc=3.0*ntc_in/1024.0; ntc_rt=ntc_adc*100000.0/(3.0-ntc_adc); ntc_x=log(ntc_rt/100000.0); // para linealizar la curva de respuesta del sensor ntc_x=(1.0/298.15)+(ntc_x*(1.0/4250.0)); // beta_ntc= 4250 ntc_temp=1.0/ntc_x; ntc_temp=ntc_temp-273.15; // FORMULA FIN } } void CO2() { float CO2_ini,CO2_dispers,AO_gain,CO2_x,CO2_y,CO2_z; // dsp = dispersion CO2_ini=0.325; CO2_dispers=0.0171; AO_gain=5.0; set_adc_channel(1); delay_us(20); CO2_in=read_adc(); delay_us(20); // punto de trabajo inicial // valor dispersion formula logaritmica // para seleccionar que puerto queremos leer CO2_adc=3.0*CO2_in/1024.0; if (CO2_adc < 1.325) { CO2_out=50000; } if ((CO2_adc<=1.625)&&(CO2_adc>=1.325)) { // FORMULA INICIO 12 Desarrollo de una unidad de adquisición y monitorización de datos para un vehículo de automoción CO2_x=CO2_adc-(CO2_ini*AO_gain); CO2_y=log10(400.0)-log10(1000.0); CO2_z=(CO2_x*CO2_y)/(CO2_dispers*AO_gain); CO2_out=pow(10,CO2_z+log10(400.0)); // FORMULA FIN } if (CO2_adc > 1.625) { CO2_out=1; } } void SPD() { float spd_radio=0.31075; int8 spd_in; spd_in=input(pin_B1); if (spd_count<20) { if (spd_in == 1) { spd_flag=1; } if ((spd_in == 0)&&(spd_flag == 1)) { spd_cntd++; spd_flag=0; } } if (spd_count>=20) { spd_vueltas=spd_cntd/4; spd_out=(2*pi*spd_vueltas/2*spd_radio*3.6); } } void RPM() { int8 rpm_in; rpm_in=input(pin_B0); if (rpm_count<20) { if (rpm_in == 1) { rpm_flag=1; } if ((rpm_in == 0)&&(rpm_flag == 1)) { rpm_cntd++; rpm_flag=0; } } 13 Desarrollo de una unidad de adquisición y monitorización de datos para un vehículo de automoción if (rpm_count==20) { rpm_vueltas=rpm_cntd; rpm_out=(60*rpm_vueltas/2); // 1min = 60s// rpm = vueltas*minuto//2s contando vueltas } } void MAP() { float map_pres,map_adc,map_vol; // variables para nuestra ecuacion int16 map_in; setup_adc_ports(sAN0,sAN2|VSS_VDD); set_adc_channel(2); // para seleccionar que puerto queremos leer delay_us(20); map_in=read_adc(); delay_us(20); // FORMULA INICIO map_adc=5.0*map_in/1024; map_pres=(map_adc+0.2)/0.02; map_vol=1.382477124*0.00001; // Datos calculados en la memoria técnica map_consm=map_vol*rpm_out*map_pres; // FORMULA FIN } void R232() { float sum=1.0; delay_ms(500); printf(lcd_putc, "\f"); lcd_gotoxy(3,2); printf(lcd_putc,"USB conectado"); printf("\nS.A.D\r"); delay_ms(500); printf(lcd_putc, "\f"); t=4; while (usb_start==1) { usb_start=input(Pin_D3); if (led_count<=1) { led_on(led_parp); } if ((led_count>1)&&(led_count<=2)) { led_off(led_parp); } if ((led_count>2)) { 14 Desarrollo de una unidad de adquisición y monitorización de datos para un vehículo de automoción led_count=0; } if (sum>0) // Lectura de toda la eeprom { lcd_gotoxy(3,2); printf(lcd_putc,"Leyendo datos..."); delay_ms(200); interv++; read_float_ext_eeprom(t); epp_tiempo=out; segundos_total=epp_tiempo; hora=segundos_total/3600; minuto=(segundos_total/60)%60; segundo=segundos_total%60; printf("\n\r"); printf("\nIntervalo = %02u %02u:%02u:%02u\r",interv,hora,minuto,segundo); printf("\n\r"); t=t+4; delay_us(20); read_float_ext_eeprom(t); epp_ntc=out; if (epp_ntc==999) { printf("\nT = -- C\r"); } else { printf("\nT = %04.2f C\r",epp_ntc); } t=t+4; delay_us(20); read_float_ext_eeprom(t); epp_CO2=out; if (epp_CO2==50000) { printf(lcd_putc,"\nCO2 >10000 ppm \r"); } if (epp_CO2==1) { printf(lcd_putc,"\nCO2 <400 ppm \r"); } else { printf("\nCO2 = %04.1f ppm\r",epp_CO2); } t=t+4; delay_us(20); read_float_ext_eeprom(t); epp_rpm=out; printf("\nRPM = %04.1f \r",epp_rpm); t=t+4; delay_us(20); read_float_ext_eeprom(t); epp_spd=out; printf("\nSPD = %04.1f \r",epp_spd); t=t+4; delay_us(20); read_float_ext_eeprom(t); 15 Desarrollo de una unidad de adquisición y monitorización de datos para un vehículo de automoción epp_consm=out; printf("\nConsm = %04.1f \r",epp_consm); t=t+4; delay_us(20); printf(lcd_putc, "\f"); sum = epp_rpm + epp_CO2 + epp_consm + epp_spd; } if (sum<=0) { lcd_gotoxy(3,2); printf(lcd_putc,"Listo!"); interv=0; } } flag_usb=0; } 16 Desarrollo de una unidad de adquisición y monitorización de datos para un vehículo de automoción Capítulo 2 Librería reloj en tiempo real ////////////////////////////////////////////////////////////////////// ////////// /// DS1307.C /// /// Driver for Real Time Clock /// /// /// /// ds1307_init() - Enable oscillator without clearing the seconds register -/// /// used when PIC loses power and DS1307 run from 3V BAT /// /// - Disable squarewave output /// /// /// /// ds1307_set_date_time(day,mth,year,dow,hour,min,sec) Set the date/time /// /// /// /// ds1307_get_date(day,mth,year,dow) Get the date /// /// /// /// ds1307_get_time(hr,min,sec) Get the time /// /// /// ////////////////////////////////////////////////////////////////////// ////////// #define #define #define #define RTC_SDA PIN_B5 RTC_SCL PIN_B4 EEPROM_SDA PIN_B5 EEPROM_SCL PIN_B4 #use i2c(master, sda=RTC_SDA, scl=RTC_SCL) 17 Desarrollo de una unidad de adquisición y monitorización de datos para un vehículo de automoción BYTE bin2bcd(BYTE binary_value); BYTE bcd2bin(BYTE bcd_value); void ds1307_init(void) { BYTE seconds = 0; i2c_start(); i2c_write(0xD0); // WR to RTC i2c_write(0x00); // REG 0 i2c_start(); i2c_write(0xD1); // RD from RTC seconds = bcd2bin(i2c_read(0)); // Read current "seconds" in DS1307 i2c_stop(); seconds &= 0x7F; delay_us(3); i2c_start(); i2c_write(0xD0); // WR to RTC i2c_write(0x00); // REG 0 i2c_write(bin2bcd(seconds)); // Start oscillator with current "seconds value i2c_start(); i2c_write(0xD0); // WR to RTC i2c_write(0x07); // Control Register i2c_write(0x80); // Disable squarewave output pin i2c_stop(); } void ds1307_set_date_time(BYTE day, BYTE mth, BYTE year, BYTE dow, BYTE hr, BYTE min, BYTE sec) { sec &= 0x7F; hr &= 0x3F; i2c_start(); i2c_write(0xD0); i2c_write(0x00); i2c_write(bin2bcd(sec)); i2c_write(bin2bcd(min)); i2c_write(bin2bcd(hr)); i2c_write(bin2bcd(dow)); i2c_write(bin2bcd(day)); i2c_write(bin2bcd(mth)); i2c_write(bin2bcd(year)); i2c_write(0x80); i2c_stop(); // I2C write address // Start at REG 0 - Seconds // REG 0 // REG 1 // REG 2 // REG 3 // REG 4 // REG 5 // REG 6 // REG 7 - Disable squarewave output pin } void ds1307_get_date(BYTE &day, BYTE &mth, BYTE &year, BYTE &dow) { i2c_start(); i2c_write(0xD0); i2c_write(0x03); // Start at REG 3 - Day of week i2c_start(); i2c_write(0xD1); dow = bcd2bin(i2c_read() & 0x7f); // REG 3 day = bcd2bin(i2c_read() & 0x3f); // REG 4 18 Desarrollo de una unidad de adquisición y monitorización de datos para un vehículo de automoción mth = bcd2bin(i2c_read() & 0x1f); year = bcd2bin(i2c_read(0)); i2c_stop(); // REG 5 // REG 6 } void ds1307_get_time(BYTE &hr, BYTE &min, BYTE &sec) { i2c_start(); i2c_write(0xD0); i2c_write(0x00); // Start at REG 0 - Seconds i2c_start(); i2c_write(0xD1); sec = bcd2bin(i2c_read() & 0x7f); min = bcd2bin(i2c_read() & 0x7f); hr = bcd2bin(i2c_read(0) & 0x3f); i2c_stop(); } BYTE bin2bcd(BYTE binary_value) { BYTE temp; BYTE retval; temp = binary_value; retval = 0; while(true) { // Get the tens digit by doing multiple subtraction // of 10 from the binary value. if(temp >= 10) { temp -= 10; retval += 0x10; } else // Get the ones digit by adding the remainder. { retval += temp; break; } } return(retval); } // Input range - 00 to 99. BYTE bcd2bin(BYTE bcd_value) { BYTE temp; temp = bcd_value; // Shifting upper digit right by 1 is same as multiplying by 8. temp >>= 1; // Isolate the bits for the upper digit. temp &= 0x78; // Now return: (Tens * 8) + (Tens * 2) + Ones 19 Desarrollo de una unidad de adquisición y monitorización de datos para un vehículo de automoción return(temp + (temp >> 2) + (bcd_value & 0x0f)); } 20