DAC CS8416 + AD1852 — 24bit 192kHz (Arduino)

Микросхема AD1852 является однокристальной законченной 18/20/24-разрядной звуковоспроизводящей стерео системой. Она состоит из мультибитного сигма-дельта преобразователя, цифрового интерполяционного фильтра и аналоговой дифференциальной выходной схемы. Кроме этого система включает в себя стерео аттенюатор и устройство отключения звука, которые программируются через последовательный порт SPI. Микросхема AD1852 полностью совместима со всеми известными форматами DVD с частотами дискретизации 192 кГц и 96 кГц, а также с 24-разрядными данными. Для совместимости с устаревшими форматами система также поддерживает цифровую частотную коррекцию 50/15 мкс, использовавшуюся в компакт-дисках «redbook», и компенсацию предыскажений для частот дискретизации 32 кГц и 48 кГц.

Входной цифровой сигнал для внешнего ЦАПа имеет формат S/PDIF (цифровой аудио интерфейс разработанный фирмами SONY/PHILIPS, предназначен для передачи цифрового сигнала между аудио устройствами), ЦАП AD1852 не поддерживает такой формат, для преобразования S/PDIF необходим ресивер на CS8416 который преобразует S/PDIF в цифровой сигнал в формат I2S. С выхода ЦАП звуковой сигнал поступает на фильтр-сумматор собранный на ОУ NE5532.

Для нормальной работы ресивер и ЦАП должный иметь одинаковый формат передачи цифровых данных, в данном случае это I2S 24 бит с частотой сэмплирования 192 кГц.

Основные характеристики AD1852:

  • Напряжение питания +5 В
  • Поддержка 24 бит с частотой дискретизации 192 кГц
  • Отношение сигнал / шум (от 20 Гц до 20 кГц) … 114 дБ
  • Динамический диапазон (от 20 Гц до 20 кГц, вход -60 дБ) … 114 дБ
  • Общие гармонические искажения + шум (стерео) … −102 dB 0.00079 %
  • Управление SPI

Внешний ЦАП состоит из нескольких компонентов:

  • Ресивер на CS8416
  • ЦАП на AD1852
  • ФНЧ на NE5532
  • Источник питания
  • Плата Arduino Nano
  • Индикатор TM1637 (семисегментный, 4 разряда)
  • Энкодер + кнопка для управления режимами внешнего ЦАПа

Выше показана схема ресивера на CS8416, он имеет 3 активных входа, но можно использовать все 4-е доступные входы. Коммутация входами осуществляется при помощи пинов RSEL1 и RSEL0 микросхемы ресивера , при этом лог. 1 подается с питания VL (+5 В), а логический ноль с DGND.

INPUT RSEL0 RSEL1
RXP0 0 0
RXP1 1 0
RXP2 0 1
RXP3 1 1

Ресивер практически работает независимо от Arduino, контроллер необходим только для работы коммутатора входов. В схеме присутствует индикатор режима работы светодиод D1, при подключении коаксиального кабеля с источником цифрового сигнала светодиод гаснет, при отключении кабеля загорается.

Выше показана схема ЦАП на AD1852, так как управление ЦАП осуществляется через шину SPI (регулировка громкости, mute), то убрано много внешних компонентов предназначенных для конфигурирования режима работы ЦАП. Управление AD1852 по шине SPI производится при помощи трех 16-и битных регистров, первый регистр это регистр конфигурации, в нем определяются все основные параметры с которыми будет работать AD1852. Остальные два регистра задают уровень громкости для правого и левого канала. Регулировка громкости имеет линейную зависимость.

Адрес регистров задается в двух младших байтах:

Control Register Functions

Схема ФНЧ

Схема стабилизаторов источника питания

Регулировка громкости осуществляется при помощи энкдера  ky-040

При повороте ручки энкодера меняется громкость (127 шагов регулировки), при нажатии кнопки энкодера активируется режим MUTE. Так же добавлена одна кнопка, при нажатии на которую происходит переключение входа ресивера.

Схема подключения платы Arduino

#include <SPI.h>
#include <EEPROM.h>
#include <MsTimer2.h>                    // http://rcl-radio.ru/wp-content/uploads/2018/11/MsTimer2.zip
#include <Encoder.h>                     // http://rcl-radio.ru/wp-content/uploads/2019/05/Encoder.zip
#include <STM32_TM1637.h>                // http://rcl-radio.ru/wp-content/uploads/2020/02/STM32_TM1637_V1_3.zip
 Encoder myEnc(8, 9);//CLK, DT
 STM32_TM1637 tm(3,2);// CLK, DIO
 
//  AD1852 SPI
// SS    10 // CLATCH
// MOSI  11 // CDATA
// SCK   13 // CCLK
 
unsigned long times,oldPosition  = -999,newPosition;
int w,vol,mute,code_mute,in;
 
void setup(){
 Serial.begin(9600);tm.brig(7); // ЯРКОСТЬ 0...7
 MsTimer2::set(1, to_Timer);MsTimer2::start();
 pinMode(A0,OUTPUT);  // RSEL1 CS8416
 pinMode(A1,OUTPUT);  // RSEL0 CS8416
 pinMode(7,INPUT); // кнопка SW энкодера
 pinMode(6,INPUT_PULLUP); // кнопка IN
 vol = EEPROM.read(0);in = EEPROM.read(1);
 switch(in){
 case 0: digitalWrite(A0, LOW);digitalWrite(A1, LOW);tm.print_float(1,0 ,0b00000100,0b01010100,0,0);break;// px0 
 case 1: digitalWrite(A0, LOW);digitalWrite(A1, HIGH);tm.print_float(2,0 ,0b00000100,0b01010100,0,0);break;// px1
 case 2: digitalWrite(A0, HIGH);digitalWrite(A1, LOW);tm.print_float(3,0 ,0b00000100,0b01010100,0,0);break;// px2
 }
 }// setup
 
void loop(){
   if(digitalRead(7)==LOW&&mute==0){mute=1;code_mute = 0b1000000;tm.print_float(vol,0 ,0b01000000,0b01000000,0b01000000,0b01000000);delay(200);}
   if(digitalRead(7)==LOW&&mute==1){mute=0;code_mute = 0;tm.print_float(vol,0 ,0,0,0,0);delay(200);}
 
   if(digitalRead(6)==LOW){in++;if(in>2){in=0;}times=millis();w=1;
 switch(in){
 case 0: digitalWrite(A0, LOW);digitalWrite(A1, LOW);tm.print_float(1,0 ,0b00000100,0b01010100,0,0);break;// px0 
 case 1: digitalWrite(A0, LOW);digitalWrite(A1, HIGH);tm.print_float(2,0 ,0b00000100,0b01010100,0,0);break;// px1
 case 2: digitalWrite(A0, HIGH);digitalWrite(A1, LOW);tm.print_float(3,0 ,0b00000100,0b01010100,0,0);break;// px2
 }
 delay(2000);tm.print_float(vol,0 ,0,0,0,0);}
 
   if (newPosition != oldPosition){oldPosition = newPosition;
     vol=vol+newPosition;myEnc.write(0);newPosition=0;w=1;times=millis();
     if(vol>127){vol=127;}if(vol<0){vol=0;}
     Serial.println(vol);
     if(mute==0){tm.print_float(vol,0 ,0,0,0,0);}
     mute=0;code_mute = 0;
     }
 
   SPI.begin();
   WriteAD1852(0b100010010001+code_mute);  // register control 
   WriteAD1852(0b00+(vol<<9)); // register volume left
   WriteAD1852(0b10+(vol<<9)); // register volume right 
   delay(10);
 
   if(millis()-times>5000 && w==1){w=0;EEPROM.write(0,vol);EEPROM.write(1,in);}
  }// loop
 
 void WriteAD1852(uint16_t Data){
  SPI.beginTransaction(SPISettings(SPI_CLOCK_DIV16, MSBFIRST, SPI_MODE3));
  digitalWrite(SS, HIGH);
  delayMicroseconds(1);
  SPI.transfer16(Data);
  digitalWrite(SS, LOW);
  SPI.endTransaction();
}  
 
void to_Timer(){newPosition = myEnc.read()/4;}
MUTE Выбор входа

 

Добавить комментарий

Войти с помощью: