Это мой первый цифровой диктофон с использованием PIC с ОЗУ всего 256 байт. Обычно люди скажут, что нельзя получить доступ к MMC / SD карте памяти с помощью микроконтроллера с объемом ОЗУ менее 512 байт. Но я смог это сделать, но возможно есть некоторые ограничения.
Здесь я использовал PIC16F877A для доступа к MMC карте памяти. MMC связана с PIC16F877A по интерфейсу SPI. Я не использовал никакой файловой системы. МК записывает 8 битный цифровой сигнал с АЦП на MMC с помощью нескольких команд записи блока. Один блок состоит из 512 байт и также называется сектором. Точно так же он читает 8 битные цифровые данные. После прочтения каждого байта, он отправляется в регистр ШИМ для генерации ШИМ-сигнала, соответствующего аудиозаписи. Затем сигнал проходит через ФНЧ, усиливается и выводится на динамик.
Качество звука было выше моих ожиданий. Это связано с высокой скоростью передачи данных.
MMC связана с PIC16F877A через встроенный в него 8 битный последовательный интерфейс SPI. Для этого используется три вывода:
• Последовательный выход данных (SDO) — RC5/SDO
• Последовательный вход данных (SDI) — RC4/SDI/SDA
• Serial Clock (SCK) — RC3/SCK/SCL
MMC работает от 3.6В, а PIC16F877A от 5В. Нам необходим преобразователь уровня напряжения для сопряжения PIC и MMC. Для этого используются резисторы подключенные к CS, CLK и SCK. Теперь, когда 4.3В с PIC появляются на любом из этих 3-х выводов, то напряжение на соответствующих выводах MMC будет 2.48В.
Работа с MMC
Чтобы начать операцию с MMC, мы должны отправить команду длиной 6 байт(см. рисунок), которая разная для каждой операции.
Вот, как это будет выглядеть в коде:
void command(char command, unsigned long int fourbyte_arg, char CRCbits )
{
spi_write(0xff);
spi_write(0b01000000|command);
spi_write((unsigned char)(fourbyte_arg >> 24));
spi_write((unsigned char)(fourbyte_arg >> 16));
spi_write((unsigned char)(fourbyte_arg >> 8));
spi_write((unsigned char)fourbyte_arg);
spi_write(CRCbits);
spi_read();
}
Приведенные выше команды это функция управления. Они отправляют 6 байтную команду MMC.
В MMC командах наиболее значимым байтом является командный байт. В командном байте 2 «MSB» бита всегда 01. Остальные 6 бит это фактическая команда. Соответственно 6 бит CMD0 будут 000000 и 2 бита MSB будут 01. Т.е. 0b01000000 (двоичная. сист) или 0x40(шестнадцатеричная) или 64(десятичная). Потом идет 4 байта которые несут определенную информацию для передачи в MMC, т.е. информацию, такую как адрес сектора, размер блока и т.д. Это зависит от команды, требует ли она 4 байта аргумента или нет. Если нет, то неиспользуемые необходимо заполнить нулями. Потом идет байт CRC, который не используется в режиме SPI и его мы тоже заполняем нулями.
Команда 0 (CMD0) выглядит так:
command(0,0,0×95);
Существуют различные типы команд ответов. В некоторых случаях мы должны постоянно проверять ответы, ожидая правильный. Есть команды для чтения, записи и т.д. Каждая команда состоит из 512 байт данных(1 сектор). Мы не можем прекратить операцию чтения или записи в середине блока.
Инициализация MMC
Когда питание MMC подключено, нам нужно инициализировать MMC и перевести её в SPI режим. Это требует ряда команд, а также мы должны проверить ответ.
На самом деле инициализации была главной проблемой, с которой я столкнулся в самом начале. Прошло 3 дня, прежде чем я успешно инициализировал MMC карту.
Передача данных
Чтение одного блока
Аргумент определяет откуда начать читать группу байтов или блок. Адрес сектора, указанный верхним битом должен быть правильным. Если всё правильно, инициируется операция чтения и результат чтения отправляется на хост. Если произошла ошибка во время чтения, вместо пакета данных придет сообщение об ошибке.
Чтение нескольких блоков
Команда чтения нескольких блоков читает последовательно несколько блоков по указанному адресу. Если номера блоков небыли указаны перед этой командой, то буду читаться блоки до CMD12. Байт полученный сразу после CMD12 необходимо уничтожить до получения ответа от CMD12.
Запись одного блока
Когда команда записи принята, то хост-контроллер посылает пакет данных на карту после байта пространства. Формат пакета такое же, как и при чтении. Значение CRC может быть любым. После записи данных карта памяти подает сигнал об успешной записи. Большинство карт не может изменить размер блока, по умолчанию он равен 512 байтам.
В режиме SPI сигнал CS должен быть отправлен во время операции.
Запись нескольких блоков
Команда чтения нескольких блоков читает последовательно несколько блоков по указанному адресу. Если номера необходимых блоков не указаны, то будут записываться все блоки по порядку. Во время чтения сигнал занятости появится на линии DO.
Воспроизведение аудио
Для этого я использовал встроенный в PIC ШИМ модуль в качестве ЦАП. ШИМ это хорошее и дешевое решения для ЦАП. Если я ставлю 8 бит данных в реестре CCPR2L, он будет генерировать ШИМ сигнал, соответствующий этим данным. Этот сигнал может быть усилен и отправлен на динамик.
АЦП
АЦП используется для преобразования аналогового звукового сигнала с предусилителя. PIC16F877A имеют встроенный 10-битный АЦП. Я использовал лишь 8 бит для удобства хранения данных на MMC.
Прикрепленные файлы:
- voice_recorder.rar (4 Кб)