Животът на Embedder

Живот в технологиите

Всъщност пускам статията, която обещах по-рано. Трябва да кажа, че този проект се оказа изключително търсен (аз самият съм изненадан) - разработените модули влязоха в две устройства и изглежда, че ще се случи третото. Така че да не ги показваме в блога би било двойно погрешно.

Аудио изходът е същността на цифрово-аналоговото преобразуване. Това може да стане по различни начини - поставете R-2R матрица, вземете готов DAC чип, използвайте PWM изход. Ние се интересуваме от последното, защото ни позволява да се справим с най-малко количество външни компоненти и в същото време създава някои предпоставки за получаване на висока ефективност на AF усилвателя (ако целта е да свържете високоговорител, а не изход към линеен изход, например).

Вече писах за ШИМ (по-специално по отношение на AVR). Накратко, забележително е, че ефективната стойност на такъв сигнал е пропорционална на неговия работен цикъл. Съответно, ако със скоростта на вземане на проби от дигитализирания сигнал, представляващ интерес, стойностите на работния цикъл са пропорционални на действителните стойности на извадката, ефективната стойност на ШИМ сигнала спрямо времето ще представлява възпроизведения сигнал. Остава само да филтрираме носещата честота на ШИМ (и в същото време честотата на дискретизация), а на изхода получаваме аналогов сигнал от цифров. В случай на високоговорител можете да не филтрирате нищо - инерцията на механиката ще направи всичко сама. Тогава усилвателят може да работи в ключов режим и съответно да има висока ефективност.

  1. Теорема на Котелников-Найквист: честотата на дискретизация трябва да бъде най-малко два пъти максималната честота на възпроизвеждания сигнал.
  2. Основно правило: Носещата честота на ШИМ трябва да бъде най-малко два пъти честотата на дискретизация.

Както вече споменахме по-горе, красотата на избрания метод е, че от външни компоненти не се изисква нищо - почти всички контролери имат вграден PWM блок за генериране. Ако искаме линеен изход, поставяме RC филтър с гранична честота, определена от теоремата на Котелников-Найквист. По-добре би било, разбира се, да се постави филтър от втори ред, но по отношение на слушането на звука ще свърши проста RC схема. Ако искаме мощен изход към високоговорителя, поставяме ключова сцена. Според TK имах нужда точно от високоговорителя, затова поставих ключовия етап (схемата с най-добро качество е в файловете на проекта):

аудио

Веригата е проектирана с перспектива за монтаж в различни конфигурации. Без промяна на печатната платка е възможно да се получат следните опции:

1. Основната схема, която отиде при клиента.

  • не е инсталиран: C2, DA1, Q5, Q6;
  • монтиран е джъмпер R2;
  • R5, R6, R7 заменени от джъмпери, сигналът се отстранява от PWMA изхода.

В тази конфигурация той се захранва от 3V батерия (изискване за SD карта) и теоретично е в състояние да доставя мощност на товар до ват. В действителност измереният среден ток в работен режим е 30 mA (натоварване 16 Ohm).

2. При желание схемата може да бъде подобрена:

  • задайте Q5 и Q6, R5/R6/R7 на посочените стойности, премахнете сигнала от ШИМБ;
  • вдигнете захранващото напрежение, извадете джъмпера R2 и монтирайте стабилизатора и C2. В този случай максималната мощност в динамика ще се определя изключително от товароносимостта на изходните транзистори и може да бъде десетки ватове. Може да се наложи да изберете R6, за да осигурите оптималната работа на изходния етап (този резистор задава защитния интервал, без него каскадата ще излъчва дим при сериозно натоварване).

Силно се препоръчва да свържете горния щифт на R3 към земята чрез резистор от около 10K. Това ще спести Q2 от работа в откъснат основен режим, докато контролерът все още не е конфигурирал крака OC0B за извеждане. Съжалявам, първоначално го пренебрегнах, проектът беше направен набързо. По принцип ще работи по този начин, но е по-добре да бъдете застраховани.

Високоговорителят е свързан чрез кондензатор с капацитет около 22 μF, монтиран с навес. Това е достатъчно.

Към щифта RDSW първоначално е бил свързан тръстиков превключвател. Когато щифтовете RDSW са затворени, веригата е деактивирана.

Пинът на конектора за SD карта не е показан на диаграмата, тъй като се определя програмно - в този проект използвах драйвера на SD картата си в оригиналната му форма, със софтуер SPI. Да, ATmega48 има хардуерен SPI, но софтуерът е по-удобен и скоростта му е напълно достатъчна, затова го използвах.

Дъската беше проследена с едно движение. Падна в една посока:

възпроизвеждане

Така че ще възпроизведем PCM аудио от SD карта. Нека започнем с първата част, за звука.

Пусни звук

За възпроизвеждане на звук е написан отделен модул (pcm_out.c + pcm_out.h), който реализира настройката на два таймера (единият за генериране на ШИМ, а другият за отчитане на интервалите за вземане на проби), извеждане на осембитови семпли в прекъсване, както и двойно буфериране. Две функции и две променливи са достъпни извън модула:

PCM_Init (), както се досещате, инициализира всичко, свързано със звуковия изход. По-нататъшната работа с модула изглежда така:

  • за да започнете да възпроизвеждате буфера, задайте бита PCM_ENABLED в PCM_status;
  • докато буферът на сенките се възпроизвежда, напишете нови данни в PCM_write_buffer; когато буферът приключи, битът PCM_BUFFER_ENDED ще бъде зададен в PCM_status;
  • тук можем да извикаме PCM_FlipBuffers (). Тази функция разменя буферите и можем отново да пишем в PCM_write_buffer, нов, докато се възпроизвежда този, който сме записали предишния път;
  • ако зададете PCM_ENABLE_AUTOFLIP, след края на буфера за сянка той автоматично ще бъде заменен с нов, но само веднъж, след което този флаг ще бъде изчистен.

Настройки - период на честота на вземане на проби в отметки на таймера и размер на буфера в байтове. Има два буфера, така че използваната памет ще бъде два пъти по-голяма.

За всеки случай, форматът за възпроизвеждане, разбира се, е неподписан 8-битов PCM.

Достъп до SD карта.

От този момент започва най-интересното. Поне за мен.

Реших този проблем по следния начин: на картата се поставя файл, който по същество представлява опростена файлова система (нарекох го minifs). В началото му има подпис, чрез който контролерът може да го намери при четене на сектор на карта по сектор. Ако поставите файла на ново форматирана карта, няма да има проблеми с фрагментацията - това ще бъде един цял блок данни с необходимия формат. Много е удобно - намираме първоначалното отместване от подписа и го четем подред, заобикаляйки FAT, но не и в конфликт с него.

По този начин имаме отделна файлова система за MK, която се вижда на компютъра като файл и по този начин е лесно достъпна за редактиране.

Самият файл minifs е залепен блок с данни - "вътрешни" файлове - и има формата, описан по-долу (всички отмествания, разбира се, са подравнени на границата от 512 байта, физическия размер на сектора на картите).

В самото начало на файла (отместване 0x00000000) има подпис - редът „MINIFS v1.0 FILE STARTS ТУК“:

По-горе подписът е показан в шестнадесетичен с 16-байтово подравняване. Следващите 480 байта на сектора (до границата на следващия блок от 512 байта) са запазени.

Освен това (от отместването 0x00000200) е таблица с отмествания на файлове в minifs. Състои се от четирибайтови записи. Първият запис съдържа броя на файловете в minifs, следващите показват отместванията на краищата на файловете. Тоест, вторият запис показва къде започва/завършва първият файл и т.н. Всички отмествания са подравнени с 512 байта. Максимален размер на таблицата - 512 байта.

По-нататък (при изместване 0x00000400) самите данни започват - първият файл в minifs.

Между другото, форматът minifs, както лесно можете да видите, е много подобен на FAT. Само много опростено. 🙂

Програмата mkmfs е написана за създаване на minifs. Файловете, които трябва да бъдат компресирани в minifs, му се предават в параметрите на командния ред. Смисълът на работата на mkmfs е да ги чете и последователно да ги копира във файла minifs.bin, като изчислява отместванията, описани по-горе, и ги въвежда в описаната по-горе таблица. В процеса се създава дневник. Тъй като файловете в minifs се достъпват по техния номер, това е полезно за съвпадение на имената на файловете с техните номера.

От друга страна, за контролера е написан модул (minifs.c + minifs.h), който капсулира функциите за работа с описаната структура на данните. Модулът разчита на драйвер за SD карта. Той съдържа четири функции:

MINIFS_SearchFS () трябва да бъде извикан след инициализиране на SD карта, но преди работа с minifs. Тази функция търси файла, обсъден по-горе, запомня първоначалното му отместване (minifs_root в източника), което е необходимо за всички по-нататъшни изчисления, и зарежда таблицата на отместванията. Връща нула, ако нищо не е намерено.

MINIFS_FileStartOffset ()/MINIFS_FileEndOffset () - връща съответно отместването на началото и края на блока с данни с посочения пореден номер вътре в minifs. Думата „файл“ в името на всички функции на модула се отнася конкретно до блока с данни вътре в това, което се счита за FAT файл и заедно с него на компютъра (minifs.bin). Тоест това са файловете, които прехвърлихме в mkmfs.

MINIFS_FileCount () - Връща броя на блоковете данни в minifs. По принцип той просто чете първия елемент от таблицата на отместването.

От наличните настройки, които има смисъл да се редактират, има следните:

MINIFS_TABLE_SIZE - размерът на компенсиращата таблица, т.е. максималният брой блокове данни във файла, които ще бъдат достъпни за контролера. Общо за таблицата са разпределени 512 байта, но при условия на ограничена памет размерът може да бъде ограничен, което направих тук.

Как работи всичко заедно.

Специални съображения

В статията понятието "файл" се използва по два начина - първо, като файл на самата карта и, второ, като блок данни във файла minifs.bin, който е един от файловете, обработени преди това с помощта на mkmfs.

Тестове и заключение.

Всичко беше тествано по следния начин: WAV файловете бяха взети в 16kHz/8 бита, моно формат. Техните заглавки бяха отрязани, след което получените RAW файлове бяха прехвърлени в програмата mkmfs, която ги натисна в minifs.bin. Той беше излят върху 2 GB SD карта. Последният беше свързан към контролера с фърмуера, чийто код е даден по-горе. Така всеки път, когато беше включен, се пускаше следващият файл от minifs.bin.

Можете да изтеглите проекта от тук. Схеми/оформления в DipTrace, проект за AVR Studio 4/AVR-GCC. mkmfs е конзолно приложение, написано в Code: Blocks/MinGW.