Как считывать данные с помощью Arduino SPI

spi

в таблице данных указано, что я должен применить 32 последовательных такта, чтобы получить 32 бита данных. Как я могу запрограммировать это Arduino?

, 👍1

Обсуждение

Я предлагаю вам открыть примеры библиотеки SPI и проверить их. Во всяком случае, код должен быть byte result[4]; for (i = 0; i < 4; i ++) result[i] = SPI.transfer(0x00); и вы найдете в result нужные вам 32 бита, @frarugi87

Я уже это сделал. но энергетический чип, который я использую, - это STPM10, и он предполагает, что я должен использовать симплексный синхронный SPI там, где MOSI не подключен. существует только временная диаграмма для переключения между чтением байтов и записью байтов. Когда я использовал SPI.transfer(), данные не стабильны и, как мне кажется, не надежны, @Lorenz Ardiente

Как вы можете говорить, что это ненадежно? Периферийное устройство является полнодуплексным, и в соответствии с тем, как оно работает, единственный способ получения данных - это отправка фиктивных данных. Если MOSI не подключен, что ж, это не имеет значения; однако обратите внимание, что вы не можете использовать контакт MOSI для других задач. Кстати, вы не забыли правильно установить вывод slave select другого периферийного устройства? Вы использовали штырь SS на плате arduino или другой?, @frarugi87


3 ответа


3

Вы вызываете SPI.transfer() четыре раза, каждый раз сохраняя возвращаемое значение в переменной после правильного сдвига битов.

uint32_t val;
val = SPI.transfer(0xff);  //0xff - фиктивный
val |= (uint32_t)SPI.transfer(0xff) << 8;
val |= (uint32_t)SPI.transfer(0xff) << 16;
val |= (uint32_t)SPI.transfer(0xff) << 24;

Я предполагаю, что наименее значимый байт принимается первым. Убедитесь, что режим SPI является правильным, как указано в вашем техническом описании.

Если подчиненное устройство не может справиться с деассертированием между байтами (что и сделает SPI.transfer() в конце транзакции), то вы можете либо попробовать аппаратный подход SPI st2000, либо использовать bitbanged SPI с shiftIn().

,

Не уверен, что это сработает. Нам действительно нужно знать, как работает подчиненный SPI, прежде чем мы сможем предположить, как он отреагирует. Кроме того, если строка выбора чипа утверждается и отменяется с каждой 8-битной транзакцией SPI, насколько хорошо спроектирован подчиненный SPI? То есть такой подчиненный SPI может легко выйти из синхронизации с ведущим SPI. В частности, как вы уверены, какой 8-битный байт вы на самом деле читаете?, @st2000

@st2000 ОП счел нужным не давать достаточно подробностей; ничего, кроме предположений, нельзя сделать, пока это не изменится., @SoreDakeNoKoto

Все примеры, которые я видел, используют SPI,transfer(0) для чтения данных, а не SPI.transfer(0xff). Они также используют SPI.transfer и для записи данных. Я до сих пор не понял, что SPI делает с 0 или 0xff, когда вы на самом деле читаете данные. Это послано рабу?, @S. Imp

@S.Imp Это фиктивные байты. Вы можете отправить все, что захотите, но устройство на другом конце провода все равно отбросит их, если даже обратит на данные какое-то внимание. SPI.transfer() всегда используется частично из-за внутренней полнодуплексной природы SPI и (в результате первого фактора), а затем частично из-за того, как большинство микроконтроллеров реализуют свои периферийные устройства SPI. Как только часы начинают работать, на линиях MOSI и MISO всегда есть "данные", и каждый участник шины должен прочитать их или нет, решая на основе любого предопределенного протокола более высокого уровня, являются ли эти "данные" значимыми или нет., @SoreDakeNoKoto

Было бы не совсем неверно сказать, что вы не можете по-настоящему читать, не записывая на шину SPI, и наоборот. Поэтому имеет смысл просто спроектировать периферийное устройство, которое принимает байт в одном регистре и через 8 циклов возвращает байт в другом (или даже в том же самом) регистре, просто чтобы обобщить случаи использования. Затем приложение пользователя должно решить, интересует ли его только тот байт, который был записан в первую очередь (TX), или тот, который был считан обратно (RX), или и то, и другое (TX и RX). Кроме того, отсюда и неоднозначное название "transfer()", поскольку он выполняет как функции чтения, так и записи., @SoreDakeNoKoto


0

Цель состоит в том, чтобы прочитать 32 бита с помощью SPI-порта (неизвестного) устройства.

Если устройство будет терпеть активность линии выбора чипа SPI (переход от неактивного к активному и неактивному для каждого считанного 8-битного байта), вы сможете получить желаемые 32 бита данных, выполнив 4 последовательных 8-битных считывания SPI.

Однако если устройство не будет терпеть вышеуказанную активность линии выбора чипа SPI (то есть если устройство требует, чтобы выбор чипа SPI был активен для всей 32-битной транзакции SPI), вы не можете разделить 32-битную транзакцию на 4 отдельные 8 - битные транзакции SPI без контроля чипа SPI Выберите строку. Следующий пример кода иллюстрирует, как это делается:

void loop(){
//передача 0x0F на устройство на выводе 10, сохранить выбранный чип
SPI.transfer(10, 0xF0, SPI_CONTINUE);
//передача 0x00 на устройство на выводе 10, сохранить выбранный чип
SPI.transfer(10, 0×00, SPI_CONTINUE);
//передача 0x00 на устройство на выводе 10, сохранение байта, полученного в response1, сохранение выбранного чипом
byte response1 = SPI.transfer(10, 0×00, SPI_CONTINUE);
//передача 0x00 на устройство на выводе 10, сохранение байта, полученного в response2, отмена
byte response2 = SPI.transfer(10, 0×00);
}

Приведенный выше пример взят с веб-страницы библиотеки Arduino SPI и представляет собой 16-битную (а не 32-битную) передачу. Чтобы закодировать 32-битную передачу, продолжайте вызывать метод SPI.transfer с помощью параметра SPI_CONTINUE.

добавлено позже...

Похоже, люди не рекомендуют использовать методы DueExtendedSPI. А SPISettings и SPI.beginTransaction() должны использоваться? Если это так, то на этой странице показан пример кода, где код явно управляет строкой выбора чипа SPI (ищите slaveAPin & slaveBPin). Обратите внимание, как код считывает 24 бита с ведомого устройства A и записывает 8 бит на ведомое устройство B. Чтобы прочитать 32 бита вместо 24, нам нужно изменить сегмент кода (наряду с несколькими другими вспомогательными изменениями) следующим образом:

...
  SPI.beginTransaction(settingsA);
  digitalWrite (slaveAPin, LOW);
  // только чтение, поэтому отправленные данные не имеют значения
  val0 = SPI.transfer(0);
  val1 = SPI.transfer(0);
  val2 = SPI.transfer(0);
  val3 = SPI.transfer(0);
  digitalWrite (slaveAPin, HIGH);
  SPI.endTransaction();
...
,

Нам действительно нужно увидеть спецификации ведомого устройства SPI, чтобы составить более конкретный ответ., @st2000

Я использую оценочную плату STPM10. Соединение представляет собой симплексный синхронный SPI, а MOSI Arduino ни к чему не подключен. Существует временная диаграмма для переключения между только для чтения и только для записи. Мои проблемы связаны с тем, как считывать данные из регистров чипа. Я использовал SPI.transfer, но не думаю, что эти данные надежны., @Lorenz Ardiente

Временная диаграмма STPM10, найденная на странице 11 спецификации, не похожа на стандартную транзакцию SPI. Я склонен сказать, что вы не можете использовать библиотеку Arduino SPI. Вместо этого вам, возможно, придется полностью разобраться с этим в программном обеспечении. Например, я не верю, что в стандартной шине SPI есть линия "SYN". И я не верю, что линия выбора чипа должна идти высоко до конца транзакции SPI., @st2000


1

Sparkfun имеет хорошее объяснение того, что такое SPI:
https://learn.sparkfun.com/tutorials/serial-peripheral-interface-spi

Arduino IDE имеет библиотеку SPI, которая поставляется вместе с IDE.
http://www.arduino.cc/en/Reference/SPI

Библиотека поставляется с двумя примерами:
Использование SPI для считывания показаний датчика барометрического давления
Управление цифровым потенциометром с помощью SPI

,