Содержание
Урок 1. Первый проект
Урок 2. Управление кнопками
Урок 3. Подключение LCD
Урок 4. Использование ШИМ
Урок 5. Таймеры
Урок 6.1. Статическая индикация
Урок 6.2. Динамическая индикация
Урок 7.1. Генерация звука
Урок 7.2. Генерация звука. Продолжение
Урок 8.1. Передача данных через UART
Урок 8.2. Передача данных через UART. Продолжение»
Урок 9. Передача данных через SPI
Урок 10. Изучение АЦП. Простой вольтметр
Урок 11. Получение синуса при помощи ШИМ
Урок 12. Измерение температуры
Урок 13. Внешние прерывания.
Урок 14. Использование отладчика
Урок 15.1. Управление инкрементальным энкодером
Урок 15.2. Управление громкостью, при помощи энкодера
Урок 16. Управление RGB светодиодом
Урок 17. Использование ИК
Урок 18.1. Знакомство с графическим дисплеем
Урок 18.2 Вывод изображения на графический дисплей
Урок 18.3 Вывод русскоязычного текста
Урок 19. Формирование сигнала, при помощи ЦАП (R2R)
Урок 20. Опрос матричной клавиатуры
Урок 21. Сторожевой таймер
Урок 22.1 Воспроизведение wav. Введение.
Урок 22.2 Воспроизведение wav. Продолжение.
Урок 23.1 Работа с внешней памятью
Урок 23.2 Работа с файловой системой Fat

Продолжение урока затянулось, оно и понятно, пришлось освоить работу с картами памяти и файловой системой FAT. Но все таки, оно свершилось, урок готов — фактически новогоднее чудо.
petushokLogo

Дабы не перегружать статью информацией, я не буду описывать структуру формата wav файла, информации в поисковиках более чем предостаточно. Достаточно сказать, что если открыть файл, каким либо Hex редактором, то в первых 44 байтах содержится вся информация о типе файла, частоте дискретизации, количестве каналов и пр. Если нужно анализировать файл, читайте этот заголовок и будет вам счастье.

wav_format

Полезные данные начинаются с 44 байта, по сути они содержат уровни напряжений, из которых формируется звук. Мы уже говорили про ступени напряжения, в прошлой части урока. Таким образом, все просто, нужно эти ступеньки вывести на динамик с частотой дискретизации файла.

Как физически заставить динамик дрыгаться? Нужно выводить эти уровни напряжения, при помощи ШИМ, либо использовать R2R. В любом случае, использовать очень просто, прочитал число, засунул его либо в OCR, либо в PORTx. Далее через определенное время, подставил следующее значение и так до конца файла.

Пример, некий wav файл, данные идут с 44=0х2С байта, там записано число 0х80, воспроизводим звук например ШИМом первого таймера, пишем OCR1A=0х80; Допустим, частота дискретизации вавки 8кГц, соответственно прерывание должно быть настроено на эту же частоту. В прерывании, подставляем следующее значение 0x85 через 1/8000=125мкс.
wav_format2

Как настроить прерывание на 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мкФ, «+» на ножку микроконтроллера, «-» на динамик. «-» динамика на землю, «+» на конденсатор.
sch_sdfat2

Не ждите громкого сигнала на выходе, чтобы звучало громко, необходим усилитель. На видео это хорошо видно. Для теста залил петуха 8кГц и трек 22кГц.

Желающие могут смело увеличить частоту таймера2, чтобы проигрывать файлы 44кГц, опыты показывают, что можно добиться вполне неплохого качества звучания. На видео звук слабый и качество плохое, но на самом деле это из-за того, что снимал на фотоаппарат.

Также выкладываю материалы любезно предоставленные Аппаратчиком — исходник для GCC, с которого была написана прошивка под CAVR.

И видео с воспроизведением 44кГц.

Пользуясь случаем поздравляю Всех с Наступающим, желаю чтобы все прошивки и девайсы у вас работали 🙂

Проект wav плеера на Atmega8

115 комментариев: Урок 22.2 Воспроизведение wav. Продолжение.

  • здравствуйте! делаю для себя будильник для приёма таблеток (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, только не спрашивайте где :mrgreen:

  • все таки я скачал в конце статьи проект wav плеера. но мне это не помогло 😥

  • значит стоит начать с статей попроще

  • admin,проста не внимательно смотрел файлы в проекте :mrgreen: я во всем разобрался .

    эти архивы надо добавлять в пк ❓
    #include «diskio.h»
    #include «pff.h»
    если надо то куда

  • эти файлы относятся к библиотеке чена

  • Подскажите, пожалуйста, как поменять настройки таймера в исходнике, чтобы работать от кварца на 4МГц, а не от 8МГц?

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

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

Последние комментарии
  • Загрузка...
Счетчик
Яндекс.Метрика