Генерация звука с помощью AVR. Озвучь свой девайс

Введение

Написал программный модуль, позволяющий добавить функцию воспроизведения мелодий или последовательностей звуков практически в любой проект на микроконтроллере AVR. 
 
Особенности модуля:
 
- простая интеграция с готовым проектом 
- задействован только 8-ми разрядный таймер т2, при этом остается возможность использовать его для опроса или формирования временных интервалов
- модуль настраивается практически на любую частоту тактового генератора
- высота нот задается в виде символических констант (С0, А2 и т.д) или в Герцах 
- длительности задаются в стандартном виде (четверти, восьмые и т.д.) или в миллисекундах
- имеется возможность задавать темп воспроизведения мелодии и количество ее повторений
- в процессе воспроизведения мелодия может быть поставлена на паузу


Подключение звукового модуля

1. Переписываем все файлы модуля (tone.h, sound.h, sound.c)  в папку проекта.
 
2. Подключаем файл sound.c к проекту. 
Для IAR `a – кликнуть правой кнопкой мышке в окне workspace и выбрать Add > Add Files…
Для WINAVR примерно то же самое, только sound.c нужно еще прописать в make файл: 
 
    # List C source files here. (C dependencies are automatically generated.)
    SRC = $(TARGET).c sound.c
 
3. Включаем заголовочный файл sound.h в соответствующий модуль. Например, в main.c
 
   #include "sound.h"
 
4. Задаем настройки модуля в файле sound.h
 
   //если закомментировать - длительность нот будет     
   //рассчитываться из BPM`а  заданного в мелодии 
   //если оставить, то из значения заданного ниже
   //#define SOUND_BPM       24  
 
   //тактовая частота мк                              
   #define SOUND_F_CPU     16U 
 
   //вывод микроконтроллера, на котором будет генерироваться звук 
   #define PORT_SOUND PORTB
   #define PINX_SOUND 0
 
   //количество заданных мелодий.  
   #define SOUND_AMOUNT_MELODY 4
 
5. Добавляем в sound.c свои мелодии и прописываем названия мелодий в массив melody[].

Добавление мелодий

   Мелодия представляет собой массив 16-ти разрядных чисел и имеет следующую структуру 
генерация звука на avr. структура мелодии
   BPM (количество четвертных нот в минуту) – это константа, используемая для расчета длительности нот и определяющая скорость воспроизведения мелодии. 
   BPM может принимать значения от 1 до 24, что соответствует 10 и 240 четвертным нотам в минуту соответственно. 
   Если длительность нот/звуков задается в миллисекундах, то BPM, прописанный в массиве, должен быть равен 1.
   Если в заголовочном файле sound.h константа SOUND_BPM закомментирована, то длительность нот рассчитывается в процессе выполнения программы по BPM `у  заданному в массиве. Если SOUND_BPM  не закомментирована – длительность нот рассчитывается еще на этапе компиляции, исходя из значения этой константы, при этом все мелодии будут воспроизводиться в одинаковом темпе. Это ограничивает функционал, но позволяет сэкономить несколько байт кода. 
 
   Количество повторений. Может принимать значения 1 ... 254 и LOOP (255). LOOP - означает, что мелодия будет повторяться бесконечно, пока не будет подана команда SOUND_STOP или SOUND_PAUSE. 
 
   Длительность ноты – время в течение, которого генерируется заданный тон звука или выдерживается пауза. Может задаваться в ms, с помощью макроса ms(x), или в виде стандартных длительностей нот – восьмых, шестнадцатых и т.д. Ниже приведен список поддерживаемых длительностей. Если возникнет нужда в каких-то экзотических длительностях, их всегда можно добавить в файле tone.h 
 
n1  - целая нота
n2  - половинная нота
n4  - четверть
n8  - восьмая
n3  - восьмая триоль
n16 - шестнадцатая
n6  - секстоль
n32 - тридцать вторая
 
   Высота ноты задается с помощью символических констант описанных в файле tone.h, например C2, A1 и т.д. Также высота нот может задаваться в Герцах с помощью макроса f(x).
В программе есть ограничения на минимальную и максимальную частоту звука!  
 
   Маркер конца мелодии. Значение последнего элемента массива обязательно должно быть нулевым. 

Использование звукового модуля

   В начале main`a нужно обязательно вызывать функцию SOUND_Init(). Эта функция настраивает вывод микроконтроллера на выход, конфигурирует таймер Т2  и  инициализирует переменные модуля. 
   Затем нужно установить флаг разрешения прерываний - __enable_interrupt(), ведь в модуле используется прерывания таймера Т2 по переполнению и совпадению.
    После этого можно запускать воспроизведение мелодий.
Например, так: 
 
   SOUND_SetSong(2); //установить указатель на 2-ю мелодию
   SOUND_Com(SOUND_PLAY);  //воспроизвести мелодию
 
Или так:
 
   //установить указатель на 2-ю мелодию
   //и запустить воспроизведение
   SOUND_PlaySong(2);
 
    Воспроизведение мелодии можно в любой момент остановить, подав команду SOUND_STOP.
   Также мелодию можно поставить на паузу с помощью команды  SOUND_PAUSE. Последующая подача команды SOUND_PLAY возобновляет воспроизведение мелодии с места, на котором произошла остановка. 
   В принципе данный функционал не особо нужен (это уж я просто навернул) и при работе с модулем достаточно функции  SOUND_PlaySong(unsigned char numSong);

Файлы

   Примеры использования звукового модуля вы можете скачать по ссылкам ниже. Схему рисовать не стал, потому что там все просто. Пьезоизлучатель подключен к выводу PB0, кнопка запуска мелодий подключена к выводу PD3. В проектах определено 4 мелодии. Нажатие на кнопку запускает каждый раз новую мелодию. Используется микроконтроллер atmega8535. Изначально хотел заморочиться на проект с четырьмя кнопками - PLAY, STOP, PAUSE и NEXT, но потом подумал, что это лишнее. 

 
Исходники звукового модуля для трех компиляторов

PS: Модуль не проходил расширенное тестирование и предоставляется “как есть“. Если есть какие-то рациональные предложения - давайте его доработаем. 

У вас недостаточно прав для комментирования.