La manipulación directa del puerto da un resultado aleatorio: ¿Es necesario un retraso?

3

Configuración (Arduino Pro Mini ATmega328p 16MHz, 5V, sin pin conectado):

Cuandosellamadesdesetup(),estofunciona:

pinMode(11,INPUT_PULLUP);boolidentifiesAsFast=digitalRead(11);//alwaystrue

Estono:

constuint8_tidentificationPinBitNumber=PB3;//pin11constbyteidentificationPinBit=bit(identificationPinBitNumber);DDRB&=~identificationPinBit;PORTB|=identificationPinBit;boolidentifiesAsFast=PINB&identificationPinBit;//occasionallyfalse

Elpin11noestáconectado,pero,comopuedeverarriba,lotengomuyalto.Asíqueesperaríaquesiempretuvieraunvalorde1.

¿Quémefaltaalhacerlamanipulacióndirectadepuertos?

MesaleelcomportamientoconcuatroArduinoProMinisdiferentes.TodossonProMinisoriginales,diseñadosporSparkfun,fabricadosenlosEstadosUnidosycompradosaDigi-Key.Unadeellaslasaquéreciénsacadadelabolsaoriginal.PuedequetengaquequitareinsertareladaptadorFTDIunastreintaveces,peroeventualmentepuedoreproducirelproblema.

Agregarunademorade100msentrelaextraccióndelpin11ylalecturapareceresolverelproblema.Sinembargo,noentiendoporquéeseretrasoseríanecesario.

PB3paraelpin11escorrecto,comoverifiquéconectandounLEDyhaciendoqueparpadee.Consultetambiéneldiagramadeasignacióndepinesquesepuedeencontrarencualquierotrositiodelaweb:

Código completo:

// Felix E. Klee <[email protected]>

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);
}
    
pregunta feklee

2 respuestas

4

Por extraño que parezca, tu código es demasiado rápido .

El pin (y la parte de la placa de pruebas a la que está enchufado) tienen alguna capacidad. Se necesita tiempo para que el pullup resistivo en el AVR tire del pin hacia arriba.

Las funciones Arduino pinMode() y digitalRead() son lo suficientemente lentas para que, al momento de leer el pin, el pullup haya hecho su trabajo. Su código está accediendo a los registros directamente, lo que es considerablemente más rápido, por lo que es posible que el pin aún esté bajo cuando lo lea.

La cantidad de demora que necesitas es bastante mínima, sin embargo. 50 microsegundos (¡no milisegundos!) Deberían ser suficientes.

    
respondido por el duskwuff
3

¡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 lo siguiente:

PORTB |= (1 << PB5) // Set a bit

PORTB &= ~(1 << PB5) // Clear a bit

    
respondido por el Long Pham

Lea otras preguntas en las etiquetas