SPI Arduino Due conflitto con pinMode (), bug?


9

Considera il seguente esempio minimo, dove ho impostato pinModeprima di chiamare le funzioni SPI:

#include <SPI.h>

void setup() {
  pinMode(10, OUTPUT);
  SPI.begin(10);
  SPI.setDataMode(10,SPI_MODE1);
}

void loop() {
  delay(1000);
  SPI.transfer(10,1);
}

Ora quando SPI.transfer(10,1)viene chiamato loop(), vedo sempre che il pin selezionato dallo slave scende a 1,65 V, ma non a 0 come dovrebbe! (vedi immagine sotto)

modalità pin impostata prima di chiamare le funzioni SPI

Se non chiamiamo pinMode(), in questo modo:

#include <SPI.h>

void setup() {
  SPI.begin(10);
  SPI.setDataMode(10,SPI_MODE1);
}

void loop() {
  delay(1000);
  SPI.transfer(10,1);
}

Otteniamo ciò che ci aspetteremmo quando chiamiamo SPI.transfer:

Modalità pin non impostata

È un bug o hai una spiegazione per quel comportamento?

Grazie mille in anticipo per il tuo tempo e interesse!


Non dovrebbe essere SPI.setDataMode(10, SPI_MODE1);? Anche solo il secondo è utile, come begin()chiama setDataMode. Guardando il codice sorgente sembra che la libreria SPI non modifichi il pin specificato (anche se non conosco ARM).
— Gerben,

Sì hai ragione, per caso chiamo due volte setDataMode (). Domani testerò l'effetto di SPI.setDataMode (10, SPI_MODE1); Ma perché chiamare pinMode () ha questo effetto non è ancora chiaro o? @Gerben
— newandlost,

@Gerben Ho modificato il mio post
— newandlost

Risposte:


1

Potrebbe avere qualcosa a che fare con il resistore pull up interno. Secondo la scheda tecnica SAM3X / A,

Il controllo della resistenza di pull-up è possibile indipendentemente dalla configurazione della linea I / O.

Dopo il ripristino, tutti i pull-up sono abilitati.

Se cerchi tutti i file inclusi che trovi:

../Arduino/hardware/arduino/samd/cores/arduino/wiring_digtal.c

La riga 124 definisce la pinMode(uint32_t ulPin, uint32_t ulMode)funzione. Esaminando l'istruzione switch / case per INPUT vs INPUT_PULLUP vs OUTPUT viene visualizzato quanto segue:

  1. INPUT imposta un registro su reg = PORT_PINCFG_INEN.
  2. INPUT_PULLUP imposta un registro su reg = (PORT_PINCFG_INEN | PORT_PINCFG_PULLEN)
  3. OUTPUT imposta un registro su reg &= ~PORT_PINCFG_INEN.

Il 'registro' in ogni caso è lo stesso. Per la vita non riesco a trovare quale valore PORT_PINCFG_INEN o PORT_PINCFG_PULLEN sono definiti come, ma sono senza dubbio solo maschere a 8 bit (vengono lanciate su uint8_t quando sono assegnate al 'registro'). Quindi, possiamo supporre che qualunque bit controlli input / output sia attivo quando asserito, così come il bit di pullup. Per esempio:

 PORT_PINCFG_INEN   = b'00000001';
 PORT_PINCFG_PULLEN = b'00000010';
~PORT_PINCFG_INEN   = b'11111110';

Se i pull-up sono abilitati dopo il reset, possiamo dire che al reset:

 reg = b'xxxxxx1x';

Il punto (3) sopra implica fortemente che l'istruzione è:

 reg = b'xxxxxx1x' & 'b11111110';
   so
 reg = b'xxxxxx10'; // pull-up is enabled!

Pertanto, se si chiama pinMode (X, OUTPUT) prima di ogni altra cosa, si otterrà la resistenza pullup abilitata. L'impostazione del pin su un ingresso cancella il bit di abilitazione pullup, dopodiché è possibile impostare il pin su un'uscita e il bit rimarrà chiaro.

Tuttavia, l'intero arguement cade verso il basso con il semplice fatto che se non si chiama pinMode () a tutti , il problema non si verifica ...

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.