едь какой-то из транзисторов пары всегда заперт, а второй транзистор в это время полностью открыт и мощности на них не выделяется. Это, конечно, в теории, потому что из главы 3 вы знаете, что падение напряжения на открытом транзисторе все же имеет место, да и переключение не происходит мгновенно. Но вопросы КПД нас тут не интересуют, т. к. мы не собираемся конструировать 100-ваттные усилители, и указанная схема нас привлекает не столько КПД, сколько простотой и компактностью.
Представление синусоидального сигнала в виде последовательности импульсов различной длительности называется ШИМ-модуляцией (по-английски, PWM — Pulse-Wide Modulation). Фокус заключается в том, что для извлечения исходного синусоидального сигнала из ШИМ не требуется никаких специальных сложных приборов — достаточно обычного резисторно-конденсаторного ФНЧ с подходящей частотой среза (о ФНЧ см. главу 2). В результате весь звуковой тракт упрощается до предела (рис. 19.1).
Рис. 19.1.Принцип работы выходной части усилителя в режиме D
Заметки на полях
А как сформировать входной сигнал для такого усилителя, если у нас в наличии имеется лишь аналоговая звуковая волна? Нужно ли ее оцифровывать? Совсем нет: исходный аналоговый сигнал поступает на один вход компаратора, а на второй его вход подается напряжение треугольной формы и подходящей амплитуды. Тогда на выходе компаратора мы получим ШИМ-сигнал. Работа счетчика-таймера, показанная на рис. 19.2 далее, делает в точности то же самое, но в цифровой форме.
Для того чтобы получить ШИМ-сигнал из уже оцифрованного звука, у нас есть такая «штука», как микроконтроллер, причем уже специально приспособленный для подобных целей. Если вы уже имеете книгу [1] или [2], или скачивали фирменный PDF-документ с описанием какого-то из контроллеров AVR, и при этом ваше любопытство зашло столь далеко, что вы эти источники даже немного пролистали, то, несомненно, заметили, что в описаниях таймеров PWM-режиму уделяется довольно много места — больше, чем всем остальным режимам вместе взятым. Это потому, что PWM-режим сложнее простого счета. Но на самом деле идея, которая в него заложена, очень проста: мы загружаем в регистр сравнения очередное число, взятое из звуковой последовательности, и запускаем таймер на счет с нуля, а когда он дойдет до верхнего предела, то сразу реверсируется и начинает считать обратно до нуля. В контроллерах Tuny вместо реверсирования счетчик сбрасывают и начинают отсчет заново. В семействе Mega для формирования сигнала PWM есть и тот, и другой и еще некоторые режимы работы таймеров (например, с переменным битрейтом).
В момент, когда числа в счетчике таймера и в регистре сравнения равны между собой, в режиме PWM автоматически переключается знакомый нам выход, связанный с выбранным таймером (в главе 14 это был выход ОС1, который управлял миганием двоеточия). Только в данном случае он не переключается туда-сюда с каждым прерыванием от таймера, а находится в состоянии логического нуля, когда число в таймере больше, чем в регистре сравнения, и в состоянии логической единицы — когда меньше. В результате на один цикл счета «туда-обратно» мы получаем один период ШИМ-сигнала, в котором длительность состояния логической единицы строго пропорциональна числу в регистре сравнения. Меняя к следующему циклу это число на очередную выборку из звуковой последовательности, мы в результате получаем то, что требовалось: входной импульсный сигнал для усилителя в режиме D. Общая схема процесса показана на рис. 19.2 (на примере с использованием Timer 1). Кстати, отметим, что этот режим может применяться также, например, просто для формирования сигнала с определенной скважностью, не равной двум.
Рис. 19.2. Принцип работы счетчика-таймера в режиме PWM
Теперь надо понять, какие характеристики исходного оцифрованного сигнала нам нужны и какие параметры таймера необходимо устанавливать. Хотя мы будем использовать Timer 1, но задействовать все 16 разрядов в таком режиме он не может (счет в реверсивном режиме возможен максимум с 10 разрядами, а использовать режимы с переменной разрядностью мы не будем). Нам же будет достаточно и 8 — это означает, что глубина квантования исходного звука должна быть также 8 разрядов. Баха не очень сыграешь, но для передачи разборчивой речи достаточно.
Теперь разберемся с частотой оцифровки. Тактовую частоту МК для такой схемы лучше выбирать максимально возможной, для большинства AVR это 16 МГц (чтобы еще повысить качество звука, можно специально взять модель 2313, у которой максимальная частота 20 МГц, но мы будем ориентироваться на 16 МГц). Легко подсчитать, что реверсивный 8-разрядный счетчик будет считать туда и обратно с частотой fтакт/510, т. е. при такой тактовой частоте получится около 32 кГц. Это и будет несущая частота fоп на выходе ШИМ, что удовлетворительно, т. к. она выходит за пределы слышимого диапазона. Однако требуемая частота оцифровки исходного звука может быть все же заметно ниже (что удобно в целях экономии памяти). Пусть она составляет 4 кГц (это может возмутить аудиофилов, но для передачи речи это нормальный показатель).
Тогда можно сразу выбрать характеристики RC-фильтра: чтобы отфильтровать 32 кГц простой RC-цепочкой, нам желательно, чтобы частота среза не превышала частоту оцифровки, т. е. 4 кГц. Тогда 32 кГц затухнут в 8 раз по сравнению с верхней частотой диапазона оцифровки, и мы их влияние не почувствуем. Параметры фильтра рассчитываются по формуле fcp = 1/2πRС, и нашим требованиям удовлетворяют параметры R = 10 кОм и С = 3,9 нФ.
Для хранения звука используем память с I2С-интерфейсом АТ24С512. Одному отсчету тут будет соответствовать ровно один байт, одной секунде звучания — 4 кбайт. Итого 65 536 байт дадут нам около 16 с звучания. Этого достаточно, чтобы произнести стандартную предвыборную речь кандидата в президенты, если предварительно ее отредактировать и выбросить все фразы, не несущие смысловой нагрузки.
Все параметры схемы мы рассчитали, можно приступать к проектированию. В качестве звукового усилителя возьмем описанный в главе 6 микроусилитель МС34119. Выбор усилителя не имеет большого значения, но данная микросхема «умеет» работать с однополярным напряжением 5 В и это удобно. Общая схема соединений показана на рис. 19.3. Полную схему включения МС34119 см. на рис. 6.15.
Рис. 19.3.Принципиальная схема для использования AVR в режиме голосовой сигнализации
Программа для вывода звука
Здесь мы для простоты выберем АТ9 °C8515 семейства Classic (а точнее, ATmega8515 в режиме совместимости с АТ9 °C8515, потому что оригинал может работать максимум на 8 МГц тактовой частоты, а мы рассчитывали на 16 МГц). Это проще для нашего рассмотрения, поскольку в семействе Classic имеется лишь один режим PWM для таймеров, а в Mega их много и это лишь путает. В крайнем случае, разобраться в том, как дополнить программу выбором нужного нам в данном случае режима Phase Correct PWM вы сможете самостоятельно. Для работы с интерфейсом I2С в программе используется тот же самый, что и в главе 16, включаемый файл i2c.prg (см. Приложение 5, листинг П5.3).
В целях компактности из него можно для данного случая удалить процедуры, относящиеся к RTC (write_i2c и read_i2c), но будьте осторожны, чтобы не удалить что-то нужное. Кроме того, следует обратить внимание на величину задержки в процедуре delay — там у нас установлена величина 5 мкс в расчете на 4 МГц. При 16 МГц задержка укоротится вчетверо, и память будет работать на пределе (400 кГц), что не очень хорошо. Хотя обычно (если линия передачи не слишком длинная) память справляется, но помнить об этом параметре в случае возникновения каких-то сбоев следует. Но и снижать скорость шины до тех величин, что у нас были в измерителе не следует, т. к. чтение может не успеть за битрейтом (см. далее).
Программа для данного случая содержится в листинге 19.1.
Листинг 19.1
/==== программа вывода цифрового звука ====
;процессор mеgа8515 в режиме 8515, частота 16 МГц
.include "853 5def.inc"
.equ T_Sample = 193 ;предварительное значение для Timer 0 при 4 кГц
.equ bSample = 0 ;бит готовности к чтению
;регистры temp и DATA определены в "I2С.рrg" (Приложение 5)
.def FLAGS = r19
; прерывания
rjmp RESET ;начальный загрузчик
reti
reti
reti
reti
reti
reti
rjmp TIMO ;обработчик прерывания переполнения Timer 0
reti
reti
reti
reti
.include "I2C.prg"
RESET:
ldi temp,0b00100000
out DDRD,temp ;ОС1А — на выход
ldi temp,(1<
out TCCR1A,temp
ldi temp,1<
out TCCR1B,temp
ldi temp,(1<
out TCCR0,temp
out TCNT0,T_Sample ;T_Sample=6, заряжаем таймер 0 на 4 кГц
ldi temp,(1<
out TIMSK,temp
clr temp ;очищаем все регистры
out OCR1AH,temp
out OCR1AL,temp
out OCR1BH,temp
out OCR1BL,temp
ldi XH,high(Nbytes)
ldi XL,low(Nbytes) ;зарядка счетчика выводимых байт
;вместо Nbytes подставить объем записи в байтах, не более 64К
ldi YH,high(ADrWord)
ldi YL,low(ADrWord)