Que es UL es Unsigned Long o entero Largo
Que es tmp es una variable unsigned long que uso en la función hora_to_binario, lindo nombre spanenglish no?
Bueno bromas a parte.
Lo primero es decir que no esperaba que funcionar de primera. Jaja eso no es habitual, y no lo digo de vanidoso, sino porque soy mas de prueba error. Bueno la prueba salió bien.
Para entender como funciona esa rutina voy a explicarla una ves mas.
todo comienza con el uso de un reloj que supongo has aceptado que funciona usando millis() pero que ahora no nos interesa. Lo hace bien y ese es el punto. Se fija la hora y arranca y mantiene hh:mm:ss
Si se apaga perdemos todo, por eso de nuevo hay que fijarle la hora.
Se puede mejorar si.. claro.. RTC que le daría hora real y/o alguna rutina para actualizarlo pero hay mucho hecho y mucha librería asi que no vale la pena ahora.
Tenemos entonces 3 datos, que pueden ser enteros o bytes. Como me gusta siempre pensar en que tengo poca memoria intento siempre usar el tipo de variable que menos gasto de SRAM tenga. En este caso byte.
hour() minute() y second() me daran valores que almacenaría en 3 variables tipo byte
de hecho asi comienza la rutina
void hora_to_binario(byte hora, byte min, byte seg) {
a continuación, tenemos que armar en una variable algo que tenga cada uno de los numeros BCD en sus posiciones correctas.
imagina esta hora 18:04:27 bien, recuerda que son bytes, 3 bytes. byte1 = 18 byte2 = 04 byte3 = 27
Pero cuando los miras en forma binaria, su representación no es BCD sino binaria.
27 = 00011011 en binario pero 27 en BCD es 0010 0111
Son dos cosas diferentes.
Cómo paso 27 binario a BCD bueno tomo sus elementos uno a uno 2 y 7 y lo vuelvo a armar.
27 / 10 = 2
son divisiones enteras así que no tienen resto y justamente para obtener la unidad tienes dos caminos, usar módulo o usar una operación tal que multiplique el entero recién obtenido x 10 y todo restarlo del número original.
27-2*10= 7
Como eso implica varias operaciones matemáticas no es eficiente y lo descarto.
Por eso usamos módulo, que es una operación implementada a nivel procesador.
27%10=7
Con esto obtienes cada uno de los números BCD.
El siguiente paso es ubicarlos ordenadamente y conformar un número que lo contenga.
Serán 24 bits.. pues un enterlo largo tiene 32 bits de capacidad. Un entero tiene 16 bits.
Por comodidad puse unsigned long (sin signo).
Recordemos el ejemplo : 18:04:27 y esto expresado en BCD sería
1 8 0 4 2 7
0001 1000 0000 0100 0010 0111
Ahi tienes los 24 bits. Quiere decir que cada 4 bits tengo que hacer un desplazamiento a la izquierda de cada número.
De derecha a izquierda
7 no se desplaza
2 se desplaza 4 bits
4 se desplaza 8 bits
0 se desplaza 12 bits
8 se desplaza 16 bits
1 se desplaza 20 bits
La operación de desplazamiento a izquierda es << y la operacion de suma binaria es OR |
Asi que esto
unsigned long tmp = (unsigned long) (hora/10)<<20 |
(unsigned long) (hora%10)<<16 |
(unsigned long) (min/10)<<12 |
(unsigned long) (min%10)<<8 |
(unsigned long) (seg/10)<<4 |
(unsigned long) (seg%10);
He quitado los UL porque comprobé que no eran necesarios. Pero si es necesario el (typecast) o sea que la operación sea (unsigned long) de lo contrario el compilador lo hace como enteros y veras que todo lo que esta desde 16 bits en adelante no aparece. Me llevo un momento visualizarlo pero aunque entendía el error pensé que eran los números a derecha por eso le puse 20UL y luego comprobé que no era la solución.
No se si te quedan mas dudas?