MMC/SD WAV стерео плеер на ATmega32 с ПДУ

MMC/SD WAV стерео плеер на ATmega32 с ПДУ

Это мой первый и самый успешный проект на микроконтроллерах AVR. Несколько месяцев назад я попытался сделать WAV плеер на PIC16F877A. Он работал, но качество звука было не очень хорошим, потому что у него не было достаточного объема оперативной памяти, и я не смог сделать достаточный буфер данных. Когда я купил микроконтроллер ATmega32, первое, что пришло мне в голову – сделать хороший WAV плеер. Я закончил свою работу и качество звука действительно хорошее. Я могу сказать, что мой WAV плеер способен воспроизводить 8-битное моно /стерео с максимальным битрейтом 1300kbps для моно и 1600kbps для стерео. Т.е. можно играть 8-битное WAV моно с частотой дискретизации до 160 кГц и стерео до 96 кГц без шума!

Примечание: Полный спектр человеческого слуха составляет от 20 Гц до 20 кГц. Минимально достаточная частота дискретизации 40 кГц. Именно для этого частота дискретизации 44,1 кГц была выбрана для компакт-диска.

Я считаю, что это идеальный 8-битный WAV- стерео плеер. Я не нашел отличий между качеством звука с компьютера и этим плеером. Видео снималось мобильным телефоном, поэтому возможны потери качества звука. Поскольку ШИМ имеет некоторые ограничения, я пытался использовать R-2R ЦАП, но не заметил существенных улучшений.

Еще одной интересной особенностью плеера является то, что он может управляться с пульта от ТВ Philips (протокол RC5). Пультом можно переключатся между следующей и предыдущей песней, включать воспроизведение, ставить на паузу, включать некоторые забавные эффекты, такие как увеличение или уменьшение скорости воспроизведения. Программа для работы с MMC картой памяти не писалась с нуля, а была взята готовая.

Возможности:

Краткое описание работы:

Инициализация MMC карты и работа с ней была описана ранее тут.

Я использую дисплей 16×2 для отображения многих вещей. Сначала он при необходимости отображает сообщение об ошибке при попытке инициализации MMC. Когда инициализация проходит успешно, он показывает сообщение об этом.

Потом проверяется загрузочный сектор карты MMC (сектор 0), чтобы проверить файловую систему карты. Для этого нам нужно прочитать сектор 0 карты MMC и копировать его в буфер (для  этого задействовано 512б буфера). Мой код предназначен только для файловой системы FAT16, если на карте другая файловая система, он выдает сообщение об ошибке на дисплей. Если всё в порядке, то он читает данных из буфера и вычисляет номер сектора с началом данных, начало FAT и начало корневого каталога. Кроме того, он обнаруживает секторы кластеров. Каждый сектор это 512 байт. Эти данные необходимы для дальнейшей работы MMC / SD карт, хранятся как глобальные переменные.

Теперь необходимо попасть в корневой каталог. Нам нужно загрузить первый сектор корневого каталога в 512 байт буфера. Каждая запись содержит подробную информацию о файле или папке в корневом каталоге. Оттуда мы можем прочитать имя файла, атрибуты файла, адрес самого файл и многое другое. Нас интересует расширение файлов (WAV), атрибутах файла, адрес первого кластера куда записан файл.

Теперь мы можем прочитать первый кластер (группу секторов, размер зависит от размера памяти MMC / SD). Теперь, после чтения и воспроизведения всех секторов, в первой группе (проигрывание будет описано далее), то мы должны найти следующий номер кластера того же файла. Файл не может быть распределен в памяти как один раздел. Вместо этого, он может быть разделен на части, чтобы использовать свободную память эффективно (На самом деле это происходит только тогда, когда есть свободное место от удаленных файлов и добавлены новые). Таким образом, мы не можем сказать, что следующий кластер файла будет ближайшим. Но для чтения каждого файла есть список кластеров FAT (File Allocation Table), в котором каждый номер кластера имеет уникальную позицию. Мы уже вычислили начальный адрес FAT. С FAT мы можем получить следующий номер кластера в файле.

У нас есть номер первого кластера, и мы рассчитали начальный адрес сектора с определенным числом кластеров. Теперь мы читаем данные из первого сектора файла и оттуда мы получаем битрейт, частоту дискретизации, количество каналов и многое другое. Возьмем битрейт, и использовать его, чтобы установить частоту прерывания таймера. Теперь таймер генерирует прерывания в зависимости от битрейта и количества канала. Теперь на каждом прерывании таймера, 8 бит данных вводится в регистр OCR модуль таймера ШИМ. Соответственно, генерация ШИМ сигнала идет в фоновом режиме без затрат каких-либо ресурсов процессора. Этот сигнал ШИМ может быть легко демодулирован при помощи RC фильтра. Если значение конденсатора или резистора увеличивается или уменьшается , это повлияет на качество звука, т.е. он может не отфильтровать некоторые высокие частоты и можно услышать сигнал AM радио.

Теперь мы знаем, если мы используем один буфер для воспроизведения и сбора данных, то будет небольшой шум во время воспроизведения, что очень раздражает. Я выделил два специальных 512б буфера для только для аудио данных. Когда один буфер играет, другой буфер будет наполнятся.

Для декодирования сигнала телевизионного пульта мы используем прерывания таймера, проверяя входящей сигнал каждые 1778мс. При включении питания происходит задержка 400мс перед началом считывания сигнала с пульта. Возможно, плеер будет реагировать на сигнал с пульта со второго раза. Чтобы этого надо декодировать RC5 вне atmega32 и отправить значения через последовательный интерфейс для лучшей производительности.

Кварц я использовал на 16.450 МГц, т.к. под рукой не оказалось 16 МГц. Это никак не повлияло на работу микроконтроллера.

Фото работы:

Fuse: LFUSE = 0b11101111

Скачать ПО можно здесь или здесь

Оригинал статьи на английском языке (перевод: Иван для сайта cxem.net)


Категория: Микроконтроллеры
Метки:

Написать коментарий

*
= 5 + 4

Добавить изображение

Последние статьи