¿Por qué PINxn with pullup lee cero cuando no hay nada conectado a él?

0

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.

    
pregunta Igor Liferenko

1 respuesta

5

Vaya a la página 68 de su hoja de datos.
Echa un vistazo al segundo párrafo

  

Al leer un valor de pin asignado por software, una instrucción nop   debe insertarse como se indica ...

La misma racionalidad se aplica aquí cuando habilitas el pullup: necesitas al menos un retardo de una sola instrucción entre habilitar el pullup (o configurar la salida) y leer el estado del pin.
Esto permite que los flip-flops de sincronización IO (vea el bloque "SINCRONIZADOR" en la figura 10-2 en la página 66) para hacer su trabajo.

Como ha indicado que tiene algunos cables 'largos' conectados a este pin, es posible que tenga suficiente capacitancia en la línea para retrasar aún más el tiempo de subida de la señal, por lo que es posible que un solo nop pueda no será suficiente.
Pero tendría que hacer algunas mediciones cuidadosas (mirando el tiempo de aumento) o cálculos (la constante de tiempo RC usando los valores de resistencia de pullup y capacidad adicional) para estar seguro.

    
respondido por el brhans

Lea otras preguntas en las etiquetas