Продолжение урока затянулось, оно и понятно, пришлось освоить работу с картами памяти и файловой системой FAT. Но все таки, оно свершилось, урок готов — фактически новогоднее чудо.
Дабы не перегружать статью информацией, я не буду описывать структуру формата wav файла, информации в поисковиках более чем предостаточно. Достаточно сказать, что если открыть файл, каким либо Hex редактором, то в первых 44 байтах содержится вся информация о типе файла, частоте дискретизации, количестве каналов и пр. Если нужно анализировать файл, читайте этот заголовок и будет вам счастье.
Полезные данные начинаются с 44 байта, по сути они содержат уровни напряжений, из которых формируется звук. Мы уже говорили про ступени напряжения, в прошлой части урока. Таким образом, все просто, нужно эти ступеньки вывести на динамик с частотой дискретизации файла.
Как физически заставить динамик дрыгаться? Нужно выводить эти уровни напряжения, при помощи ШИМ, либо использовать R2R. В любом случае, использовать очень просто, прочитал число, засунул его либо в OCR, либо в PORTx. Далее через определенное время, подставил следующее значение и так до конца файла.
Пример, некий wav файл, данные идут с 44=0х2С байта, там записано число 0х80, воспроизводим звук например ШИМом первого таймера, пишем OCR1A=0х80; Допустим, частота дискретизации вавки 8кГц, соответственно прерывание должно быть настроено на эту же частоту. В прерывании, подставляем следующее значение 0x85 через 1/8000=125мкс.
Как настроить прерывание на 8кГц? Вспоминаем, если таймер работает на частоте 250кГц, то регистр сравнения прерывания нужно подставить (250/8)-1=31-1 или 0x1E. С ШИМом тоже все просто, чем выше частота на которой он работает тем лучше.
Чтобы прошивка работала, условимся, что флешка отформатирована в FAT32, используется либа PetitFat из урока 23.2. Файл в формате wav либо 8кГц, либо 22,050кГц, моно. Название файла 1.wav. Анализируем прошивку.
#include <mega8.h> #include "diskio.h" #include "pff.h" unsigned char buffer[512]; /* буфер в который копируется инфа с флешки */ volatile unsigned int count; //счетчик скопированных данных interrupt [TIM2_COMP] void timer2_comp_isr(void) //прерывание в котором подставляются значения { OCR1A = buffer[count]; //выводим звук на динамик if (++count >= 512) //увеличиваем счетчик count = 0; //если 512 обнуляем } void main(void) { unsigned int br; /* счетчик чтения/записи файла */ unsigned char buf = 0; //переменная определяющая какая часть буфера читается FATFS fs; /* Рабочая область (file system object) для логических дисков */ PORTB=0x00; DDRB=0x02; //дрыгаем шимом ocr1a // Timer/Counter 1 initialization // Clock source: System Clock // Clock value: 8000,000 kHz // Mode: Fast PWM top=0x00FF // OC1A output: Non-Inv. TCCR1A=0x81; TCCR1B=0x09; TCNT1=0x00; OCR1A=0x00; // Timer/Counter 2 initialization // Clock source: System Clock // Clock value: 250,000 kHz // Mode: CTC top=OCR2 TCCR2=0x0B; TCNT2=0x00; //OCR2=0x1E; //настройка регистра сравнения для 8кГц OCR2=0xA; //для 22кГц #asm("sei") // Timer(s)/Counter(s) Interrupt(s) initialization if(disk_initialize()==0) //инициализируем флешку { pf_mount(&fs); //монтируем файловую систему pf_open("1.wav"); //открываем вавку pf_lseek(44); //перемещаем указатель на 44 pf_read(buffer, 512,&br); //в первый раз заглатываем сразу 512байт TIMSK=0x80; //врубаем музон while(1) { if(!buf && count>255) //если воспроизвелось больше 255 байт, { pf_read(&buffer[0], 256,&br);//то читаем в первую половину буфера инфу с флешки buf=1; if (br < 256) //если буфер не содержит 256 значений значит конец файла break; } if(buf && count<256) { pf_read(&buffer[256], 256,&br); // читаем во вторую часть буфера с флешки buf = 0; if (br < 256) break; } } TIMSK = 0x00; //глушим все pf_mount(0x00); //демонтируем фат } while (1) { } } |
Для проверки, на ножку OCR1A подключаем динамик через конденсатор 100мкФ, «+» на ножку микроконтроллера, «-» на динамик. «-» динамика на землю, «+» на конденсатор.
Не ждите громкого сигнала на выходе, чтобы звучало громко, необходим усилитель. На видео это хорошо видно. Для теста залил петуха 8кГц и трек 22кГц.
Желающие могут смело увеличить частоту таймера2, чтобы проигрывать файлы 44кГц, опыты показывают, что можно добиться вполне неплохого качества звучания. На видео звук слабый и качество плохое, но на самом деле это из-за того, что снимал на фотоаппарат.
Также выкладываю материалы любезно предоставленные Аппаратчиком — исходник для GCC, с которого была написана прошивка под CAVR.
И видео с воспроизведением 44кГц.
Пользуясь случаем поздравляю Всех с Наступающим, желаю чтобы все прошивки и девайсы у вас работали 🙂
Проект wav плеера на Atmega8
здравствуйте! делаю для себя будильник для приёма таблеток (4 времени срабатывания). старый вариант был на atmega8L с пьезорезонатором. питание от аккумулятора мобильника. сделал на меге8 и карте mikrosd. работает (карту подключал без резисторов), НО меге не хватает питания (питаю 3.3в). приходится часто заряжать аккум. пытался портировать код в megа8L — не работает. куда копать? подскажите пожалуйста!
Разница между atmega8 и atmega8l нет, в том что максимальная частота л 8мгц, а в остальном они одинаковы. Поэтому смысла ставить л вместо обычной нет, частоту проекта можно настроить и для обычной. Если большое потребление, то убирайте все подсветки, вводите мк в сон.
как только поставил резисторы подтяжки с +3.3в по 10кОм на линии CS, DI, CLK так всё и заработало! тактирую кварцем на 8МГц ввиду того, что при разряде аккумулятора ниже 3.1в и тактировании от встроенного RC генератора скорость воспроизведения немного падает. слышно на слух. огромное СПАСИБО Вам за статью!
p.s. или mega8L попалась такая, или всё вместе, схема работает от 2.38в.
еще раз СПАСИБО!!!
Здравствуйте! у меня опять затык…
оформил процедуру:
void play_h (unsigned int x){
if(disk_initialize()==0) //инициализируем флешку
{
pf_mount(&fs); //монтируем файловую систему
switch (x){
case 1:{pf_open(«1h.wav»);break;} //открываем вавку 1h.wav
case 2:{pf_open(«2h.wav»);break;} //открываем вавку 2h.wav
// и так далее…
}
pf_lseek(44); //перемещаем указатель на 44
pf_read(buffer, 512,&br);
TIMSK=0x80;
while(1)
{
if(!buf && count>255)
{
pf_read(&buffer[0], 256,&br);
buf=1;
if (br < 256)
break;
}
if(buf && count<256)
{
pf_read(&buffer[256], 256,&br);
buf = 0;
if (br < 256)
break;
}
}
TIMSK = 0x00;
pf_mount(0x00);
}
}
в цикле:
while (1)
{
if(!PIND.3){rtc_get_time(&hour,&min,&sek); //если нажата кнопка — считать время
play_h(hour);play_m(min);} // процедура play_m идентична play_h, но воспроизводятся файлы 1m.wav и т.д.,
}
получается громоздкий код.
а вот как "склеить" переменную hour для pf_open(hour+".wav") я так и не допёр.
может есть какое нибудь решение? в долгу не останусь: хоть на Ваш номер телефона деньжат переведу, или каким другим способом отблагодарю. (я ещё новичок в программировании,прошу сильно не пинать).
«1.wav» это массив символов, переводить можно с помощью функции sprintf
например так
sprintf(buf[], "%c.wav", hour)
в массиве buf будет преобразованный массив
Есть ли возможность менять частоту звука и тембр непосредственно в контроллере?
Что запишешь через комп, то и будет.
Например, wav файл — звук акустической гитары ноты ми первой октавы. Что нужно делать для того, чтобы в процессе его воспроизведения частота звука плавно увеличивалась (как это бывает при подтяжке струны — band)? интересует именно программная часть
Вы сами ответили на свой вопрос — увеличивайте частоту. Программная часть разжевана в таймерах. Чем чаще прерывание, тем выше частота.
Подскажите как настроить проект под mega328 (различие только в настройках таймеров)?
хотя не заметил — по умолчанию CKDIV8 установлен — убрать и все норм
I am trying to compile the code with AVR Studio 5, and it show me a lotof errors.
Did someone who have the project folder, can upload it, or to contact with him for sending it to me ?
Thank you
Vasilis
Second link is source code for avr studio. For compile, you need add libs from first link
Thank you!!!
What about fuses?
Low = E4
High = 99
Correct ?
for external crystal resonator 8mhz
low:0xff
high:0xd9
for internal rc 8mhz
low:0xe4
high:0xd9
Thank you for your answer, but both settings are for external rc.
Ok, You are right. Forget my previous answer.
Thank you!!!
Добрый день!
Подскажите, выдает 5 ошибок, чего может не хватать?.
Linker error: \diskio.h(26): function ‘disk_initialize’ declared, but never defined
Linker error: \pff.h(137): function ‘pf_mount’ declared, but never defined
Linker error: \pff.h(138): function ‘pf_open’ declared, but never defined
Linker error: \pff.h(139): function ‘pf_read’ declared, but never defined
Linker error: \pff.h(141): function ‘pf_lseek’ declared, but never defined
не подключен сишный файл, он добавляется в настройках проекта
Здравствуйте!
Подскажите пожалуйста, а библиотека для работы с SD-картой как-то привязана к портам аппаратного SPI (в схеме протеуса подключение именно на SPI)? Возможно ли переназначить ей другой порт/другие ножки, не относящиеся к SPI?
Спасибо.
если реализовать программный SPI
Или взять STM32. Там аж 2 штуки SPI и первый можно даже ремапить под свои нужды.
Или взять ПЛИСину там можно сколько угодно SPI наворотить, были бы ЛЭ 😀
Здравствуйте!
В протеусе схема работает?
нет
Какие-нибудь элементы нужно ещё добавлять к схеме, которая приведена выше, чтобы собрать её в железе?
при трехвольтовом питании нет
Спасибо за ответы.
Ещё вопрос, можно ли сделать так, чтобы песни, записанные на флешку проигрывались по очереди при нажатии кнопки, если можно, подскажите как это будет выглядеть в коде программы
Почему нет звука в протеусе? Слышу какие-то: пи-пи-пи-пи-пи-пи…?
Протеус не поддерживает карты памяти, кроме MMC. Поэтому ничего работать в нем не будет
Здравствуйте, а как сделать ,чтобы трек с кнопки запускался и останавливался с другой ❓ . А то проста плеер нужен ,а купить лень 😀 .
В конце статьи добавил проект wav плеера.
я не могу открыть файл проекта .
ищите цавр 3.12, только не спрашивайте где
все таки я скачал в конце статьи проект wav плеера. но мне это не помогло 😥
значит стоит начать с статей попроще
admin,проста не внимательно смотрел файлы в проекте я во всем разобрался .
эти архивы надо добавлять в пк ❓
#include «diskio.h»
#include «pff.h»
если надо то куда
эти файлы относятся к библиотеке чена
Подскажите, пожалуйста, как поменять настройки таймера в исходнике, чтобы работать от кварца на 4МГц, а не от 8МГц?