Не удается заставить мой ЦАП (PT8211) работать правильно, используя PIC32MX uc и SPI - PullRequest
0 голосов
/ 07 июня 2019

Я просто пытаюсь научиться использовать внешний АЦП и ЦАП (PT8211) с моим PIC32MX534f06h.

До сих пор мой код просто собирал сигнал с моего АЦП каждый раз, когда срабатывает прерывание по таймеру, а затем отправлял этот же сигнал в ЦАП.Компоненты прерывания и АЦП работают нормально и были протестированы независимо, но напряжения, которые выводит мой ЦАП, не имеют для меня большого значения и остаются на уровне 2,5 В (он питается от 0 до 5 В).

IЯ пытался подать на ЦАП различные значения в диапазоне от 0 до 65534 (16-битный ЦАП, так что я предполагаю, что это должен быть ожидаемый диапазон значений для подачи на него, верно?), напряжение остается на уровне 2,5 В.

Я попытался изменить конфигурацию SPI, используя разные SPI (3 и 4) и ЦАП (у меня один припаян к моей печатной плате, припаян к SPI3 и один макет, связанный с SPI4 в случае, если одинспаянный на моей плате был неисправен).Я удостоверился, что линия выбора чипа работает как ожидалось.Я не мог видеть данные и часы, которые были переданы, так как у меня еще нет объема.

У меня немного не в порядке.

Выбор микросхемы и настройки конфигурации SPI


signed short adc_value;
signed short DAC_output_value;
int Empty_SPI3_buffer;

#define Chip_Select_DAC_Set() {LATDSET=_LATE_LATE0_MASK;}
#define Chip_Select_DAC_Clr() {LATDCLR=_LATE_LATE0_MASK;}

#define SPI4_CONF 0b1000010100100000 // SPI on, 16-bit master,CKE=1,CKP=0   
#define SPI4_BAUD 100 // clock divider

Функция выхода ЦАП

//output to external DAC
void DAC_Output(signed int valueDAC) {
    INTDisableInterrupts();
    Chip_Select_DAC_Clr();
    while(!SPI4STATbits.SPITBE);    // wait for TX buffer to empty 
    SPI4BUF=valueDAC;               // write byte to TX buffer 
    while(!SPI4STATbits.SPIRBF);    // wait for RX buffer to fill 
    Empty_SPI3_buffer=SPI4BUF;      // read RX buffer 
    Chip_Select_DAC_Set();
    INTEnableInterrupts();
}

ISRвыборка данных, вызванная таймером1.Это отлично работает.ADC_input вводит данные в глобальную переменную adc_value (12 бит, со знаком)

//ISR to sample data 
void __ISR( _TIMER_1_VECTOR, IPL7SRS) Test_data_sampling_in( void)
{
    IFS0bits.T1IF = 0;
    ADC_Input();
    //rescale the signed 12 bit audio values to unsigned 16 bits wide values
    DAC_output_value = adc_value + 2048;  //first unsign the signed 12 bit values (between 0 - 4096, center 2048)
    DAC_output_value = DAC_output_value *16;  // the scale between 12 and 16 bits is actually 16=65536/4096
    DAC_Output(DAC_output_value);
 }

основная функция с SPI, IO, конфигурация таймера

void main() {

    SPI4CON = SPI4_CONF; 
    SPI4BRG = SPI4_BAUD;

    TRISE = 0b00100000;
    TRISD = 0b000000110100;
    TRISG = 0b0010000000;

    LATD = 0x0;
    SYSTEMConfigPerformance(80000000L);  //
    INTCONSET = _INTCON_MVEC_MASK;    /* Set the interrupt controller for multi-vector mode */

//  
    T1CONbits.TON = 0;              /* turn off Timer 1 */
    T1CONbits.TCKPS = 0b11;            /* pre-scale = 1:1 (T1CLKIN = 80MHz (?) ) */
    PR1 = 1816;                    /* T1 period ~ ?  */
    TMR1 = 0;                       /* clear Timer 1 counter */
//    
    IPC1bits.T1IP = 7;              /* Set Timer 1 interrupt priority to 7 */
    IFS0bits.T1IF = 0;              /* Reset the Timer 1 interrupt flag */
    IEC0bits.T1IE = 1;               /* Enable interrupts from Timer 1 */
    T1CONbits.TON = 1;              /* Enable Timer 1 peripheral */

    INTEnableInterrupts();

    while (1){ 



  }
}

Я ожидаю увидеть напряжение навыходной сигнал моего ЦАП для имитации тех, которые я положил на вход моего АЦП, вместо этого выходное значение ЦАП всегда является постоянным, независимо от того, что я ввожу в АЦП

Чего мне не хватает?Кроме того, при включении SPI, я все еще должен вручную управлять конфигурацией IO выводов SDI SDO SCK, используя TRIS, или об этом автоматически заботятся?

Ответы [ 2 ]

0 голосов
/ 09 июня 2019

Прежде всего, большое спасибо за ваш комментарий. Очень помогает знать, что я не смотрю на передачу SPI, и это объясняет, почему она не работает.

Несколько размышлений об этом

  • Я погуглил бит бит (стук?), И, похоже, он сильно загружает процессор, чего я бы определенно постарался избежать
  • Я видел (успешный) проект (в MikroC), где кто-то передает данные из того же PIC в тот же ЦАП, используя SPI, без каких-либо проблем, по-видимому, так что, я думаю, это ДОЛЖНО работать, как-нибудь? Может, он преобразует данные, чтобы они работали? вот код, который он использует, я не уверен, что происходит с битовым переключателем F15, я думал, что это было сделано для решения проблемы сдвига LSB. Вот фрагмент (работающего) кода MikroC, о котором я говорю

     valueDAC = valueDAC + 32768;
     valueDAC.F15 =~ valueDAC.F15;
     Chip_Select_DAC = 0;
     SPI3_Write(valueDAC);
     Chip_Select_DAC = 1;

Насколько я понимаю, два самых больших различия между SPI и I2S заключаются в том, что SPI отправляет «пачки» данных, а I2S непрерывно отправляет данные. Другое отличие состоит в том, что данные, отправленные после состояния изменения слова, представляют собой младший бит последнего слова. Поэтому я подумал, что мой SPI запускается таймером, который всегда одинаков, поэтому, даже если данные не отправляются непрерывно, звуковая волна будет немного более «псевдонимной», и если она будет запускаться достаточно регулярно (скажем, на частоте 44 МГц), она не должна так сильно отличаться от отправки данных I2S на той же частоте, верно? Если это так, и я правильно понимаю, «единственной» проблемой остается управление проблемой размещения LSB-next-word-MSB, но я подумал, что LSB практически ничтожен для 16-битных значений, так что если бы я мог просто сдвинуть бит значение справа, а затем просто установите значение LSB в 0 или 1, ошибка будет мала, и формат будет правильным.

Звучит так, будто у меня есть действительный 'Mc-Gyver-I2S-from-my-SPI' или я забыл что-то важное?

Я пытался реализовать его, но пока безуспешно, но мне нужно проверить конфигурацию SPI, так как я не уверен, что она настроена правильно

Вот код на данный момент

SPI config



       #define Chip_Select_DAC_Set() {LATDSET=_LATE_LATE0_MASK;}
        #define Chip_Select_DAC_Clr() {LATDCLR=_LATE_LATE0_MASK;}

        #define SPI4_CONF 0b1000010100100000
        #define SPI4_BAUD 20 

Функция вывода DAaC



      //output audio to external DAC
        void DAC_Output(signed int valueDAC) {
        INTDisableInterrupts();
        valueDAC = valueDAC  >> 1;  // put the MSB of ValueDAC 1 bit to the right     (becase the MSB of what is transmitted will be seen by the DAC as the LSB of the     last value, after a word select change)
        //Left channel
        Chip_Select_DAC_Set(); // Select left channel
        SPI4BUF=valueDAC; 
        while(!SPI4STATbits.SPITBE);    // wait for TX buffer to empty 
        SPI4BUF=valueDAC; // write 16-bits word to TX buffer 
        while(!SPI4STATbits.SPIRBF);    // wait for RX buffer to fill 
        Empty_SPI3_buffer=SPI4BUF;      // read RX buffer (don't know why we need to do     this here, but we do) 
        //SPI3_Write(valueDAC); MikroC option
        // Right channel
        Chip_Select_DAC_Clr(); 
        SPI4BUF=valueDAC; 
        while(!SPI4STATbits.SPITBE);    // wait for TX buffer to empty 
        SPI4BUF=valueDAC; // write 16-bits word to TX buffer 
        while(!SPI4STATbits.SPIRBF);    // wait for RX buffer to fill 
        Empty_SPI3_buffer=SPI4BUF;  
        INTEnableInterrupts();
        }

Данные, которые я отправляю сюда, подписаны, диапазон 16 бит, я думаю, вы сказали, что с этим ЦАП все в порядке, верно?

Или, может быть, я мог бы использовать подставленный SPI? в этом режиме часы работают непрерывно, но мне все равно придется решать проблему смещения LSB MSB.

Я немного растерялся здесь, поэтому любая помощь будет крутой

0 голосов
/ 08 июня 2019

Прежде всего, я согласен, что документация, которую я впервые нашел для PT8211, довольно скудная.Я нашел расширенную документацию здесь .Ваш ЦАП (PT8211) на самом деле является устройством I2S , а не SPI.WS - это не выбор чипа, а выбор слова (левый / правый канал).В I2S, если вы устанавливаете WS в 0, это означает левый канал.Однако, похоже, что в расширенной таблице данных я обнаружил, что WS 0 на самом деле является правильным каналом (см. Рисунок).

Выбранная вами PIC, похоже, не имеет аппаратного обеспечения I2S, так что вам, возможно, придется ее немного разбить.Тем не менее, есть много информации о I2S, см. Спецификация шины I2S .

Есть некоторые небольшие различия с SPI и I2C.Обратите внимание, что первый бит, когда WS переходит от высокого к низкому, это младший бит правого канала.и когда WS переходит от низкого к высокому, это не младший бит левого канала.Обратите внимание, что выходной сигнал должен быть между 0,4 В и 2,4 В (стандарт I2S), а не между 0 и 5 В.(Макс. 2.5 В, это то, что вы видели).

I2S

I2S

По сути, я бы попробовал этосначала с правильным протоколом с алгоритмом битовой синхронизации с непрерывным переключением между левым / правым каналом.

...