SPI Arduino Aufgrund eines Konflikts mit pinMode (), Fehler?

9

Betrachten Sie das folgende minimale Beispiel, das ich pinModevor dem Aufrufen von SPI-Funktionen festgelegt habe:

#include <SPI.h>

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

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

Wenn jetzt SPI.transfer(10,1)angerufen wird loop(), sehe ich immer, dass der vom Slave ausgewählte Pin auf 1,65 V abfällt, aber nicht auf 0, wie es sollte! (siehe Bild unten)

Pin-Modus eingestellt, bevor SPI-Funktionen aufgerufen werden

Wenn wir nicht anrufen pinMode(), so:

#include <SPI.h>

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

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

Wir bekommen, was wir erwarten würden, wenn wir anrufen SPI.transfer:

Pin-Modus nicht eingestellt

Ist das ein Fehler oder haben Sie eine Erklärung für dieses Verhalten?

Vielen Dank im Voraus für Ihre Zeit und Ihr Interesse!

newandlost
quelle
Sollte es nicht sein SPI.setDataMode(10, SPI_MODE1);? Auch nur der zweite ist nützlich, da begin()setDataMode aufgerufen wird. Wenn man sich den Quellcode ansieht, sieht es so aus, als würde die SPI-Bibliothek den von Ihnen angegebenen Pin nicht ändern (obwohl ich ARM nicht kenne).
Gerben
Ja, Sie haben Recht, aus Versehen rufe ich setDataMode () zweimal auf. Morgen werde ich die Wirkung von SPI.setDataMode (10, SPI_MODE1) testen. Aber warum der Aufruf von pinMode () diesen Effekt hat, ist immer noch nicht klar oder? @ Gerben
Newandlost
@ Gerben Ich habe meinen Beitrag geändert
newandlost

Antworten:

1

Dies könnte etwas mit dem internen Pull-up-Widerstand zu tun haben. Laut SAM3X / A-Datenblatt

Die Steuerung des Pull-up-Widerstands ist unabhängig von der Konfiguration der E / A-Leitung möglich.

Nach dem Zurücksetzen sind alle Klimmzüge aktiviert.

Wenn Sie alle Include-Dateien durchsuchen, die Sie finden:

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

Zeile 124 definiert die pinMode(uint32_t ulPin, uint32_t ulMode)Funktion. Wenn Sie die switch / case-Anweisung für INPUT vs INPUT_PULLUP vs OUTPUT untersuchen, sehen Sie Folgendes:

  1. INPUT setzt ein Register auf reg = PORT_PINCFG_INEN.
  2. INPUT_PULLUP setzt ein Register auf reg = (PORT_PINCFG_INEN | PORT_PINCFG_PULLEN)
  3. OUTPUT setzt ein Register auf reg &= ~PORT_PINCFG_INEN.

Das 'Register' ist jeweils das gleiche. Ich kann für mein ganzes Leben nicht finden, als welchen Wert PORT_PINCFG_INEN oder PORT_PINCFG_PULLEN definiert sind, aber es handelt sich zweifellos nur um 8-Bit-Masken (sie werden in uint8_t umgewandelt, wenn sie dem 'Register' zugewiesen werden). Wir können also davon ausgehen, dass jedes Bit, das die Ein- / Ausgabe steuert, aktiv ist, wenn es aktiviert ist, ebenso wie das Pullup-Bit. Zum Beispiel:

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

Wenn Klimmzüge nach dem Zurücksetzen aktiviert sind, können wir dies beim Zurücksetzen sagen:

 reg = b'xxxxxx1x';

Punkt (3) oben impliziert stark, dass die Anweisung lautet:

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

Deshalb , wenn Sie pinMode (X, OUTPUT) , bevor irgendetwas nennen sonst werden Sie aktiviert mit dem Pull - up - Widerstand am Ende. Wenn Sie den Pin auf einen Eingang setzen, wird das Pullup-Aktivierungsbit gelöscht. Danach können Sie den Pin auf einen Ausgang setzen und das Bit bleibt frei.

Die ganze Argumentation fällt jedoch mit der einfachen Tatsache zusammen, dass das Problem nicht auftritt , wenn Sie pinMode () überhaupt nicht aufrufen ...

CharlieHanson
quelle