SPI Arduino Karena konflik dengan pinMode (), bug?

9

Pertimbangkan contoh minimal berikut, tempat saya mengatur pinModesebelum memanggil fungsi 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);
}

Sekarang ketika SPI.transfer(10,1)dipanggil loop(), saya selalu melihat bahwa pin slave yang dipilih turun ke 1.65V, tetapi tidak 0 seperti seharusnya! (lihat gambar di bawah)

mode pin diatur sebelum memanggil fungsi SPI

Jika kami tidak menelepon pinMode(), seperti ini:

#include <SPI.h>

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

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

Kami mendapatkan apa yang kami harapkan saat menelepon SPI.transfer:

Mode pin tidak diatur

Apakah itu bug atau Anda punya penjelasan untuk perilaku itu?

Terima kasih banyak sebelumnya atas waktu dan minat Anda!

baru dan kalah
sumber
Bukankah seharusnya begitu SPI.setDataMode(10, SPI_MODE1);? Juga hanya yang kedua yang berguna, seperti begin()panggilan setDataMode. Melihat kode sumber sepertinya perpustakaan SPI tidak mengubah pin yang Anda tentukan (meskipun saya tidak tahu ARM).
Gerben
Ja Anda benar, secara tidak sengaja saya memanggil setDataMode () dua kali. Besok saya akan menguji efek SPI.setDataMode (10, SPI_MODE1); Tetapi mengapa memanggil pinMode () memiliki efek ini masih belum jelas atau? @Gerben
newandlost
@Gerben Saya mengubah posting saya
newandlost

Jawaban:

1

Mungkin ada hubungannya dengan resistor pull up internal. Menurut lembar data SAM3X / A,

Kontrol resistor pull-up dimungkinkan terlepas dari konfigurasi jalur I / O.

Setelah reset, semua pull-up diaktifkan.

Jika Anda menggali semua file yang disertakan, Anda menemukan:

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

Baris 124 mendefinisikan pinMode(uint32_t ulPin, uint32_t ulMode)fungsi. Meneliti pernyataan switch / case untuk INPUT vs INPUT_PULLUP vs OUTPUT Anda melihat yang berikut:

  1. INPUT menyetel register ke reg = PORT_PINCFG_INEN.
  2. INPUT_PULLUP mengatur pendaftaran reg = (PORT_PINCFG_INEN | PORT_PINCFG_PULLEN)
  3. OUTPUT menetapkan register reg &= ~PORT_PINCFG_INEN.

'Daftar' dalam setiap kasus adalah sama. Saya tidak bisa seumur hidup saya menemukan nilai PORT_PINCFG_INEN atau PORT_PINCFG_PULLEN apa yang didefinisikan sebagai, tetapi mereka tidak diragukan lagi hanya topeng 8-bit (mereka dilemparkan ke uint8_t ketika mereka ditugaskan ke 'register'). Dengan demikian, kita dapat mengasumsikan bahwa bit mana saja yang mengontrol input / output aktif ketika dinyatakan, seperti halnya bit pullup. Sebagai contoh:

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

Jika pull-up diaktifkan setelah reset, kita dapat mengatakan itu saat reset:

 reg = b'xxxxxx1x';

Poin (3) di atas sangat menyiratkan bahwa instruksi adalah:

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

Karena itu, jika Anda memanggil pinMode (X, OUTPUT) sebelum hal lain, Anda akan berakhir dengan resistor pullup diaktifkan. Mengatur pin ke input akan menghapus bit pullup enable, setelah itu Anda dapat mengatur pin ke output dan bit akan tetap jelas.

Namun, seluruh argumen jatuh dengan fakta sederhana bahwa jika Anda tidak memanggil pinMode () sama sekali , masalahnya tidak terjadi ...

CharlieHanson
sumber