Внедряем аудиопроц, прерывания uart, инициализацию из EEPROM в усилок

Код проекта усилителя на tda7294 в PIC16f877a становится все больше, отлаживать его все труднее и дольше, но останавливаться уже нельзя :) В проекте вместе с новыми добавлениями появляются хирургические вырезы, но уже фактически видна финишная прямая, вон уже шлифмашинку заказал корпус свой пилить. Ну да это все лирика… Ну, приступим. Сначала я внедрил управление аудиопроцом TDA8425в существующий проект, но тут и расписывать особо нечего, все было подробно рассмотрено, здесь я просто добавил функции управления и вывел индикацию на дисплей. Так что этот пункт просто пропускаем. Дальше, так как я хочу сделать софт для ББ, то надо сварганить систему связи. Здесь я планирую заюзать преобразователь на FT232 с виртуальным портом. Конечно логичнее было бы взять какой-нибудь PIC18 серии с USB на борту, но я к сожалению пока еще не умею работать с USB портом, да и изначальный камень менять не хочется. В общем есть два варианта получать команды по уарту: в главном цикле проверяя флаг RCIF или в прерываниях опять же по этому флагу. Первый вариант отожрет немерянно ресурсов, поэтому для нас он неприемлем. Юзаем прерывания!

if (RCIF)
{
 if (!UartBytes[0])
   UartBytes[0] = getch();
 else
 {
   UartBytes[1] = getch();
   UartRecieve = 1;
 }
}

Перед этим естественно был включен RCIE. Для обмена данными я завел две переменные в массиве UartBytes – первая из них команда, вторая значение. После заполнения второй переменной устанавливается флаг UartRecieve, который обрабатывается в главном цикле программы:

if (UartRecieve)
{
 temp = UartBytes[0];
 ComByte = UartBytes[1];
 UartBytes[0] = 0;
 UartBytes[1] = 0;
 UartRecieve = 0;
 switch (temp)
 {
   case 49 : SetHour(ComByte); //установка часов
             break;
   case 50 : SetMin(ComByte); //установка минут
             break;
   case 51 : SetSeconds(ComByte); //установка секунд
             break;
   case 52 : if (ComByte < 10) //установка громкости
               volume = ComByte;
             else
               volume = 100 - ComByte;
             VL(volume);
             VR(volume);
             break;</pre>
case 53 : if (ComByte <= 15) //установка басов
 bass = ComByte;
 else
 bass = 100 - ComByte;
 BassSetup(bass);
 break;
 case 54 : if (ComByte <= 12) //установка тембра
 treble = treble;
 else
 treble = 100 - treble;
 break;
 case 55 : if (ComByte == 0xFF) //приглушение
 mute();
 else
 {
 TRISB2 = 1;
 TRISB1 = 1;
 volume_flag = 1;
 bass_flag = 0;
 treble_flag = 0;
 source_flag = 0;
 mode_flag = 0;
 menu(0);
 muteIR = 0;
 }
 break;

 case 56 : SwFuncByte = ComByte; //источник и режим
 I2CStart();
 I2CSend(0x82);
 I2CSend(0x08);
 I2CSend(SwFuncByte);
 I2CStop();
 break;
case 57 : //Alarm //будущая функция будильника
 break;
 case 58 : //StBy //будущая функция режима ожидания
 break;
 case 59 : //Radio //будущее радио
 break;
 case 60 : printf("\r\n%d", ReadHour()); //читаем часы
 break;
 case 61 : printf("\r\n%d", ReadMin()); //читаем минуты
 break;
 case 62 : printf("\r\n%d", ReadSeconds()); //читаем секунды
 break;
 case 63 : printf("\r\n%d", volume); //читаем громкость
 break;
 case 64 : printf("\r\n%d", bass); //читаем басы
 break;
 case 65 : printf("\r\n%d", treble); //читаем тембр
 break;
 case 66 : printf("\r\n%d", SwFuncByte); //читаем источник и режим
 break;
 case 67 : printf("\r\nalarm"); //читаем будильник
 break;
 case 68 : printf("\r\nstby"); //читаем в режиме ожидания мы или нет
 break;
 case 69 : printf("\r\nradio"); //читаем радиостанцию
 break;
}
}

По ходу дела решил добавить будильник, всегда хотел просыпаться под звуки радиостанции, а если бы она была еще и интернет радио :) Но это все пока в перспективе вместе с радиоприемниками.

Кстати заметил интересный глюк – у меня раньше из прерываний вызывалось несколько функций напрямую, из-за этого выбрасывало предупреждение “Possible hardware stack overflow”, но это еще не самое интересное, а самое интересное вскрылось, когда количество пунктов-команд уарта перевалило за 6, пульт продолжал работать исправно, но вот по нажатию на кнопку энкодера начиналось шоу на дисплее и по уарту. На первом куча разнообразных символов с огромной скоростью мчалось вправо, на втором выскакивали сообщения предназначенные для дисплея!!! Так что лучше все предупреждения фиксить сразу, а то мало ли на какие грабли еще можно наступить и дебажить до посинения.

Ну а теперь возьмемся за EEPROM. Итак, что нам нужно записывать?

1. Громкость

2. Бас

3. Тембр

4. Значение SwFuncByte (Здесь у нас источник, режим и mute)

5. Статус StBy

6. Время будильника (на перспективу)

7. Радиостанция (на перспективу)

Для начала я взял первые 4 пункта и записал их значения в EEPROM стандартными функциями записи, примерно так:


eeprom_write(0x00, 0x02); //volume
eeprom_write(0x01, 0x00); //bas
eeprom_write(0x02, 0x00); //treble
eeprom_write(0x03, 0b11001110); //SwFuncByte

Ну и проверяем после включения:

Вроде все правильно, вынесем теперь это дело в отдельную функцию:


void SaveState() //Сохранение значений в EEPROM
{
eeprom_write(0x00, volume);     //volume
eeprom_write(0x01, bass);       //bass
eeprom_write(0x02, treble);     //treble
eeprom_write(0x03, SwFuncByte); //SwFuncByte
}

Так, сейчас нужна функция инициализации с чтением из EEPROM


void InitAmp() //Инициализаця рабочих переменных из EEPROM
{
volume = eeprom_read(0x00);
bass = eeprom_read(0x01);
treble = eeprom_read(0x02);
SwFuncByte = eeprom_read(0x03);
}

Теперь надо решить, когда будет происходить сохранение, но это уже тема для другой статьи.
А здесь небольшая демонстрация:

Благодаря этому видео нашел еще один баг – при записи значения басов через уарт,  значение сбрасывается в 0, тоже самое и при чтении по уарту…

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

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Можно использовать следующие HTML-теги и атрибуты: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code class="" title="" data-url=""> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre class="" title="" data-url=""> <span class="" title="" data-url="">