Проблема с настройкой 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 настроен неправильно.

Любые подсказки приветствуются.

, 👍1

Обсуждение

Я не думаю, что общение похоже на то, что вы здесь написали. Похоже, он отправляет данные следующим байтом. Попробуйте использовать 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


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(значение);
    }
}
,