Как считывать данные с помощью Arduino SPI
в таблице данных указано, что я должен применить 32 последовательных такта, чтобы получить 32 бита данных. Как я могу запрограммировать это Arduino?
@Lorenz Ardiente, 👍1
Обсуждение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
Цель состоит в том, чтобы прочитать 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
Sparkfun имеет хорошее объяснение того, что такое SPI:
https://learn.sparkfun.com/tutorials/serial-peripheral-interface-spi
Arduino IDE имеет библиотеку SPI, которая поставляется вместе с IDE.
http://www.arduino.cc/en/Reference/SPI
Библиотека поставляется с двумя примерами:
Использование SPI для считывания показаний датчика барометрического давления
Управление цифровым потенциометром с помощью SPI
- Как использовать SPI на Arduino?
- Как увеличить скорость записи на SD-карту в Ардуино
- Как передать более 1 байта сразу по шине SPI?
- OVF в последовательном мониторе вместо данных
- Как отправить строку с подчиненного устройства Arduino с помощью SPI?
- Проблема совместного использования MISO с несколькими RFID-считывателями RC522
- Путаница между SPI и I2C для SSD1306 OLED
- Какие контакты можно использовать для выбора микросхемы (CS, CC) на Arduino Nano Every?
Я предлагаю вам открыть примеры библиотеки 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