Проблема с настройкой Arduino Due SPI на АЦП.
У меня возникли проблемы с настройкой Arduino Due SPI для AD7490 АЦП.
Вот как я подключил контакты:
- +3,3 В > 7490 контакт 22 Вин
- +3,3 В > 7490 Вref
- DUE CS (8) > 7490 контакт 20 SS — выбор подчиненного устройства)
- DUE SCK > 7490 контакт 16 (SCK — часы)
- DUE MOSI > 7490 контакт 19 (MOSI — вывод данных)
- Земля > 7490, контакт 24 (все линии заземления связаны между собой)
- ИЗ-ЗА MISO > 7490, контакт 15
Ниже приведен мой код, мне кажется, что я записываю в регистр правильные биты. Я думаю, что проблема заключается в том, чтобы записать время. Код представляет собой простую попытку прочитать один канал.
#include <SPI.h>
// Установка констант
const int adcChipSelectPin = 8; // устанавливаем контакт 8 в качестве выбора микросхемы для
ADC:
// Запускаем функцию настройки:
void setup() {
pinMode (adcChipSelectPin, OUTPUT);
// изначально устанавливаем высокий уровень ChipSelectPins:
digitalWrite(adcChipSelectPin, HIGH);
// инициализируем SPI:
SPI.begin();
SPI.setBitOrder(MSBFIRST); // Не строго необходимо, но просто так
sure.
SPI.setDataMode(SPI_MODE0); // Не строго необходимо, но просто так
sure.
Serial.begin(9600);
//Тактовая частота: главные часы/делитель
//84 МГц/64 = 1,3 МГц
SPI.setClockDivider(SPI_CLOCK_DIV64);
} // Завершение функции настройки.
// Функция запуска цикла:
void loop() {
float voltage[2];
for (int i = 0; i < 3; i++) {
voltage[i] = readAdc(0, 0);
}
}// Функция завершения цикла.
//Функция чтения АЦП, принимает канал для чтения.
float readAdc(int channel, int slave) {
float value;
if (slave == 0) {
noInterrupts(); // отключаем прерывания для подготовки к отправке адресных данных в
ADC.
digitalWrite(adcChipSelectPin, LOW); // устанавливаем низкий уровень на выводе Chip Select, чтобы
select the ADC.
byte FirstByte = 0b10000011;
byte SecondByte = 0b00110000;
SPI.transfer(FirstByte);
byte response1 = SPI.transfer(SecondByte);
byte response2 = SPI.transfer(0x00);
digitalWrite(adcChipSelectPin, HIGH); // поднимаем вывод Chip Select на высокий уровень
de-select the ADC.
interrupts(); // Включить прерывания.
Serial.println(response1);
Serial.println(response2);
}
Серийный.принтс последовательно выводит 255. По моему опыту, это означает, что SPI настроен неправильно.
Любые подсказки приветствуются.
@Flux, 👍1
Обсуждение1 ответ
Лучший ответ:
▲ 1
Для всех, кто столкнулся с той же проблемой: у меня это сработало:
// подключаем код библиотеки:
#include <SPI.h>
// Установка констант
const int adcChipSelectPin = 8; // устанавливаем вывод 8 в качестве выбора микросхемы для АЦП:
// Запускаем функцию настройки:
void setup() {
pinMode (adcChipSelectPin, OUTPUT);
// изначально устанавливаем высокий уровень ChipSelectPins:
digitalWrite(adcChipSelectPin, HIGH);
// инициализируем SPI:
SPI.begin();
SPI.setBitOrder(MSBFIRST); // Не обязательно, но на всякий случай.
SPI.setDataMode(SPI_MODE0); // Не обязательно, но на всякий случай.
Serial.begin(9600);
//Тактовая частота: главные часы/делитель
//84 МГц/64 = 1,3 МГц
SPI.setClockDivider(SPI_CLOCK_DIV64);
//Отправляем фиктивные значения при включении АЦП
//Удерживайте Din High в течение 16 тактов дважды
digitalWrite(adcChipSelectPin, LOW);
SPI.transfer(0xFF);
SPI.transfer(0xFF);
digitalWrite(adcChipSelectPin, HIGH);
digitalWrite(adcChipSelectPin, LOW);
SPI.transfer(0xFF);
SPI.transfer(0xFF);
digitalWrite(adcChipSelectPin, HIGH);
asm volatile("nop");
asm volatile("nop");
asm volatile("nop");
asm volatile("nop");
asm volatile("nop");
//Отправляем фиктивные значения, при следующем чтении должны быть правильные значения
digitalWrite(adcChipSelectPin, LOW);
byte FirstByte = 0x83;
byte SecondByte = 0x50;
byte response1 = SPI.transfer(FirstByte);
byte response2 = SPI.transfer(SecondByte);
digitalWrite(adcChipSelectPin, HIGH);
asm volatile("nop");
asm volatile("nop");
asm volatile("nop");
asm volatile("nop");
asm volatile("nop");
/////////////////////////////////////////////////// //////////////////////////////////
// Тихое время 50 нс?
asm volatile("nop");
asm volatile("nop");
asm volatile("nop");
asm volatile("nop");
asm volatile("nop");
} // Завершение функции настройки.
// Функция запуска цикла:
void loop() {
float voltage[2];
for (int i = 1; i < 17; i++) {
voltage[i] = readAdc(0, 1);
// Тихое время 50 нс?
asm volatile("nop");
asm volatile("nop");
asm volatile("nop");
asm volatile("nop");
asm volatile("nop");
}
} // Функция завершения цикла.
//Функция чтения АЦП, принимает канал для чтения.
float readAdc(int channel, int slave) {
float value;
if (slave == 0) {
byte FirstByte = 0x83;
byte SecondByte = 0x50;
FirstByte |= channel << 2;
noInterrupts(); // отключаем прерывания для подготовки к отправке адресных данных в АЦП.
digitalWrite(adcChipSelectPin, LOW); // переводим вывод Chip Select в низкий уровень, чтобы выбрать АЦП.
//Запись = 1
//ПОСЛЕДОВАТЕЛЬНОСТЬ = 0
// ДОБАВИТЬ3-ДОБАВИТЬ0 = 0000
//PM1 = PM0 = 1
//Тень = 0
//СЛАБЫЙ/Три = 1
//Диапазон = 0
//Кодирование = 1
//0b10000010 1010 0000
//лишние 4 нуля для заполнения
//Возможно, придется подождать 16 * (1/частота)
//16 * (1/1,3 МГц)
byte response1 = SPI.transfer(FirstByte);
byte response2 = SPI.transfer(SecondByte);
digitalWrite(adcChipSelectPin, HIGH);
interrupts(); // Включить прерывания.
//Serial.println(response1);
Serial.println(response2);
byte channel = (response1 >> 4);
//значение байта = (response1 << 4);
//байт digitalValue = (response1 << 4) | ответ2;
//Serial.println(digitalValue);
//Serial.println(канал);
byte digitalValue = 0x00;
float value = (float(digitalValue) * 3.3) / 4096.000; // Цифровое значение
converted to an analogue voltage using a VREF of 2.048V.
//Serial.print(канал);
//Serial.print("\t");
//Serial.println(значение);
}
}
,
@Flux
Смотрите также:
- Программирование ведомого SPI для Arduino
- Использование экрана SD-карты на Arduino Due
- Расширенная настройка АЦП на Due (SAM3X8E) для повышения точности
- Arduino/ESP8266 нет данных SPI, поступающих от MCP3008
- Как ускорить Due ADC
- Запуск передачи SPI с помощью прерывания в Arduino Due
- Создание синусоидальной волны с помощью ЦАП и ее обратная передача
- Взаимодействие ADS8319 с Arduino UNO
Я не думаю, что общение похоже на то, что вы здесь написали. Похоже, он отправляет данные следующим байтом. Попробуйте использовать
SPI.transfer(FirstByte); SPI.transfer(SecondByte); digitalWrite(adcChipSelectPin, ВЫСОКИЙ); asm Летучий («Нет»); asm Летучий («Нет»); asm Летучий («Нет»); asm Летучий («Нет»); asm Летучий («Нет»); digitalWrite (adcChipSelectPin, LOW); байтовый ответ1 = SPI.transfer(0x00); байтовый ответ2 = SPI.transfer(0x00);
. Пять «nop» предназначены для соблюдения времени «t_quiet» 50 морских миль, указанного в таблице данных., @frarugi87(конечно, в этой работе вы можете избежать использования записей 0x00 и объединить последовательные запросы; например, что-то вроде (используя только один SPI.transfer вместо двух и некоторый псевдокод)
SPI.transfer(чтение канала 0); CS высокий, nops, низкий CS; байт result_ch0 = SPI.transfer(чтение канала 1); высокий CS, ..[повторите столько раз, сколько вам нужно].., низкий CS; байт result_chN = SPI.transfer(0x00);
, @frarugi87Я попробовал ваше предложение и, к сожалению, все еще получаю тот же ответ, что и раньше. Я не уверен, в чем может быть проблема на данном этапе., @Flux
Вы пытались измерить значение напряжения на выводе MISO? стабильно 3,3 В или ниже? Может попробовать отключить его от АЦП и измерить напряжение на микроконтроллере MISO? Можете ли вы попробовать поставить резистор 10 кОм между MISO и GND?, @frarugi87
Напряжение на моем выводе MISO составляет всего около 0,8 В постоянного тока. Когда я отключился от АЦП, я увидел напряжение около 0,8 В., @Flux
Если вы думаете, что проблема может быть в моей плате, я только что подключил другой АЦП через SPI и получаю правильные значения., @Flux
можно ли попробовать использовать слабые подтягивания или тяги вниз? Я имею в виду, попробуйте установить резистор 10 кОм между MISO и +3,3 В, затем между MISO и GND. 0,8 В действительно странные, похоже на отсоединенный контакт... дважды проверьте пайку этого провода с АЦП., @frarugi87
От 3,3 В до MISO я получаю почти 3,3 В, а от MISO до GND — почти 0 В. Я пропустил этот АЦП через печь оплавления, поэтому, возможно, я допустил ошибку из-за перегрева. У меня появится еще одна плата, поэтому я постараюсь убедиться, что соблюдаю спецификации перекомпоновки таблицы. Кроме того, мой код выглядит нормально? Спасибо за помощь, кстати!, @Flux
Так откуда же взялось 0,8В? если вы монтировали их самостоятельно, то дважды проверьте пайку вывода DOUT на АЦП; возможно он не правильно припаян. Иногда простое нагревание паяльником (и/или добавление припоя) исправляет пайку., @frarugi87
Я только что подключил новый АЦП к своей печатной плате и теперь получаю 3,3 В, хотя на выходе записи все еще нет., @Flux
3,3 В кажется разумным. Каков ваш результат? Можете ли вы подключить осциллограф во время передачи, чтобы проверить, действительно ли он что-то передает?, @frarugi87
Эй, фраруги, я понял. Огромное вам спасибо за указатели!, @Flux