while ( ! ( TIFR & 1 << TOV0 ) )
no me gusta como está escrito, me gustaría más con un paréntesis adicional, y separo en más líneas para ver mejor qué paréntesis afecta a cada cosa:
while (
!( TIFR & (1 << TOV0) )
)
Ahí está usando un registro TIFR (un registro de propósito especial) supongo que será un registro de operación de un timer, y seguramente dentro de ese registro hay un bit que se llama TOV0.
TOV0 es una etiqueta (un #define) que debe indicar el número de bit, si es un registro de 8 bits podrá valer de 0 a 7. Cuál sera su valor lo indica el #define y debe corresponder con la hoja de datos del microcontrolador.
Para usar operaciones lógicas and (&) y or ( | ) queremos obtener una máscara del bit:
bit máscara bin / hexa / operación shift
0 0b00000001 = 0x01 = 1 << 0
1 0b00000010 = 0x02 = 1 << 1
2 0b00000100 = 0x04 = 1 << 2
3 0b00001000 = 0x08 = 1 << 3
4 0b00010000 = 0x10 = 1 << 4
5 0b00100000 = 0x20 = 1 << 5
6 0b01000000 = 0x40 = 1 << 6
7 0b10000000 = 0x80 = 1 << 7
Entonces con (1<<TOV0) está obteniendo la máscara del bit TOV0.
Otros fabricantes pueden definir TOV0 directamente como máscara, pero aquí el fabricante está definiendo TOV0 como número de bit, de ahí la necesidad de usar la operación shif leftt/desplazamiento a la izquierda.
Otro detalle, bien hecho debería escribirse
(1U <<TOV0)
La U indica al compilador que 1 es un entero SIN signo, de lo contrario dependiendo del compilador se podría interpretar que 1 es un entero con signo, y una operación shift aplicada sobre un entero con signo.... dudo que sea un comportamiento estandar igual para todos los compiladores.
Bueno, entonces tengo la máscara del bit, ¿por qué la quiero?
( TIFR & (1U << TOV0) )
La operación and hace una and bit a bit entre la máscara del bit TOV0 y el registro TIFR.
La máscara del bit TOV0 tiene un 1 en la posición TOV0, y todos los demás bits en 0.
Por lo tanto la operación and (&) entre TIFR y la máscara de TOV0 nos devuelve el valor del bit TOV0 del registro TIFR, por que la and pone a 0 el resto de todos los bits.
En realidad nos estamos quedando con el valor del bit TOV0 del registro TIFR desplazado.
Quiero decir, no me quedo con un valor 0 o 1, me quedo con un valor 0 o (1U <<TOV0).
Si TOV0 vale 3:
( TIFR & (1U << TOV0) ) = ( TIFR & (1U << 3) ) = ( TIFR & 0b00000100 )
El resultado de esa operación puede ser 0 (si el registro TIFR en ese momento tiene ese bit puesto a 0) o 0b00000100 que NO es 1.
No es el valor del bit, sino el valor de la máscara del bit.
PERO, para el lenguaje C un valor 0 es un false lógico, y un valor distinto de 0 es un true lógico.
Por eso al aplicar la operación negación: !() da igual que sea la máscara del bit o el valor del bit.
!(1) = 0
!(0b00000100) = 0
!(0) = algo distinto de 0
Repito: esto es para lenguaje C, otros lenguajes de programación pueden no interpretarlo así.
Entonces "leamos" la expresión !( TIFR & (1 << TOV0) )
El bit TOV0 del registro TIFR negado.
Por último
while (
!( TIFR & (1 << TOV0) )
)
el while va a ejecutarse mientras lo que hay dentro del paréntesis del while (el más externo) sea verdadero.
Eso significa que el while va a ejecutarse cuando el negado(bit TOV0 del registro TIFR) = verdadero.
Que es lo mismo que decir que se ejecuta cuando el bit TOV0 del registro TIFR es 0.
FIN
