Микросхема 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 | Выбор входа |