Содержание
Урок 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

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

  • С резистором я сам знаю :razz: а вот как организовать регулировку с контроллера?

  • каждая точка это амплитуда, если домножать все точки на коэффициент, то общая амплитуда будет изменяться

  • Подскажите, правильно я понимаю, что:
    1) Программирование программатором, использующим MISO и т.д. будет далее не доступно?

  • нет, в момент программирования контроллер находится в состоянии сброса, поэтому основная прога никак не повлияет

  • Для использования на Atmega32a нужно только порты поменять на соответствующие и библиотеку mega32?

  • и настройки spi

  • Скачал проект при компиляции выводит кучу Warning`ов. Это нормально или искать где ошибка?

  • нормально

  • Доброго времени суток!
    Очень понравился ваш проект! Я его решил перенести на arduino2560 и при компиляции всплывает ошибка
    invalid conversion from ‘unsigned int*’ to ‘WORD* {aka short unsigned int*}’ [-fpermissive]
    С чем это может быть связано? Все типы выставлены вроде правильно
    #include
    #include
    #include
    unsigned int buffer[512]; /* буфер в который копируется инфа с флешки */
    volatile unsigned int count; //счетчик скопированных данных
    extern unsigned int br;
    //volatile unsigned int tcnt2;
    void setup()
    { pinMode(53, OUTPUT);
    pinMode(51, OUTPUT);
    digitalWrite(53, LOW);
    digitalWrite(51, LOW);
    }
    //***************Настройка таймера-счётчика****************
    void Timer1_init()
    { TCCR1B |= ((1<<WGM12) | (1<<CS12));
    TIMSK1 |= (1<255) //если воспроизвелось больше 255 байт,
    { //pf_read(buffer[0], 256, br);//то читаем в первую половину буфера инфу с флешки
    buf=1;
    if (br < 256) break; //если буфер не содержит 256 значений значит конец файла
    }
    if(buf && count<256)
    { pf_read(&buffer[256], 256,&br); // читаем во вторую часть буфера с флешки
    buf = 0;
    if (br < 256) break;
    }

    }
    //TIMSK = 0x00; //глушим все
    pf_mount(0x00); //демонтируем фат
    }

    }
    }

  • читайте не unsigned int а unsigned char

  • Правильно ли я понимаю что ШИМ в данном примере работает на частоте 31250 Гц?
    Какую роль играет частота ШИМа, или важно только чтобы прерывание было настроено на частоту дискретизации файла?

  • чем быстрее шим, тем быстрее вы можете перейти от одного уровня напряжения к другому. если скорость будет не достаточная, то тупо напряжение не будет успевать меняться, вместо ожидаемого звука вы услышите совсем не то

  • Кстати о петухах, новый язык прогирования Petooh появился

  • А разве не нужно согласование уровней с SD картой? Или MCU от трех вольт запитан?

  • от 3.3В

  • Собрал всё работает,не получается таймер 2 настроить чтоб проигрывать файлы на 44кГц,,поставил кварц на 16мГц, дайте пожалуйста код настройки таймера

  • в статье есть формула, подставьте значения. теорию можно почитать тут http://avr-start.ru/?p=4500

  • Доброй ночи.
    Есть вопрос по схеме. При использовании прошивки wav_player.7z и аудио записи в формате wav 8кГц — звук идет через динамик, но на фоне воспроизведения идет сильный гул в результате которого слушать мелодию не реально. В чем может быть проблема?

  • кондер стоит для отвязки?

  • Да, конденсатор тоже ставил согласно схемы, но результат не изменился в лучшую сторону. Может ли быть это из за используемого усилителя? Я использовал усилитель вот такой: ardu.net/ru/moduli/41-usilitel-zvuka-2kh3w-25-5-5v-miniatyurnyj-pam8403-190871911.html
    При его использовании в других схемах такого шума нет.

  • возможно, попробуйте подтянуть выход с мк на землю через 100кОм.

  • Добрый вечер!

    Каким образом в данном проекте заставить воспроизводить один из двух звуковых файлов (1.wav и 2.wav) по нажатию на одну из двух кнопок?

  • в конце статьи есть что то вроде вав плеера

  • Здравствуйте! Спасибо огромное за Ваши уроки. Собрал схему данного урока — работает!
    Подскажите пожалуйста, как сделать так, чтобы воспроизведение начиналось не с момента подачи питания, а через некоторое время? Создал прерывание по переполнению таймера 0, в нем веду отсчет времени, а где подставить условие на начало воспроизведения не знаю. Помогите пожалуйста.

  • сделайте флаг while(play!= 1);

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

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

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

Свежие записи
Последние комментарии
  • Загрузка...
Архивы
Счетчик
Яндекс.Метрика