| Ваш IP: 3.238.4.24 | Online(45) - гости: 28, боты: 17 | Загрузка сервера: 0.94 ::::::::::::


DAC CS8416 + CS4398 (Arduino)

ЦАП — цифро-аналоговый преобразователь — это устройство, которое преобразует информацию из цифрового вида  в аналоговые сигналы, при этом максимально точно и без искажений.

Собрать внешний ЦАП на компонентах предложных в статье не сложно, он содержит несколько недорогих компонентов и в настройке практически не нуждается. Дополнительно во внешнем ЦАПе используется плата Arduino Nano, энкодер и дисплей LCD1602(I2C). Фактически ЦАП может работать и без Arduino, но суть проекта была в получении к дополнительных функциям ЦАП на CS4398, таким как управление громкостью и функции MUTE.

Внешний ЦАП состоит из 5-х основных модулей:

  • приемник S/PDIF на CS8416
  • ЦАП на CS4398
  • фильтр-сумматор на NE5532
  • плата Arduino Nano
  • блок питания

S/PDIF (Sony/Philips Digital Interface) – распространенный и стандартизированный интерфейс, предназначенный для передачи цифрового звука между доступными компонентами, звуковыми картами, ресиверами и аудиоаппаратурой.

I2S — стандарт интерфейса электрической последовательной шины, использующийся для соединения цифровых аудиоустройств. Применяется для передачи PCM-аудиоданных между интегральными схемами в электронном устройстве. Шина I2S передает по разным линиям сигналы синхронизации и сигналы данных, что приводит к снижению фазового дрожания, типичного для систем связи, восстанавливающих сигналы синхронизации из целого потока.

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

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

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

  • отношение сигнал/шум 120 дБ
  • динамический диапазон 120 дБ
  • уровень гармонических искажений -107 дБ
  • взаимное проникновение каналов 120 дБ
  • входной формат: PCM I2S, RJ, LJ от 16 бит 32 кГц до 24 бит 192 кГц

В моем случае внешний ЦАП имеет упрощенное питание, для уменьшения шумов и искажений желательно применять рекомендованную схему питания (см.ниже).

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

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

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

Для питания схемы ресивера используется следующая схема:

Основное напряжение +5 В подается с платы Arduino, которое является напряжением VL, для питания VD и VA используются два стабилизатора напряжения 78L33 (3.3 В).

Выше показана схема ЦАП, для его питания я использую напряжение 5 В подаваемое с платы Arduino.

Для питания фильтр-сумматора необходим отдельный двух полярный источник +/-12 В. Для настройки уровня выходного сигнала можно изменить номиналы резисторов R15 R22.

Ниже показана схема рекомендованного источника питания.

Для питания внешнего ЦАПа рекомендуется использовать три независимых источника питания, который состоит из одного трансформатора с тремя независимыми вторичными обмотками,  одна из которых имеет отвод от середины для двух полярного источника питания. Каждый источник питания имеет свой диодный мост. При этом аналоговая и цифровая земля объединяются через дроссель. Дополнительно как можно ближе к микросхемам по цепи питания устанавливаются фильтрующие конденсаторы 0,1 и 22 мкФ. Подключение к плате Arduino осуществляется тремя проводами (I2C) SDA SCL и GND к DGND цепи питания ЦАП.

Как было отмечено ранее, управление ЦАП CS4398 при помощи Arduino позволяет управлять громкостью и режимом MUTE. Регулировка громкостью и режимом MUTE осуществляется при помощи энкодера (KY-040), информация выводится на дисплей LCD1602 работающего на шине I2C. Регулировка громкости содержит 130 ступеней (по 0,5 дБ), при нажатии кнопки энкодера можно включить или выключить режим MUTE.

 

#include <Wire.h>
#include <EEPROM.h>
#include <MsTimer2.h> // https://rcl-radio.ru/wp-content/uploads/2018/11/MsTimer2.zip
#include <Encoder.h>  // https://rcl-radio.ru/wp-content/uploads/2019/05/Encoder.zip
#include <LiquidCrystal_I2C.h> //Библиотека -  http://forum.rcl-radio.ru/misc.php?action=pan_download&item=45&download=1
 LiquidCrystal_I2C lcd(0x27,16,2);  // Устанавливаем дисплей 
 Encoder myEnc(9, 8);//CLK, DT
      byte v1[8] = {7,7,7,7,7,7,7,7};
      byte v2[8] = {7,7,0, 0, 0, 0, 0, 0};      
      byte v3[8] = { 0, 0, 0, 0, 0,0,31,31};
      byte v4[8] = {31,31, 0, 0, 0, 0,31,31};
      byte v5[8] = { 28, 28, 0, 0, 0, 0, 28, 28};//
      byte v6[8] = {28,28,28,28,28,28,28,28};
      byte v7[8] = { 0, 0, 0, 0, 0, 0,7,7};
      byte v8[8] = { 31, 31,0,0,0,0,0, 0};
      int a[3];
      byte i,d1,d2,d3,d4,d5,d6,e1,e2,e3;
 unsigned long time,oldPosition  = -999,newPosition;
 int vol,vol_d;
 bool w,mute;

void setup() {
 Wire.begin();
 lcd.init();lcd.backlight();
 pinMode(10,INPUT);
 lcd.createChar(1, v1);lcd.createChar(2, v2);lcd.createChar(3, v3);
 lcd.createChar(4, v4);lcd.createChar(5, v5);lcd.createChar(6, v6);
 lcd.createChar(7, v7);lcd.createChar(8, v8);
 Serial.begin(9600);
 lcd.setCursor(0,0);lcd.print("     CS4398     ");
 lcd.setCursor(0,1);lcd.print("     CS8416     ");
 MsTimer2::set(1, to_Timer);MsTimer2::start();
 delay(1000);
 vol = EEPROM.read(0);
 wireWrite(0x4C, 0x02, 0b00011010);// I2S 24 bit / 48 kHz / 100...200 kHz
 wireWrite(0x4C, 0x03, 0b00001001);// default
 wireWrite(0x4C, 0x04, 0b11000000);// default
 wireWrite(0x4C, 0x05, vol);
 wireWrite(0x4C, 0x06, vol);
 wireWrite(0x4C, 0x07, 0b10110000);// default
 wireWrite(0x4C, 0x08, 0b01000000);// default
 wireWrite(0x4C, 0x09, 0b00001000);// default
 Serial.print("Chip ID 0");
 Serial.println(wireRead(0x4C, 0x01),BIN);
 lcd.clear();
}

void loop() {
 if(digitalRead(10)==LOW && mute==0){mute=1;wireWrite(0x4C, 0x04, 0b11011000);delay(300);} 
 if(digitalRead(10)==LOW && mute==1){mute=0;wireWrite(0x4C, 0x04, 0b11000000);delay(300);} 
 if(mute==1){lcd.setCursor(0,1);lcd.print("MUTE");}else{lcd.setCursor(0,1);lcd.print("192k");}
 
 if (newPosition != oldPosition){oldPosition = newPosition;
     vol=vol+newPosition;myEnc.write(0);newPosition=0;time=millis();w=1;
      if(vol<0){vol=0;}if(vol>130){vol=130;}
      wireWrite(0x4C, 0x05, vol);
      wireWrite(0x4C, 0x06, vol);
      lcd.setCursor(0,0);lcd.print("VOLUME ");
     }
      
     vol_d=130-vol;
     a[0]=vol_d/100;
     a[1]=vol_d/10%10;
     a[2]=vol_d%10;
      for(i=0;i<3;i++){
      switch(i){
        case 0: e1=7,e2=8,e3=9;break;
        case 1: e1=10,e2=11,e3=12;break;
        case 2: e1=13,e2=14,e3=15;break;
        }
      switch(a[i]){
        case 0: d1=1,d2=8,d3=6,d4=1,d5=3,d6=6;break;
        case 1: d1=32,d2=2,d3=6,d4=32,d5=32,d6=6;break;
        case 2: d1=2,d2=8,d3=6,d4=1,d5=4,d6=5;break;
        case 3: d1=2,d2=4,d3=6,d4=7,d5=3,d6=6;break;
        case 4: d1=1,d2=3,d3=6,d4=32,d5=32,d6=6;break;
        case 5: d1=1,d2=4,d3=5,d4=7,d5=3,d6=6;break;
        case 6: d1=1,d2=4,d3=5,d4=1,d5=3,d6=6;break;
        case 7: d1=1,d2=8,d3=6,d4=32,d5=32,d6=6;break;
        case 8: d1=1,d2=4,d3=6,d4=1,d5=3,d6=6;break;
        case 9: d1=1,d2=4,d3=6,d4=7,d5=3,d6=6;break;
    }
     
      lcd.setCursor(e1,0);lcd.write((uint8_t)d1);lcd.setCursor(e2,0);lcd.write((uint8_t)d2);lcd.setCursor(e3,0);lcd.write((uint8_t)d3);
      lcd.setCursor(e1,1);lcd.write((uint8_t)d4);lcd.setCursor(e2,1);lcd.write((uint8_t)d5);lcd.setCursor(e3,1);lcd.write((uint8_t)d6);
 }

 delay(20);if(millis()-time>5000 && w==1){w=0;EEPROM.write(0,vol);}
 }// loop
 

void wireWrite(byte addr, byte reg, byte data){
  Wire.beginTransmission(addr);
  Wire.write (reg);
  Wire.write (data);
  Wire.endTransmission();
  }

byte wireRead(int addr, int reg){
  Wire.beginTransmission(addr);
  Wire.write (reg);
  Wire.endTransmission();
  Wire.requestFrom(addr,1);
  while(Wire.available()<1);
  byte value = Wire.read();
  return value;
  }  

void to_Timer(){newPosition = myEnc.read()/4;}  

Если открыть монитор порта Вы увидите ID номер CS4398:

This register is Read-Only. Bits 7 through 3 are the part number ID, which is 01110b (14h), and the remaining Bits (2 through 0) are for the chip revision (Rev. A = 000, Rev. B = 001, …)

Форум — http://forum.rcl-radio.ru/viewtopic.php?id=202


Селектор входов

Изменив немного схему, добавив два резистора 4,7 кОм к пинам TSEL1 и TSEL0 CS8416, можно сделать селектор входов. Коммутация входов осуществляется при помощи Arduino (выходы A0 A1). Добавлена одна кнопка для переключения входов которая подключена к пину D2 Arduino (кнопка при нажатии замыкается на GND).

Уровень громкости и номер выбранного входа сохраняется в энергонезависимой памяти.

#include <Wire.h>
#include <EEPROM.h>
#include <MsTimer2.h> // https://rcl-radio.ru/wp-content/uploads/2018/11/MsTimer2.zip
#include <Encoder.h>  // https://rcl-radio.ru/wp-content/uploads/2019/05/Encoder.zip
#include <LiquidCrystal_I2C.h> //Библиотека -  http://forum.rcl-radio.ru/misc.php?action=pan_download&item=45&download=1
 LiquidCrystal_I2C lcd(0x27,16,2);  // Устанавливаем дисплей 
 Encoder myEnc(9, 8);//CLK, DT
      byte v1[8] = {7,7,7,7,7,7,7,7};
      byte v2[8] = {7,7,0, 0, 0, 0, 0, 0};      
      byte v3[8] = { 0, 0, 0, 0, 0,0,31,31};
      byte v4[8] = {31,31, 0, 0, 0, 0,31,31};
      byte v5[8] = { 28, 28, 0, 0, 0, 0, 28, 28};//
      byte v6[8] = {28,28,28,28,28,28,28,28};
      byte v7[8] = { 0, 0, 0, 0, 0, 0,7,7};
      byte v8[8] = { 31, 31,0,0,0,0,0, 0};
      int a[3];
      byte i,d1,d2,d3,d4,d5,d6,e1,e2,e3;
 unsigned long time,oldPosition  = -999,newPosition;
 int vol,vol_d,in;
 bool w,mute;

void setup() {
 Wire.begin();
 lcd.init();lcd.backlight();
 pinMode(10,INPUT);   // кнопка энкодера
 pinMode(A0,OUTPUT);  // RSEL1
 pinMode(A1,OUTPUT);  // RSEL0
 pinMode(2,INPUT_PULLUP); // кнопка IN
 lcd.createChar(1, v1);lcd.createChar(2, v2);lcd.createChar(3, v3);
 lcd.createChar(4, v4);lcd.createChar(5, v5);lcd.createChar(6, v6);
 lcd.createChar(7, v7);lcd.createChar(8, v8);
 Serial.begin(9600);
 lcd.setCursor(0,0);lcd.print("     CS4398     ");
 lcd.setCursor(0,1);lcd.print("     CS8416     ");
 MsTimer2::set(1, to_Timer);MsTimer2::start();
 delay(1000);
 vol = EEPROM.read(0);
 in = EEPROM.read(1);
 wireWrite(0x4C, 0x02, 0b00011010);// I2S 24 bit / 48 kHz / 100...200 kHz
 wireWrite(0x4C, 0x03, 0b00001001);// default
 wireWrite(0x4C, 0x04, 0b11100000);// default
 wireWrite(0x4C, 0x05, vol);
 wireWrite(0x4C, 0x06, vol);
 wireWrite(0x4C, 0x07, 0b10110000);// default
 wireWrite(0x4C, 0x08, 0b01000000);// default
 wireWrite(0x4C, 0x09, 0b00001000);// default
 Serial.print("Chip ID 0");
 Serial.println(wireRead(0x4C, 0x01),BIN);
 lcd.clear();
 switch(in){
 case 0: digitalWrite(A0, LOW);digitalWrite(A1, LOW);lcd.print("COAX 1");break;// px0 
 case 1: digitalWrite(A0, LOW);digitalWrite(A1, HIGH);lcd.print("COAX 2");break;// px1
 case 2: digitalWrite(A0, HIGH);digitalWrite(A1, LOW);lcd.print("COAX 3");break;// px2
 }
}

void loop() {
 if(digitalRead(2)==LOW){in++;if(in>2){in=0;}lcd.clear();time=millis();w=1;
 lcd.setCursor(5,0);lcd.print("INPUT");lcd.setCursor(05,1);
 switch(in){
 case 0: digitalWrite(A0, LOW);digitalWrite(A1, LOW);lcd.print("COAX 1");break;// px0 
 case 1: digitalWrite(A0, LOW);digitalWrite(A1, HIGH);lcd.print("COAX 2");break;// px1
 case 2: digitalWrite(A0, HIGH);digitalWrite(A1, LOW);lcd.print("COAX 3");break;// px2
 }delay(2000);lcd.clear();}
 
  
 if(digitalRead(10)==LOW && mute==0){mute=1;wireWrite(0x4C, 0x04, 0b11011000);delay(300);} 
 if(digitalRead(10)==LOW && mute==1){mute=0;wireWrite(0x4C, 0x04, 0b11000000);delay(300);} 
 if(mute==1){lcd.setCursor(0,1);lcd.print("MUTE  ");}
 else{lcd.setCursor(0,1);lcd.print("COAX ");lcd.print(in+1);
 }
 
 if (newPosition != oldPosition){oldPosition = newPosition;
     vol=vol+newPosition;myEnc.write(0);newPosition=0;time=millis();w=1;
      if(vol<0){vol=0;}if(vol>130){vol=130;}
      wireWrite(0x4C, 0x05, vol);
      wireWrite(0x4C, 0x06, vol);}
    lcd.setCursor(0,0);lcd.print("VOLUME ");
     vol_d=130-vol;
     a[0]=vol_d/100;
     a[1]=vol_d/10%10;
     a[2]=vol_d%10;
      for(i=0;i<3;i++){
      switch(i){
        case 0: e1=7,e2=8,e3=9;break;
        case 1: e1=10,e2=11,e3=12;break;
        case 2: e1=13,e2=14,e3=15;break;
        }
      switch(a[i]){
        case 0: d1=1,d2=8,d3=6,d4=1,d5=3,d6=6;break;
        case 1: d1=32,d2=2,d3=6,d4=32,d5=32,d6=6;break;
        case 2: d1=2,d2=8,d3=6,d4=1,d5=4,d6=5;break;
        case 3: d1=2,d2=4,d3=6,d4=7,d5=3,d6=6;break;
        case 4: d1=1,d2=3,d3=6,d4=32,d5=32,d6=6;break;
        case 5: d1=1,d2=4,d3=5,d4=7,d5=3,d6=6;break;
        case 6: d1=1,d2=4,d3=5,d4=1,d5=3,d6=6;break;
        case 7: d1=1,d2=8,d3=6,d4=32,d5=32,d6=6;break;
        case 8: d1=1,d2=4,d3=6,d4=1,d5=3,d6=6;break;
        case 9: d1=1,d2=4,d3=6,d4=7,d5=3,d6=6;break;
    }
     
      lcd.setCursor(e1,0);lcd.write((uint8_t)d1);lcd.setCursor(e2,0);lcd.write((uint8_t)d2);lcd.setCursor(e3,0);lcd.write((uint8_t)d3);
      lcd.setCursor(e1,1);lcd.write((uint8_t)d4);lcd.setCursor(e2,1);lcd.write((uint8_t)d5);lcd.setCursor(e3,1);lcd.write((uint8_t)d6);
 }

 delay(20);if(millis()-time>5000 && w==1){w=0;EEPROM.write(0,vol);EEPROM.write(1,in);}
 }// loop
 

void wireWrite(byte addr, byte reg, byte data){
  Wire.beginTransmission(addr);
  Wire.write (reg);
  Wire.write (data);
  Wire.endTransmission();
  }

byte wireRead(int addr, int reg){
  Wire.beginTransmission(addr);
  Wire.write (reg);
  Wire.endTransmission();
  Wire.requestFrom(addr,1);
  while(Wire.available()<1);
  byte value = Wire.read();
  return value;
  }  

void to_Timer(){newPosition = myEnc.read()/4;}  

Добавлен баланс, изменено подключение

 

#include <Wire.h>
#include <EEPROM.h>
#include <MsTimer2.h> // https://rcl-radio.ru/wp-content/uploads/2018/11/MsTimer2.zip
#include <Encoder.h>  // https://rcl-radio.ru/wp-content/uploads/2019/05/Encoder.zip
#include <LiquidCrystal_I2C.h> //Библиотека -  http://forum.rcl-radio.ru/misc.php?action=pan_download&item=45&download=1
 LiquidCrystal_I2C lcd(0x27,16,2);  // Устанавливаем дисплей 
 Encoder myEnc(9, 8);//CLK, DT
      byte v1[8] = {7,7,7,7,7,7,7,7};
      byte v2[8] = {7,7,0, 0, 0, 0, 0, 0};      
      byte v3[8] = { 0, 0, 0, 0, 0,0,31,31};
      byte v4[8] = {31,31, 0, 0, 0, 0,31,31};
      byte v5[8] = { 28, 28, 0, 0, 0, 0, 28, 28};//
      byte v6[8] = {28,28,28,28,28,28,28,28};
      byte v7[8] = { 0, 0, 0, 0, 0, 0,7,7};
      byte v8[8] = { 31, 31,0,0,0,0,0, 0};
      int a[3];
      byte i,d1,d2,d3,d4,d5,d6,e1,e2,e3;
 unsigned long time,oldPosition  = -999,newPosition;
 int vol,vol_d,in,balanc,balanc_d,menu;
 bool w,mute;

void setup() {
 Wire.begin();
 lcd.init();lcd.backlight();
 pinMode(10,INPUT);   // кнопка энкодера
 pinMode(A0,OUTPUT);  // RSEL1
 pinMode(A1,OUTPUT);  // RSEL0
 pinMode(2,INPUT_PULLUP); // кнопка IN
 pinMode(3,INPUT_PULLUP); // кнопка MUTE
 lcd.createChar(1, v1);lcd.createChar(2, v2);lcd.createChar(3, v3);
 lcd.createChar(4, v4);lcd.createChar(5, v5);lcd.createChar(6, v6);
 lcd.createChar(7, v7);lcd.createChar(8, v8);
 Serial.begin(9600);
 lcd.setCursor(0,0);lcd.print("     CS4398     ");
 lcd.setCursor(0,1);lcd.print("     CS8416     ");
 MsTimer2::set(1, to_Timer);MsTimer2::start();
 delay(1000);
 vol = EEPROM.read(0);in = EEPROM.read(1);balanc = EEPROM.read(2)-20;
 wireWrite(0x4C, 0x02, 0b00011010);// I2S 24 bit / 48 kHz / 100...200 kHz
 wireWrite(0x4C, 0x03, 0b00001001);// default
 wireWrite(0x4C, 0x04, 0b11100000);// default
 wireWrite(0x4C, 0x05, vol+balanc+20);
 wireWrite(0x4C, 0x06, vol-balanc+20);
 wireWrite(0x4C, 0x07, 0b10110000);// default
 wireWrite(0x4C, 0x08, 0b01000000);// default
 wireWrite(0x4C, 0x09, 0b00001000);// default
 Serial.print("Chip ID 0");
 Serial.println(wireRead(0x4C, 0x01),BIN);
 lcd.clear();
 switch(in){
 case 0: digitalWrite(A0, LOW);digitalWrite(A1, LOW);lcd.print("COAX 1");break;// px0 
 case 1: digitalWrite(A0, LOW);digitalWrite(A1, HIGH);lcd.print("COAX 2");break;// px1
 case 2: digitalWrite(A0, HIGH);digitalWrite(A1, LOW);lcd.print("COAX 3");break;// px2
 }
}

void loop() {
 /// MENU /////////////////////////////////////// 
 if(digitalRead(10)==LOW){menu++;if(menu>1){menu=0;}lcd.clear();time=millis();w=1;delay(200);}
  
 /// INPUT ////////////////////////////////////// 
 if(digitalRead(2)==LOW){in++;if(in>2){in=0;}lcd.clear();time=millis();w=1;
 lcd.setCursor(5,0);lcd.print("INPUT");lcd.setCursor(5,1);
 switch(in){
 case 0: digitalWrite(A0, LOW);digitalWrite(A1, LOW);lcd.print("COAX 1");break;// px0 
 case 1: digitalWrite(A0, LOW);digitalWrite(A1, HIGH);lcd.print("COAX 2");break;// px1
 case 2: digitalWrite(A0, HIGH);digitalWrite(A1, LOW);lcd.print("COAX 3");break;// px2
 }delay(1000);lcd.clear();}
 
 /// MUTE /////////////////////////////
 if(digitalRead(3)==LOW && mute==0){mute=1;wireWrite(0x4C, 0x04, 0b11011000);delay(300);} 
 if(digitalRead(3)==LOW && mute==1){mute=0;wireWrite(0x4C, 0x04, 0b11000000);delay(300);} 
 if(mute==1){lcd.setCursor(0,1);lcd.print("MUTE  ");}
 else{lcd.setCursor(0,1);lcd.print("COAX ");lcd.print(in+1);
 }
 
 /// VOLUME + BALANCE ////////////////
 if(menu==0){
 if (newPosition != oldPosition){oldPosition = newPosition;
     vol=vol+newPosition;myEnc.write(0);newPosition=0;time=millis();w=1;
      if(vol<0){vol=0;}if(vol>150){vol=150;}
      wireWrite(0x4C, 0x05, vol+balanc+20);
      wireWrite(0x4C, 0x06, vol-balanc+20);}
      lcd.setCursor(0,0);lcd.print("VOLUME ");
     vol_d=150-vol;
     a[0]=vol_d/100;
     a[1]=vol_d/10%10;
     a[2]=vol_d%10;

 }

 if(menu==1){
 if (newPosition != oldPosition){oldPosition = newPosition;
     balanc=balanc+newPosition;myEnc.write(0);newPosition=0;time=millis();w=1;
      if(balanc<-20){balanc=-20;}if(balanc>20){balanc=20;}
      wireWrite(0x4C, 0x05, vol+balanc+20);
      wireWrite(0x4C, 0x06, vol-balanc+20);}
      lcd.setCursor(0,0);lcd.print("BALANCE ");
     if(balanc<0){lcd.setCursor(9,0);lcd.write((uint8_t)3);}else{lcd.setCursor(9,0);lcd.print(" ");}
     balanc_d=abs(balanc);
     a[0]=balanc_d/10;
     a[1]=balanc_d%10;
 }
  //////////////////////////////////  
    if(menu==0){
      for(i=0;i<3;i++){
      switch(i){
        case 0: e1=7,e2=8,e3=9;break;
        case 1: e1=10,e2=11,e3=12;break;
        case 2: e1=13,e2=14,e3=15;break;
        }
      switch(a[i]){
        case 0: d1=1,d2=8,d3=6,d4=1,d5=3,d6=6;break;
        case 1: d1=32,d2=2,d3=6,d4=32,d5=32,d6=6;break;
        case 2: d1=2,d2=8,d3=6,d4=1,d5=4,d6=5;break;
        case 3: d1=2,d2=4,d3=6,d4=7,d5=3,d6=6;break;
        case 4: d1=1,d2=3,d3=6,d4=32,d5=32,d6=6;break;
        case 5: d1=1,d2=4,d3=5,d4=7,d5=3,d6=6;break;
        case 6: d1=1,d2=4,d3=5,d4=1,d5=3,d6=6;break;
        case 7: d1=1,d2=8,d3=6,d4=32,d5=32,d6=6;break;
        case 8: d1=1,d2=4,d3=6,d4=1,d5=3,d6=6;break;
        case 9: d1=1,d2=4,d3=6,d4=7,d5=3,d6=6;break;
    }
     
      lcd.setCursor(e1,0);lcd.write((uint8_t)d1);lcd.setCursor(e2,0);lcd.write((uint8_t)d2);lcd.setCursor(e3,0);lcd.write((uint8_t)d3);
      lcd.setCursor(e1,1);lcd.write((uint8_t)d4);lcd.setCursor(e2,1);lcd.write((uint8_t)d5);lcd.setCursor(e3,1);lcd.write((uint8_t)d6);
 }}
///////////////////////////////////////
if(menu==1){
       for(i=0;i<2;i++){
      switch(i){
        case 0: e1=10,e2=11,e3=12;break;
        case 1: e1=13,e2=14,e3=15;break;
        }
      switch(a[i]){
        case 0: d1=1,d2=8,d3=6,d4=1,d5=3,d6=6;break;
        case 1: d1=32,d2=2,d3=6,d4=32,d5=32,d6=6;break;
        case 2: d1=2,d2=8,d3=6,d4=1,d5=4,d6=5;break;
        case 3: d1=2,d2=4,d3=6,d4=7,d5=3,d6=6;break;
        case 4: d1=1,d2=3,d3=6,d4=32,d5=32,d6=6;break;
        case 5: d1=1,d2=4,d3=5,d4=7,d5=3,d6=6;break;
        case 6: d1=1,d2=4,d3=5,d4=1,d5=3,d6=6;break;
        case 7: d1=1,d2=8,d3=6,d4=32,d5=32,d6=6;break;
        case 8: d1=1,d2=4,d3=6,d4=1,d5=3,d6=6;break;
        case 9: d1=1,d2=4,d3=6,d4=7,d5=3,d6=6;break;
    }
     
      lcd.setCursor(e1,0);lcd.write((uint8_t)d1);lcd.setCursor(e2,0);lcd.write((uint8_t)d2);lcd.setCursor(e3,0);lcd.write((uint8_t)d3);
      lcd.setCursor(e1,1);lcd.write((uint8_t)d4);lcd.setCursor(e2,1);lcd.write((uint8_t)d5);lcd.setCursor(e3,1);lcd.write((uint8_t)d6);
 }}


 delay(20);if(millis()-time>10000 && w==1){w=0;EEPROM.write(0,vol);EEPROM.write(1,in);EEPROM.write(2,balanc+20);
 menu=0;}
 }// loop
 
void wireWrite(byte addr, byte reg, byte data){
  Wire.beginTransmission(addr);
  Wire.write (reg);
  Wire.write (data);
  Wire.endTransmission();
  }

byte wireRead(int addr, int reg){
  Wire.beginTransmission(addr);
  Wire.write (reg);
  Wire.endTransmission();
  Wire.requestFrom(addr,1);
  while(Wire.available()<1);
  byte value = Wire.read();
  return value;
  }  

void to_Timer(){newPosition = myEnc.read()/4;}  

Форум — http://forum.rcl-radio.ru/viewtopic.php?pid=2306#p2306

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

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

Случайные статьи

  • TFT-дисплей SPI 320×240 (Arduino)

    TFT-дисплей SPI 320×240 (Arduino)

    Цветной TFT-дисплей SPI 320×240 используется для отображения текста и графических элементов: иконок, картинок, графиков, кадров анимации. Основные характеристики дисплея: Наименование: TFT01-22SP Контроллер: ILI9341C Диагональ: 3,2 дюйма Напряжение питание: 5 В Напряжение сигналов: 3,3 В Разрешение: 240 x 320 (RGB) Для работы с данными дисплеями отлично подойдет библиотека UTFT. Библиотека достаточно …Подробнее...
  • HI-FI УМЗЧ

    HI-FI УМЗЧ

    Характеристики: Номинальная выходная мощность — 24 Вт Диапазон звуковых частот при неравномерности 2дБ -20…22000Гц КНИ не более — 0,008%!!! Номинальное Uвх — 1В Rвх-7,5кОм Имеется защита от КЗ в нагрузке. Низкий КНИ достигнут благодаря введению глубокой ООС. Все детали кроме выходных транзисторов и БП монтируются на печатной плате. L1 наматывается …Подробнее...
  • Двухполярный источник питания 9 В от одной батареи

    Такой источник питания необходим для питания переносной РЭА, содержащей, например, операционные усилители. ИМС MAX1044 представляет собой конвертор напряжения с переносом заряда от конденсатора С1 к конденсатору С2 . В процессе работы MAX1044 вначале подключает «+» вывод С1 к питающему напряжению, а его «-» вывод — к общему проводу («Electronics Design», …Подробнее...
  • Индикатор уровня сигнала (Arduino)

    Индикатор уровня сигнала (Arduino)

    На рисунке показана схема линейного индикатора уровня сигнала, уст-во основано на Arduino Nano, индикатор LCD 1602. Индикатор способен отображать 30 уровней входного сигнала, входной сигнал не должен превышать 1.1 В, так как вход АЦП имеет внутреннее опорное напряжение 1.1 В. При большом уровне входного сигнала используйте делитель напряжения. #include <LiquidCrystal.h> …Подробнее...
  • Цифровой селектор входных сигналов на мультиплексорах КМОП структуры

    Число положений — 4 Максимальная амплитуда коммутирующего сигнала 7,5В Полоса частот 20…40000Гц Коэф. гармоник (20…20000Гц) — 0,1% Напряжение питания 15В Двоичный код сигнала, управляющего мультиплексором DD1, снимается с выходов RS триггеров на DD3.1-DD3.4. В зависимости от кода на входах А1 А2 микросхемы DD1 к ее выходу(вывод3) подключается один из входов. …Подробнее...