Configuración (Arduino Pro Mini ATmega328p 16MHz, 5V, sin pin conectado):
Cuando se llama desde el setup()
, esto funciona:
pinMode(11, INPUT_PULLUP);
bool identifiesAsFast = digitalRead(11); // always true
Esto no:
const uint8_t identificationPinBitNumber = PB3; // pin 11
const byte identificationPinBit = bit(identificationPinBitNumber);
DDRB &= ~identificationPinBit;
PORTB |= identificationPinBit;
bool identifiesAsFast = PINB & identificationPinBit; // occasionally false
El pin 11 no está conectado, pero, como puede ver arriba, lo tengo en alto. Así que esperaría que siempre tenga un valor de 1.
¿Qué me estoy perdiendo al hacer la manipulación directa del puerto?
Obtengo el comportamiento con cuatro Arduino Pro Minis diferentes. Todos son Pro Minis originales, diseñados por Sparkfun, fabricados en EE. UU. y comprados a Digi-Key. Uno de ellos lo saqué recién sacado de la bolsa original. Es posible que tenga que quitar e insertar el adaptador FTDI unas treinta veces, pero finalmente puedo reproducir el problema.
Agregar un retraso de 100 ms entre tirar del pin 11 y leerlo parece resolver el problema. Sin embargo, no entiendo por qué ese retraso sería necesario.
PB3
para el pin 11 es correcto, como comprobé conectando un LED y haciéndolo parpadear. Consulte también el diagrama de asignación de pines que se puede encontrar en otros lugares de la web:
Código completo:
// Felix E. Klee <felix.klee@inka.de>
const uint8_t ledPinBitNumber = PB5; // pin 13
const byte ledPinBit = bit(ledPinBitNumber);
const uint8_t identificationPinBitNumber = PB3; // pin 11
const byte identificationPinBit = bit(identificationPinBitNumber);
unsigned long delayDuration; // ms
void turnLedOn() {
PORTB |= ledPinBit;
}
void turnLedOff() {
PORTB &= ~ledPinBit;
}
void setDelayDuration() {
#if 0
pinMode(11, INPUT_PULLUP);
bool identifiesAsFast = digitalRead(11); // always true
#else
// Input pullup:
DDRB &= ~identificationPinBit;
PORTB |= identificationPinBit;
bool identifiesAsFast = PINB & identificationPinBit; // occasionally false
#endif
delayDuration = identifiesAsFast ? 300 : 3000;
}
void setup() {
DDRB |= ledPinBit; // Set up LED pin for output
setDelayDuration();
}
void loop() {
turnLedOn();
delay(delayDuration);
turnLedOff();
delay(delayDuration);
}
Por extraño que suene, tu código es demasiado rápido .
El pin (y la parte de la protoboard a la que está enchufado) tiene algo de capacitancia. Se necesita tiempo para que el pull-up resistivo en el AVR levante el pin.
El Arduino pinMode()
y digitalRead()
las funciones son lo suficientemente lentos como para que, cuando lleguen a leer el pin, el pullup haya hecho su trabajo. Su código está accediendo a los registros directamente, lo cual es considerablemente más rápido, por lo que es posible que el pin aún esté bajo cuando lo lea.
Sin embargo, la cantidad de retraso que necesita es bastante mínima. 50 microsegundos (¡no milisegundos!) deberían ser suficientes.
¡Lo estás haciendo de la manera incorrecta!
Un puerto Arduino consta de 8 pines, por ejemplo PB0, PB2, PB3, ..., PB7.
Si desea manipular un registro o un bit o algunos bits, puede que tenga que hacer esto:
PORTB |= (1 << PB5) // Set a bit
PORTB &= ~(1 << PB5) // Clear a bit
PORTB &= ~(1 << PB5) // Clear a bit
No puedo editar ya que es un cambio de un solo carácter.bit
(definido en Arduino.h ) y constantes, vemos que es PORTB |= identificationPinBit
igual a PORTB |= 1ul << PB3
. El asunto está en otra parte.define
se usa en algún lugar de la máquina interna de Arduino, lo que encuentro sobre bit()
la función puede referirse a esto .
feklee
feklee