Код проекта усилителя на 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, тоже самое и при чтении по уарту…
Уведомление: Adding the audio processor, initialization and EEPROM to the amplifier brain | diymicro.org