SPI Arduino Из-за конфликта с pinMode (), ошибка?

9

Рассмотрим следующий минимальный пример, который я установил pinModeперед вызовом функций 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);
}

Теперь, когда SPI.transfer(10,1)вызывается loop(), я всегда вижу, что выбранный ведомый вывод падает до 1,65 В, но не 0, как должно! (см. изображение ниже)

режим вывода установлен перед вызовом функций SPI

Если мы не позвоним pinMode(), вот так:

#include <SPI.h>

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

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

Мы получаем то, что ожидаем при звонке SPI.transfer:

Режим вывода не установлен

Это ошибка или у вас есть объяснение такого поведения?

Заранее большое спасибо за ваше время и интерес!

newandlost
источник
Не должно ли это быть SPI.setDataMode(10, SPI_MODE1);? Также полезен только второй, так как begin()вызывает setDataMode. Глядя на исходный код, похоже, что библиотека SPI не меняет указанный вами вывод (хотя я не знаю ARM).
Гербен
Ja ты прав, случайно я вызываю setDataMode () дважды. Завтра я проверю эффект SPI.setDataMode (10, SPI_MODE1); Но почему вызов pinMode () имеет этот эффект до сих пор не ясно или? @ Гербен
newandlost
@ Гербен Я изменил свой пост
newandlost

Ответы:

1

Это может быть связано с внутренним подтягивающим резистором. Согласно данным SAM3X / A,

Управление подтягивающим резистором возможно независимо от конфигурации линии ввода / вывода.

После сброса все подтягивания включены.

Если вы перебираете все найденные файлы включения:

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

Линия 124 определяет pinMode(uint32_t ulPin, uint32_t ulMode)функцию. Изучая инструкцию switch / case для INPUT против INPUT_PULLUP против OUTPUT, вы видите следующее:

  1. INPUT устанавливает регистр в reg = PORT_PINCFG_INEN.
  2. INPUT_PULLUP устанавливает регистр в reg = (PORT_PINCFG_INEN | PORT_PINCFG_PULLEN)
  3. OUTPUT устанавливает регистр в reg &= ~PORT_PINCFG_INEN.

«Регистр» в каждом случае одинаков. Я не могу на всю жизнь найти, какое значение PORT_PINCFG_INEN или PORT_PINCFG_PULLEN определены как, но они, без сомнения, просто 8-битные маски (они приводятся к uint8_t, когда они назначаются в «регистр»). Таким образом, мы можем предположить, что любой бит, управляющий вводом / выводом, активен при подтверждении, как и бит подтягивания. Например:

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

Если подтяжки активируются после сброса, мы можем сказать, что при сбросе:

 reg = b'xxxxxx1x';

Пункт 3 выше строго подразумевает, что инструкция:

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

Поэтому, если вы вызываете pinMode (X, OUTPUT) раньше, чем-либо еще, вы в конечном итоге получите включенный нагрузочный резистор. Установка вывода на вход очистит бит включения подтягивания, после чего вы можете установить вывод на выход, и этот бит останется чистым.

Тем не менее, вся arguement падает с простым фактом , что , если вы не вызываете pinMode () вообще , проблема не возникает ...

CharlieHanson
источник