SPI Arduino Due konflikt z pinMode (), błąd?

9

Rozważ następujący minimalny przykład, w którym ustawiłem pinModeprzed wywołaniem funkcji 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);
}

Teraz, kiedy SPI.transfer(10,1)jest wywoływany loop(), zawsze widzę, że wybrany pin slave spada do 1,65 V, ale nie 0, jak powinien! (patrz zdjęcie poniżej)

tryb pin ustawiony przed wywołaniem funkcji SPI

Jeśli nie dzwonimy pinMode(), tak:

#include <SPI.h>

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

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

Otrzymujemy to, czego oczekujemy, dzwoniąc SPI.transfer:

Tryb pin nie jest ustawiony

Czy to błąd, czy masz wyjaśnienie tego zachowania?

Z góry dziękuję za poświęcony czas i zainteresowanie!

newandlost
źródło
Nie powinno tak być SPI.setDataMode(10, SPI_MODE1);? Przydaje się tylko drugi, ponieważ begin()wywołania setDataMode. Patrząc na kod źródłowy wygląda na to, że biblioteka SPI nie zmienia podanego pinu (chociaż nie znam ARM).
Gerben,
Ja masz rację, przez przypadek dzwonię setDataMode () dwa razy. Jutro przetestuję efekt SPI.setDataMode (10, SPI_MODE1); Ale dlaczego wywołanie pinMode () ma ten efekt wciąż nie jest jasne lub? @Gerben
newandlost
@Gerben Zmodyfikowałem swój post
newandlost

Odpowiedzi:

1

Może to mieć coś wspólnego z wewnętrznym rezystorem podciągającym. Zgodnie z arkuszem danych SAM3X / A,

Sterowanie rezystorem podciągającym jest możliwe bez względu na konfigurację linii we / wy.

Po zresetowaniu wszystkie podciągnięcia są włączone.

Jeśli przejrzysz wszystkie znalezione pliki dołączania:

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

Wiersz 124 określa pinMode(uint32_t ulPin, uint32_t ulMode)funkcję. Analizując instrukcję switch / case dla INPUT vs INPUT_PULLUP vs OUTPUT, widzisz:

  1. INPUT ustawia rejestr na reg = PORT_PINCFG_INEN.
  2. INPUT_PULLUP ustawia rejestr na reg = (PORT_PINCFG_INEN | PORT_PINCFG_PULLEN)
  3. WYJŚCIE ustawia rejestr na reg &= ~PORT_PINCFG_INEN.

„Rejestr” w każdym przypadku jest taki sam. Nie mogę przez całe życie znaleźć, jaką wartość PORT_PINCFG_INEN lub PORT_PINCFG_PULLEN są zdefiniowane, ale bez wątpienia są to tylko 8-bitowe maski (są one przesyłane do uint8_t, gdy są przypisywane do „rejestru”). Możemy zatem założyć, że którykolwiek bit kontrolujący wejście / wyjście jest aktywny, gdy jest potwierdzony, podobnie jak bit pullup. Na przykład:

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

Jeśli pull-upy są włączone po resecie, możemy powiedzieć, że po resecie:

 reg = b'xxxxxx1x';

Punkt 3 powyżej wyraźnie sugeruje, że instrukcja jest:

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

Dlatego jeśli wywołasz pinMode (X, WYJŚCIE) przed czymkolwiek innym , skończysz z włączonym rezystorem podciągającym. Ustawienie pinu na wejście wyczyści bit włączania pullup, po czym możesz ustawić pin na wyjście, a bit pozostanie czysty.

Jednak cała arguement spada z prostego faktu, że jeśli nie nazywamy pinMode () w ogóle , problem nie występuje ...

CharlieHanson
źródło