Введение
Индикаторы уровня звука, используемые в аудиоусилителях, как правило, бывают трёх типов.
Первый тип основан на нескольких (до десятка) светодиодах либо на светодиодных матрицах (до полутора десятков светодиодов), которые загораются в зависимости от уровня звука в усилителе. Преимущество таких индикаторов в их дешевизне. Их стоимость – не более 200–500 руб. Недостаток – низкая разрешающая способность: даже по полутора десяткам светодиодов об уровне звука можно судить лишь приблизительно. Кроме того, такие индикаторы имеют довольно большие габариты, в связи с чем они не всегда помещаются на лицевой поверхности корпуса усилителя, если их расположить вертикально, а горизонтальное их расположение не особенно эстетично.
Второй тип – стрелочные индикаторы. Их преимущество в том, что по отклонению стрелок можно довольно точно следить за уровнем звука. Такие индикаторы раньше часто использовались в магнитофонах, а сейчас также продолжают использоваться в усилителях в стиле «ретро» (с подсветкой с помощью миниатюрных ламп накаливания). С эстетической точки зрения такие индикаторы смотрятся довольно неплохо, однако они довольно дороги: два таких индикатора с платой сопряжения сейчас можно приобрести за 1600 руб. и выше. Кроме того, такие индикаторы также занимают довольно много места как на лицевой панели усилителя, так и внутри него из-за довольно габаритной платы сопряжения. Два таких индикатора автор использовал в усилителях, описанных в [1] (там приведена их фотография в корпусе усилителя) и [2] (фотография, к сожалению, не приведена).
Третий тип – дисплейные индикаторы. На дисплее отражаются уровни звука либо в виде гистограмм, либо даже в виде спектра. Их преимущества – небольшой размер и довольно высокое разрешение. Кроме того, они эстетически идеально смотрятся на лицевой панели корпуса усилителя. Часто такие индикаторы используют в аудиоплеерах. Однако такие индикаторы ещё дороже стрелочных: они стоят уже от 2000 руб. и выше.
В то же время подобный дисплейный индикатор, который по стоимости не будет превышать 400–500 руб., можно изготовить и своими силами. Например, стоимость дисплея OLED 1306 не более 120–130 руб., стоимость одного ОУ MCP6002 не более 40 руб. (их потребуется два) и стоимость МК EFM8LB12 не более 120–150 руб. Описание такого дисплейного индикатора и является предметом настоящей статьи.
Принципиальная схема платы индикатора
Схема устройства (рис. 1), как можно убедиться, не отличается особой сложностью.
Вкратце функционирование схемы сводится к следующему.
Два входных сигнала InA и InB поступают на входы двух относительно точных двухполупериодных выпрямителей на базе двух сдвоенных ОУ MCP6002 (DA1 и DA2). Конденсаторы CA1 и CB1, включённые в обратную связь выходных ОУ, превращают их в ФНЧ, сглаживающие выходные напряжения. Далее через RC цепочки R6AC4A и R6BC4B эти выходные напряжения поступают на два входа АЦП МК (ADCinA и ADCinB), которые измеряют эти напряжения, а результат измерений выводят на дисплей, сопряжённый с МК по высокоскоростному интерфейсу SPI.
На дисплее строятся две столбчатые гистограммы, высота которых пропорциональна входным напряжениям.
Теперь более подробно.
Рассмотрим схему на базе ОУ DA1.1, представляющую собой прецизионный однополупериодный выпрямитель. Эта прецизионность обусловлена тем, что диоды VD1A и VD2A включены в обратную связь ОУ DA1.1, за счёт чего их прямое падение напряжения снижается с 0,6 В (это стандартное падение напряжения на обычном диоде) до единиц и даже до десятых долей мВ. Снижение падения напряжения с 0,6 В до таких малых значений происходит оттого, что эти 0,6 В делятся на коэффициент усиления ОУ без обратной связи, который составляет от нескольких тысяч до десятков тысяч. Кроме того, на это снижение влияют также скоростные характеристики ОУ. Здесь необходимо добавить, что диоды должны быть именно стандартными, поскольку, например, диоды Шоттки (типа PMEG1010) существенно искажают форму выходного сигнала. В качестве диодов применены ставшие уже классическими стандартные диоды 1N4148, которые, благодаря современным технологиям, сейчас выпускаются в корпусе SOD523 и занимают место на плате, как, например, резистор в корпусе 0603.
Однополупериодный выпрямитель работает следующим образом. Если на вход ОУ DA1.1 подаётся синусоидальный сигнал InA, то при его отрицательной полуволне, т.е. когда InA < 0, за счёт того, что ОУ включён в инверсном режиме работы (InA подаётся на инвертирующий вход – на 2-й вывод DA1.1, а неинвертирующий вход заземлён), диод VD2 открывается (VD1A при этом закрыт), и выходное напряжение ОУ становится равным потенциалу «земли», т.е. равно нулю. В этом случае точка соединения анода диода VD1A и двух резисторов R2A и R4A будет также находиться под нулевым потенциалом. При положительной полуволне InA, т.е. когда InA > 0, на выходе ОУ будет отрицательный потенциал, поэтому диод VD2 закрывается, VD1 открывается, и на аноде диода VD1A будет инверсный сигнал InA, т.е. отрицательная полуволна входного напряжения. Резюме:
при положительной полуволне входного напряжения на аноде VD1 будет отрицательная полуволна входного напряжения, а при отрицательной – нулевой потенциал, или, другими словами, получаем однополупериодный выпрямитель.
Второй ОУ DA1.2 включён как суммирующий инвертирующий усилитель с точкой суммирования входного напряжения InA и напряжения на аноде VD1A, подключённой к его инвертирующему входу (6-й вывод). За счёт того, что входное напряжение InA проходит в точку суммирования через резистор R3A (5,1 К), а напряжение с анода VD1A – через резистор R4A (2,55 К), номинал которого в два раза меньше (и ток которого от этого в два раза больше), в точке суммирования это напряжение будет удвоено.
Резюме: при положительной полуволне InA в точке суммирования будет суммироваться положительная полуволна InA и удвоенная отрицательная полуволна InA, в результате чего получаем отрицательную полуволну InA; при отрицательной полуволне InA в точке суммирования будет суммироваться нулевой потенциал (от анода VD1A) и отрицательная полуволна InA (через R3A), в результате чего получаем также отрицательную полуволну InA.
Таким образом, в точке суммирования (6-й вывод DA1.2) получаем двухполупериодный выпрямитель, выходное напряжение которого будет состоять из отрицательных полуволн InA.
Коэффициент усиления Ку инвертирующего усилителя DA1.2 равен отношению номинала резистора R5A к резисторам R3A и R4A. Если бы номинал R5A был бы равен 5,1 К, то Ку = –1, и на выходе (7-й вывод DA1.2) мы бы получили двухполупериодный выпрямитель уже положительных полуволн входного сигнала InA. Такая схема хорошо известна (см., например, [3], рис. 25.10). Но, как видно из рис. 1, номинал R5A в два раза больше (10,2 К), поэтому Ку = –2, и выходное напряжение DA1.2 соответствует двухполупериодному выпрямителю с удвоенным выходным напряжением (по сравнению с амплитудой сигнала InA). Если не включать конденсатор C1A, то такой двухполупериодный выпрямитель будет идеально работать вплоть до 10 кГц, а при дальнейшем увеличении частоты форма сигнала будет уже несколько искажаться (это проверялось автором на осциллографе). Роль конденсатора C1A состоит в том, что, поскольку он включён в обратную связь ОУ DA1.2, он совместно с ОУ DA1.2 образует своего рода интегратор (или ФНЧ). Схема с таким конденсатором даже в настоящее время используется в мультиметрах или вольтметрах переменного напряжения (на рис. 25.10 в [3] такой конденсатор показан пунктиром). При номинале C1A = 4,7 мкФ ВЧ составляющая входного сигнала обрезается, другими словами, он является своего рода демпфером сродни инерционности стрелочных индикаторов уровня звука. Хотя, как будет видно из дальнейшего изложения, инерционность настоящего дисплейного индикатора уровня звука существенно ниже стрелочных.
Как было упомянуто выше, выходной сигнал с ОУ DA1.2 через RC цепочку R6AC4A подаётся на первый вход АЦП МК (ADC0.1, 24-й вывод DD1, сигнал ADCinA). Эта цепочка – необходимый стандартный атрибут, устанавливаемый перед входом АЦП.
Второй двухполупериодный выпрямитель-интегратор на ОУ DA2 устроен аналогично. Разница состоит только в том, что оба ОУ поменялись местами. Это сделано исключительно ради удобства разводки (см. далее). Его выход подключается ко второму входу АЦП МК (ADC0.2, 22-й вывод DD1, сигнал ADCinB).
Входные сигналы InA и InB (и «земля») поступают на плату соответственно с двухконтактных штыревых цанговых разъёмов PSLM-02 – XinA и XinB.
К этим разъёмам ответными разъёмами (цанговыми гнёздами SIP-2) подключаются экранированные кабели, вторые концы которых такими же гнёздами подключаются к выходным разъёмам предварительного усилителя, описанного в [2], – сигналы VoutA– и VoutB– соответственно (сигналы VoutA+ и VoutB+ используются для подключения к пик-детектору [2]).
Программирование МК осуществляется по интерфейсу C2 сигналами RST/C2CK и C2D, которые вместе с «землёй» подаются на плату с 3-штырькового разъёма XB (PLL-03). К этому разъёму ответным гнездом подключается выходной кабель от USB DEBUG –
адаптера, который сопряжён с компьютером по интерфейсу USB (подробности в [4]). RC-цепочка R1R2C1 предназначена как для программирования МК, так и для его сброса (Power On Reset) при включении питания.
Питание на плату (± 14 В и «земля») поступает с 3-штырькового разъёма PSLM-03 (XП). К этому разъёму ответным гнездом подключается 3-проводный кабель, который своим вторым концом подключается к соответствующим напряжениям усилителя, описанного в [2].
Для получения стабилизированного напряжения +3 В используется стабилизатор 78L03 (DA3), для получения отрицательного напряжения – стабилизатор LM337 (DA4). Как известно, его выходное напряжение зависит от соотношения резисторов RP1 и RP2 и внутреннего опорного напряжения:
–Uвых = –1,25 В (1+RP2/RP1) = –1,25 В × (1 + 332 Ом/237 Ом) = –3,001 В » –3 В. При этом номинал RP1 не должен превышать 240 Ом.
Сопряжение МК с дисплеем OLED1306 организовано по интерфейсу SPI с помощью сигналов MOSI и SCK, помимо которых в дисплей также передаются сигналы RES, D/C и CS. Все дисплейные сигналы (вместе с питанием и «землёй») поступают на 7-штырьковый разъём PLS-07 (XOK). Этот разъём вставляется в ответный разъём PLSF-07 (XO), распаянный на плате дисплея.
Конденсаторы C2A, C3A, C2B, C3B, C2, C3, CP1–CP4 – блокировочные.
Все резисторы и конденсаторы (кроме CP1 и CP3) – для поверхностного монтажа размером 0603, CP1 и CP3 размером 0805. Все конденсаторы рассчитаны на напряжение 50 В. Все резисторы должны иметь допуск не более 1%.
ОУ MCP6002 (точное название TPMCP6002T-I/MS) – в корпусе MSOP-8, МК – в корпусе QFN24, стабилизаторы в корпусе TO-92, диоды (точное название 1N4148X) – в корпусе SOD523.
Разводка и внешний вид платы
Разводка платы (рис. 2а, б) сделана автором с помощью программы SprintLayOut v.6.0. В переходные отверстия, отмеченные чёрными кружками на рис. 2а, необходимо вставить тонкий (0,2–0,3 мм) лужёный медный провод и пропаять его с двух сторон платы. Все разъёмы и выводы стабилизаторов, для которых предусмотрены контактные площадки на обратной стороне платы, также пропаиваются с двух сторон платы. Плата (рис. 2г, д) изготовлена из двустороннего фольгированного стеклотекстолита толщиной 1,5 мм. Укрупнённый вид МК (рис. 2в) показан для его сравнения с корпусом МК, полученным в программных средствах при инициализации устройств (см. далее).
Программные средства
Программирование МК проводилось в среде Simplisity Studio v.4.0 на языке C51 (Keil 8051 v.9.54.0).
В общем меню настроек (рис. 3) необходимо выбрать только те устройства, которые отмечены галочками.
Перед тем как настраивать АЦП (рис. 4а), отмеченный галочкой в самом верху слева общего меню (рис. 3), необходимо настроить внутренний генератор на частоту 72 МГц (рис. 4б), выбрать системную тактовую частоту, соответствующую частоте этого генератора (рис. 4в), и указать, что чтение памяти необходимо производить при частоте менее 75 МГц (рис. 4г).
В настройках АЦП (рис. 4а) необходимо обратить внимание, что используется внутренний источник опорного напряжения 1,65 В. Коэффициент усиления внутреннего ОУ перед АЦП установить на значение 0,75, чтобы максимальное входное напряжение составило 2,2 В. Также выбрать первый вход АЦП как ADC0.1 (P0.2), указать, что аналоговая «земля» подаётся в АЦП с P0.1/AGND pin, установить делитель системной тактовой частоты на 4 и таким образом тактировать АЦП частотой 18 МГц. В этом случае общее время аналого-цифрового преобразования составит 1,167 мкс.
В настройках интерфейса SPI (рис. 4д) необходимо разрешить SPI (Enabled), выбрать коэффициент деления тактовой частоты равным 2, что даёт частоту тактового сигнала SCK равной 12 МГц, и выбрать 3-проводный режим master. Кроме того, необходимо поставить галочку в поле Clock/Data, чтобы сигналы SPI выводились в соответствующие порты МК.
Далее, чтобы вся конструкция работала, необходимо разрешить матрицу соединений (рис. 4е).
В остальных трёх опциях, отмеченных галочками, установить следующие настройки: Interrupts – запретить, Voltage Regulator – разрешить и Watchdog Timer – запретить.
После этого необходимо переключиться в режим Default Mode Port I/O, в результате чего на экран выведется корпус МК со всеми портами (рис. 4ж). Прежде всего, необходимо с помощью команд skip, которые отмечены красными крестиками, передвинуть сигналы SPI в нижнюю часть корпуса, чтобы их можно было легко соединить с разъёмом OLED-дисплея (см. рис. 2в).
Порты P0.1 (аналоговая «земля»), P0.2 (аналоговый вход 1-го канала, ADC0.1) и P0.4 (аналоговый вход 2-го канала, ADC0.2) настроить как аналоговые входы/выходы – Analog I/O (пример – рис. 4з). Порты сопряжения МК с дисплеем (см. также рис. 2в): P2.2 (MOSI), P2.0 (SCK), P1.6 (RES), P1.5 (D/C) и P1.4 (CS) настроить как цифровые выходы – Digital Push-Pull Output (пример – рис. 4и). Порты P2.1 (MISO) и все остальные неиспользуемые порты настроить как цифровые входы – Digital OpenDrain I/O (пример – рис. 4к).
После того как все настройки сделаны, необходимо нажать на кнопку двойной дискеты в верхней левой области экрана, чтобы записать всю конфигурацию на диск. При этом на C51 автоматически сгенерируется файл подпрограммы инициализации устройств InitDevice.c, которая подключится к основной программе, т.е. в самом начале основной программы (Main) будет обращение к подпрограмме InitDevice.c: enter_DefaultMode_from_RESET();.
Теперь по поводу самих подпрограмм.
Таких подпрограмм три.
Первая – инициализация и очистка дисплея. Поскольку об этом подробно описано в [5], чтобы не повторяться, эта подпрограмма не приводится.
Вторая – подпрограмма аналого-цифрового преобразования.
Эта подпрограмма uint16_t ACP(uint8_t NK) организована в виде функции, аргументом которой является номер канала (1 или 2), АЦП которого необходимо произвести, а полученный результат – это 16-разрядное (uint16_t ) значение самой функции. Вначале подпрограмма выясняет, какой канал необходимо подключить, и устанавливает значение мультиплексора на данный канал, а затем производит 8-кратное измерение напряжения по этому каналу и осредняет его. Далее, поскольку в качестве опорного напряжения используется внутренний источник опорного напряжения 1,65 В и коэффициент усиления внутреннего ОУ, равный 0,75 (см. рис. 4а), результат умножается на 2200 мВ (= 1,65 В/0,75) и делится на 16 383 (2
14 – 1), так как разрядность АЦП – 14 бит. С погрешностью в 1 бит в качестве делителя можно использовать число 16 384 (2
14), или, другими словами, вместо деления, которое производится достаточно долго, можно использовать простой сдвиг результата на 14 разрядов вправо. Обращение к этой подпрограмме очень простое. Например, чтобы измерить напряжение первого канала U1, необходимо написать: U1 = ACP(1); (см. далее).
Для приблизительной оценки времени аналого-цифрового преобразования двух каналов, с учётом 8-кратного измерения по каждому каналу, необходимо учесть, что максимальное время одного АЦП составляет 1,167 мкс (см. рис. 4а). Умножив это время на 8 и учитывая, что каналов 2, получим: Т
АЦП = 1,167 мкс × 8 × 2 = 18,672 мкс ≈ 20 мкс.
Подпрограмма с комментариями приведена в листинге 1. Эта подпрограмма взята из одного из примеров работы с АЦП в Simplisity Studio, поэтому некоторые комментарии оставлены в оригинальном виде.
Листинг 1. Подпрограмма для работы с АЦП
//-----------------------------------
uint16_t ACP(uint8_t NK) {
uint32_t accumulator = 0; // accumulator for averaging
uint32_t result, mV; // mV - measured voltage in mV
uint16_t rez;
uint8_t measurements; // = 8 measurement counter
ADC0MX = (NK == 1) ? ADC0MX_ADC0MX__ADC0P1 : ADC0MX_ADC0MX__ADC0P2;
//NK=1/2 => ADC0MX=ADC0MX_ADC0MX__ADC0P1/ADC0MX_ADC0MX__ADC0P2
for (measurements = 0; measurements < 8; measurements++) {
ADC0CN0_ADINT = 0; // clear ADC0 conv. complete flag
ADC0CN0_ADBUSY = 1; // Start a conversion by setting ADBUSY
while (!ADC0CN0_ADINT); // wait conversionComplete
accumulator += ADC0; // DATA 0BDH ; ADC0 Data Word
}
//result = accumulator / 8;
result = accumulator >> 3;
// Vref (mV)/gain(=0,75)
// measurement (mV) = ------------------------ * result (bits)
// (2^14)-1 (bits)
// Vref = 1,65 V = 1650 mV
// 1650 mV / 0,75 = 2200 mV
// (2^14)-1 = 16384-1=16383
mV = (result * 2200) >> 14;
//mV = (result * 2200)/16383;
rez = mV;
return (rez);
}
//-----------------------------------
Третья подпрограмма – вывод гистограммы на дисплей. Но прежде чем её описывать, сделаем некоторое отступление.
Дисплей OLED 1306 состоит из 8 строк по 8 пикселей по вертикали в каждой строке. Верхние две строки имеют жёлтый цвет, остальные – синий. Количество столбцов в дисплее 128.
Имеет смысл синий цвет (6 нижних строк) использовать как нормальный режим работы, т.е. когда уровень звука не выходит за предел, в котором могут возникнуть искажения, а жёлтый цвет – как начало режима, в котором уровень звука находится выше этого предела. Чтобы соотношение уровня звука выше предела и нормального режима было наиболее реальным, для жёлтого цвета желательно использовать всего одну строку, т.е. отношение количества пикселей жёлтого цвета и количества пикселей нормального режима составляло 1/7, или, другими словами, использовать 7 строк, а 8-ю строку не использовать.
Поскольку максимальное напряжение, подаваемое на АЦП, составляет 2200 мВ (см. выше), имеет смысл оценить, каким образом строить столбец, высота которого пропорциональна входному напряжению. Максимальная высота столбца составляет 7 строк × 8 пикселей = 56 пикселей. То есть 56 пикселей должны отображать 2200 мВ. Если разделить 2200 мВ на 56 пикселей, получим: 2200 мВ / 56 = 39, 27 мВ » 40 мВ. Если принять, что 40 мВ составляет 1 пиксель, то получим, что дисплей может отражать: 40 мВ × 56 пикселей = 2240 мВ, что даже чуть больше, чем 2200 мВ, или, другими словами, область отображения напряжения на дисплее чуть больше реального напряжения. Поскольку каждая строка состоит из 8 пикселей, имеет смысл выяснить, какому напряжению соответствует каждая строка. Для этого умножим 40 мВ на 8 пикселей и получим: 40 мВ × 8 пикселей = 320 мВ. Поскольку 7-я строка жёлтого цвета отражает режим работы выше предела, в котором могут возникнуть искажения, порог начала такого режима будет составлять: 6 строк × 320 мВ = 1920 мВ. Учитывая, что Ку ОУ DA1 и DA2 составляет 2, реальное напряжение порога будет составлять: 1920 мВ / 2 = 960 мВ = 0,96 В, т.е. почти такому же значению (0,95 В), которое использовалось в пик-детекторе, описанном в [2].
Таким образом, получаем следующий алгоритм получения высоты столбца для вывода на экран дисплея.
Выясняем, сколько целых строк, например, переменная c содержит, если входное напряжение равно UL, для чего его необходимо разделить на 320: с = = UL/320. В эти (нижние) строки необходимо выводить байт 0xff, т.е. полностью их закрашивать. Далее необходимо выяснить, сколько пикселей потребуется вывести в верхнюю строку, или, другими словами, чему должно равняться значение самого верхнего байта. Для этого нужно получить остаток ost от деления (ost = UL % 320) и разделить его на 40 мВ, т.е. получить целую часть остатка (c_ost = ost/40). Необходимо отметить, что всё деление производится в целых числах. Для получения значения самого верхнего байта (byte_verh) количество его младших бит, которые соответствуют пикселям, должно равняться числу остатка c_ost. Если, например, c_ost = 3, то значение byte_verh = = 00000111, при c_ost = 5 byte_verh = 00011111 и т.п. Каким образом это получить? Самый простой путь – написать 7 операторов if, в которых перечислить все комбинации. Но такой путь, во-первых, очень долгий и, во-вторых, займёт много места в программе. Однако можно поступить следующим простым способом. Если взять байт со всеми единицами 11111111
2 = 0xff и сдвинуть его влево на число остатка, т.е. если, например, c_ost = 3, то при таком сдвиге правые три бита обнулятся: 11111000
2. Если теперь инвертировать все биты полученного числа, то получим 00000111, т.е. то, что требуется. Оператор инверсии всех бит числа (~), как правило, называют двоичным дополнением или, реже, инверсией. Таким образом, получаем следующее выражение для верхнего байта: byte_verh = ~(0xff << c_ost). Для вывода столбца предусмотрен массив с 8-ю элементами ML[8], в который и будут выводиться данные.
Исходя из количества столбцов в дисплее (128), имеет смысл количество столбцов для каждой гистограммы принять равным 20, или, другими словами, ширину гистограммы принять равной 20 пикселям, и две гистограммы расположить на некотором расстоянии друг от друга. Например, гистограмму левого канала выводить с 90 по 110-й столбец, а правого – с 20 по 40-й.
Подпрограмма вывода гистограммы outUL(uint16_t UL,uint8_t NK) также оформлена в виде функции, аргументами которой являются входное напряжение (UL) и номер канала АЦП (NK). Для обращения к ней необходимо указать напряжение (например, U1) и номер канала (например, 1). Например, для вывода гистограммы левого канала необходимо написать: outUL(U1,1).
Подпрограмма с комментариями приведена в листинге 2, и, учитывая предыдущее объяснение, её несложно понять.
Листинг 2. Подпрограмма вывода гистограммы
//-----------------------------------
u//---------------------------------
void outUL(uint16_t UL,uint8_t NK) { //UL - показание АЦП в мВ
uint8_t c, c_ost, byte_verh,NA,KA;
uint16_t ost;
c = UL / 320; //целая часть
ost = UL % 320; //остаток
c_ost = ost / 40; //
// byte_verh=0xff-(0xff << c_ost);
byte_verh = ~(0xff << c_ost); //»~» - побитовое дополнение/инверсия всех бит
for (k = 0; k < c; k++) {
ML[k] = 0xff; //закраска синим нижних строк
}
ML[c] = byte_verh; // верхний байт
if (c < 6) {
for (k = c + 1; k < 7; k++) {
ML[k] = 0x00; //закраска черным верхних строк
}
}
if (NK==1){
NA=90;//левый канал
KA=110; }
else {
NA=20;//правый канал
KA=40; }
//---------------------------------
//вывод массива на экран
//---------------------------
CS = 1;
//-----------------------
// Построение гистограммы
//----------------------
outcmd(0x21); // Установка столбца
outcmd(NA); // Начальный адрес
outcmd(KA); // Конечный адрес
outcmd(0x22); // Установка строки
outcmd(0); // Начальный адрес
outcmd(6); // Конечный адрес
DC = 1; //Данные
CS = 0;
for (l = 0; l < 20; l++) { // 20 столбцов
for (k = 0; k < 7; k++) { // 7 строк
outspi(ML[k]); // Закраска
}
}
CS = 1;
} // конец п/п
//----------------------------
Оценим время работы этой подпрограммы. Скорость работы интерфейса SPI – около 12 Мбод (см. рис. 4е), или 12 000 000 бод / 8 = 1 500 000 байт/с. Учитывая, что каждая гистограмма состоит из 20 столбцов по 7 байт каждый, получим, что для вывода одной гистограммы потребуется вывести 7 × 20 байт = 140 байт, а для двух, соответственно, – 280 байт. Разделив 280 байт на 1 500 000 байт/с, получим 186 мкс ≈ 200 мкс. Таким образом, время вывода на дисплей примерно в 10 раз больше времени работы АЦП (20 мкс – см. выше). Общее время вывода двух гистограмм с учётом АЦП составит около 240 мкс. Частота обновления экрана дисплея составит 1/240 мкс = 1/0,24 мс = 4,167 кГц, т.е. чуть более 4 кГц.
Это более чем на порядок быстрее обновления экрана телевизора (100–200 Гц).
В качестве дисплея можно использовать и более медленный, цветной 0,96″ TFT-дисплей с IPS-матрицей.
В этом дисплее вместо вывода одного бита, определяющего цвет (как в OLED 1306), требуется вывести 2 байта цвета (16 бит), т.е. он в 16 раз медленнее OLED 1306. Но даже в этом случае его частота обновления экрана составит 4000 Гц / 16 = 250 Гц, хотя эта частота может быть незначительно снижена, поскольку из-за чуть большего разрешения этого дисплея по сравнению с OLED 1306 (80×160 пикселей против 64×128 в OLED 1306) придётся выводить бо́льшее количество пикселей (байт), правда, ненамного. Можно предположить, что частота обновления экрана будет всё равно больше частоты обновления экрана телевизора. Этот дисплей полноцветный (а не двухцветный, как OLED 1306). В связи с этим в качестве цвета гистограмм в нормальном режиме работы можно использовать зелёный цвет, а в режиме перегрузки, т.е. превышения порога, когда могут возникнуть искажения, – красный, что намного эстетичней, чем соответственно синий и жёлтый цвета в OLED 1306.
С учётом предыдущих подпрограмм основная программа очень проста и приведена в листинге 3. Она измеряет напряжение каждого канала и выводит на дисплей обе гистограммы. Как можно заметить, программа зациклена (её последний оператор goto A).
Листинг 3. Основная программа
//-----------------------------------
u//----------------------------
// main() Routine
// ---------------------------
int main(void) {
// Call hardware initialization routine
enter_DefaultMode_from_RESET();
//------------------
CLS(); // Инициализация ЖКИ
CS = 1;
//----------------------------
A:
U1 = ACP(1);
DEL2US();
U2 = ACP(2);
U1 = U1 * 3;//2-Ку ИУ;2-Ку ОУ выпрямителя(10,2К);0,75-Ку АЦП МК
U2 = U2 * 3;//2*2*0,75=3.
outUL(U1,1);// левый канал
outUL(U2,2);// правый канал
goto A;
}
После трансляции всей программы в среде Simplisity Studio внизу экрана появляется следующее сообщение:
Program Size: data=64.1 xdata=0 const=0 code=1105
LX51 RUN COMPLETE. 0 WARNING(S), 0 ERROR(S)
Finished building target: EFM8LB12F64E-C-QFN24_6.omf
Из этого сообщения следует, что программа использует около половины (всего 64 байта) внутренней оперативной памяти с прямой адресацией (data = 64.1), размер которой 128 байт, внешняя дополнительная оперативная память с косвенной адресацией размером 4096 байт не используется вообще (xdata = 0), размер кодовой части программы составляет 1105 байт (code = 1105), т.е. чуть более 1 кбайт, что соответствует около 1/64 от максимального размера программной памяти для этого МК, равного 64 кбайт. В связи с этим в качестве МК могут использоваться МК EFM8LB11F16 или EFM8LB10F16 (они дешевле EFM8LB12F64) с программной памятью 16 кбайт. Программа использует так называемую small model, где все данные располагаются в памяти с прямой адресацией (data), и которая работает наиболее быстро.
Программа в уже готовом загрузочном *.hex-формате (EFM8LB12F64E-C-QFN24_6.hex) приведена в дополнительных материалах к статье на сайте журнала.
Конструкция и результаты работы устройства
К плате дисплея по углам, где расположены крепёжные отверстия, эпоксидной смолой приклеены 4 квадратные пластиковые пластины размером 4×4×2 мм (рис. 5). Чтобы отражающая поверхность дисплея не касалась поверхности корпуса усилителя, толщина пластины выбрана чуть больше (на 0,2–0,3 мм) расстояния от поверхности платы дисплея до верхней поверхности самого дисплея. Эти пластины, в свою очередь, приклеены к обратной стороне лицевой панели корпуса усилителя, в которой прорезано окно по размеру поверхности дисплея, на которой расположены все пиксели. В качестве клея автор использовал дихлорметан (можно использовать любой другой клей, растворяющий пластик). Плата устройства просто вставлена своими контактами в соответствующие контакты платы дисплея и на них достаточно прочно держится. Кабели питания и входных сигналов вставлены в соответствующие контакты платы устройства.
По общему виду лицевой поверхности корпуса работающего усилителя (рис. 6) о реальной работе устройства можно судить только косвенно по фотографии, т.е. в статике. Поэтому для того, чтобы реально убедиться в работе устройства, в дополнительных материалах к статье приведены два 15-секундных видеофайла (Old brown shue.mov и It’s probable me.mov) и один 9-секундный (PICT0003.mov), снятые при работе усилителя, когда к нему был подключён телефон, который воспроизводил реальные звуковые *.mp3 файлы. При этом регулятор громкости на усилителе и движок громкости на телефоне были установлены на максимум. Первые два файла – Old brown shue.mp3 и It’s probable me.mp3 – имеют мировую известность, и представлять их нет необходимости. Третий видеофайл (PICT0003.mov) получен, когда напряжения U1 и U2 умножаются не на 3 (см. последнюю программу), а на 4. В этом случае реальные напряжения, отражающиеся на дисплее в виде гистограмм, не совсем соответствуют действительности, однако их повышенное значение позволяет оценить весь диапазон изменения высоты гистограмм (на них можно заметить много моментов, когда высота гистограмм зашкаливает, и на них появляется верхняя область жёлтого цвета). Поскольку аппарат, на который снимались видеофайлы, не пишет звук, все *.mov-файлы беззвучные.
Заключение
Применение МК EFM8LB12, двух ОУ MCP6002 и дисплея OLED 1306 позволило сконструировать малогабаритный и малоинерционный индикатор уровня звука, который показал отличную работу в составе аудиоусилителя. По стоимости он в несколько раз меньше аналогичных готовых покупных устройств. Автор рекомендует его для повторения.
Литература
- Кузьминов А. Применение инструментального усилителя в усилителе низкой частоты // Современная электроника. 2016. № 6.
-
Кузьминов А. Усовершенствованный УМЗЧ на базе ИУ и мощных ОУ // Современная электроника. 2019. № 5.
-
Титце У., Шенк К. Полупроводниковая схемотехника: справочное руководство. М.: Мир, 1982.
-
Кузьминов А.Ю. Связь между компьютером и микроконтроллером. Современные аппаратные и программные средства. М.: Перо, 2018.
-
Кузьминов А. НЧ генератор синусоидальных сигналов на базе синтезатора частоты AD9833, микроконтроллера EFM8SB10 и 0.91″ дисплея OLED-1306 с батарейным питанием // Современная электроника. 2024. № 2.
© СТА-ПРЕСС, 2024