Los relojes BCD son una molestia con los que trabajar; No tengo idea de por qué son tan populares.
Si uno simplemente desea comparar dos horas o fechas, puede simplemente comparar las partes numéricas de los componentes en orden de menos significativo a más significativo; El año en que se envolvió de 99 a 00 puede haber sido un problema hace 15 años, pero ya no. Es importante tener cuidado con el hecho de que muchos chips BCD utilizan los bits superiores de los campos "decenas" para varios propósitos, por lo que es posible que haya que enmascarar los valores de lectura con 0x3F o 0x7F antes de hacer comparaciones. Además, uno debe asegurarse de que el dispositivo esté configurado para el modo "24 horas", o bien tratar con el hecho de que la mayoría, si no todos, los dispositivos que usan BCD tienen (y pueden por defecto) un modo "12 horas" que numera las horas 0x12, 0x01..0x09, 0x10, 0x11, 0x52, 0x41..0x0x49, 0x50, 0x51 [algunos dispositivos pueden poner el indicador AM / PM en el bit 7 en lugar del bit 6]; en tales dispositivos, las comparaciones numéricas simples no funcionarán desde las 12:00 am hasta las 11:00 am y la 1:00 pm, y las 12:00 pm se ordenarán después de las 11:00 pm.
Mi recomendación al usar cualquier tipo de chip RTC es convertir el tiempo en un número lineal de segundos. Convierta cada byte a un valor decimal haciendo algo como:
unsigned char bcd_to_dec(unsigned char bcd)
{
return bcd - 3*(bcd >> 4);
}
Para las fechas posteriores al 1 de marzo de 2000, reste 3 del mes. Si eso es negativo o mayor que 12, sume 12 al mes y reste uno del año. Eso cambiará el calendario, de modo que el 1 de marzo es el primer día del mes 0 de cada año, por lo que el 29 de febrero será el último día del año.
Calcule el número del 1 de marzo del año (relativo al 1 de marzo de 2000) al calcular (year*365)+(year/4u)
. Agregue un número de día para el mes actual usando una tabla de 12 entradas. Luego agregue (día actual - 1). Eso dará el número de días desde el 1 de marzo de 2000.
Multiplica eso por 24, suma las horas, multiplica eso por 60, suma los minutos, multiplica eso por 60 y suma los segundos.
Todo esto es un poco un poco molesto de trabajo, pero permitirá realizar cálculos con tiempos relativos mucho más fácilmente de lo que era posible con BCD. Se puede minimizar la cantidad de espacio de código requerido si se define un valor global del tipo unsigned long
y un método:
void mul(unsigned char factor) { ulong_acc *= factor; }
Hacer eso reducirá cada paso de multiplicación para que no sea más que un movlw
seguido de una llamada de función.