Compresión del lenguaje C en AVR

while ( ! ( TIFR & 1 << TOV0 ) )

muy buenas soy nuevo en lenguaje c , y tengo y na duda con la compresión de esta linea de código, este ejemplo es de la programación en c de un avr.

lo que hace es esperar el cambio de una bandera para luego ejecutar otra introducción, mi duda des que funcion realiza el ! en esta linea de código.
 

D@rkbytes

Moderador
Mi duda es qué función realiza el ! en esta linea de código.
El signo ! en C es el operador de negación lógica.

Por ejemplo:
if (!flag)
Comprueba que el valor de flag sea cero.
Lo contrario sería:
if (flag)
Que comprueba si el valor de flag es 1 o mayor.
 
si comprueba que es cero o uno , ejecuta la siguiente linea es eso verdad compañero.

y en mi caso el ver el resultado de cero ejecutara las lineas del bucle while ????



#include <avr/io.h>
int main() {
DDRB = 0xFF; // Puerto B como salida
PORTB = 0x00; // Inicializa la salida
TCNT0 = -100; // Para que desborde en el evento 100
TCCR0 = 0x01; // Reloj, sin pre-escalador
while(1) { // Lazo infinito
while( ! ( TIFR & 1 << TOV0 ) ) // Sondea, espera la bandera
;
TIFR = TIFR | 1 << TOV0; // Limpia la bandera, le escribe 1
TCNT0 = -100; // Recarga al temporizador
PORTB = PORTB ^ 0x01; // Conmuta la salida
}
}

este es el ejemplo a analizar , en que caso el while ejecura la siguiente linea de código cuando detecte un cero o otra cantidad mayor ?????????????? perodon la falta de comprecion soy nuevo en esto del c.
 
Última edición:

D@rkbytes

Moderador
La sentencia para mi sería así: while( ! ( TIFR & 1 << TOV0 ) );
O sea, cerrando el bucle con ;
Entonces se saldría del bucle while cuando el valor de TIFR And 1 << TOV0 sea diferente a 0
Por lo tanto, se crea un bucle de espera y cuando se obtenga un valor de 1 o mayor, se continuaría la ejecución de las siguientes instrucciones.

Prácticamente lo que se espera es que la bandera TOV0 (Bit 0 del registro TIFR) se ponga en 1.
 
M

Miembro eliminado 356005

Habría que indicar, además, el orden de ejecución de las operaciones.

Es decir, primero se hace la operación binaria 1<<TOV0, que "desplaza" un bit '1' hacia la izquierda tantas posiciones como indique el valor TOV0. Y con ello se hace luego la operación a nivel de bit '&' o '|' con el contenido del registro TIFR.

Ese orden lo marca la precedencia de los operadores.
 
Última edición por un moderador:
si sos novato, empleando avr-gcc o atmel studio... y estás en WinGate, podrías bajarte el devgcc, y probar esas sentencias que te parecen extrañas sin recurrir a un debug, o al Isis Proteus, esos compiladores son en realidad el gnu-gcc

Tambien en tu condición de novato, es IMPRESINDIBLE que leas "programming 101" , del foro avrfreaks.

Las personas usuarios de los AVR, suelen ser más prolijos, más "ansi" en sus códigos contra los usuarios PIC, los users-avr son ferozmente criptográficos y son son pocos, la info escasea y está en el 99,9% de las ocasiones en Inglés.

http://www.avrfreaks.net/forum/tut-c-bit-manipulation-aka-programming-101?page=all
 
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 :)
 
Arriba