Considere el siguiente programa C:
#include <avr/io.h>
int main(void)
{
DDRB |= 1 << PB0; /* LED */
PORTB |= 1 << PB5; /* pullup */
if (!(PINB & 1 << PB5))
PORTB |= 1 << PB0; /* turn on LED */
while (1) ;
}
Hay dos situaciones:
-
conecte un cable de 10 cm a
PB5
pin (el otro extremo del cable está en el aire): el resultado es que algunas veces después de encender el led, a veces el led no está encendido. -
no conecte nada a
PB5
pin: el resultado es que después de que el led poweron nunca se enciende.
En hoja de datos en la sección 10.2.4 "Lectura del valor del PIN" nada se aplica a este caso.
La pregunta es: ¿qué hace que PINB & 1 << PB5
lea valor cero, a pesar del hecho de que se ha levantado? ¿Y cómo resolver este problema?
Si agrego un retraso de 10 ms después de arrancar, el led nunca se enciende después del encendido. ¿Por qué? ¿Dónde se describe?
#include <avr/io.h>
#define F_CPU 16000000UL
#include <util/delay.h>
int main(void)
{
DDRB |= 1 << PB0; /* LED */
PORTB |= 1 << PB5; /* pullup */
_delay_ms(10);
if (!(PINB & 1 << PB5))
PORTB |= 1 << PB0; /* turn on LED */
while (1) ;
}
Pero esta demora es solo para mostrar que hay algo mal. No quiero usar la demora para resolver este problema. Quiero saber la causa (y la correcta fix).
( Nota: en mi proyecto, este cable que cuelga en el aire es un extremo de un interruptor de botón, y el microcontrolador a veces detecta que se presionó un botón (mientras no lo estaba), lo cual es un gran problema. )
EDIT
El "sincronizador" no ayuda. En el siguiente ejemplo, algunas instrucciones se ejecutan después de habilitar la extracción. Pero el comportamiento es el mismo que se describió originalmente.
#include <avr/io.h>
int main(void)
{
PORTB |= 1 << PB5; /* pullup */
DDRB |= 1 << PB0; /* LED */
if (!(PINB & 1 << PB5))
PORTB |= 1 << PB0; /* turn on LED */
while (1) ;
}
EDIT2 Consulte también esta respuesta.