Доработка генератора на PIC16F84A и AD9850


И.Нечаев, г.Курск, А.Долгий, г.Москва

Микросхема прямого синтеза частоты, управляемая микроконтроллером, обеспечивает уникальные параметры измерительного генератора: высокую "кварцевую" стабильность частоты в сочетании с легкостью ее перестройки и установки с клавиатуры. Однако в устройстве, описанном в статье С. Кулешова "Генератор на PIC16F84A и AD9850" в "Радио", 2004, № 3, с. 26—29, не реализованы потенциальные возможности примененных микросхем. В технических характеристиках заявлена точность установки частоты 1 Гц. Но на практике частота выходного сигнала может отличаться от набранной с клавиатуры и показанной индикатором на 0,1...0,6 %, что существенно затрудняет использование генератора. В предлагаемой вниманию читателя подборке предложены два принципиально разных способа устранения этого недостатка, а также другие усовершенствования генератора.

Устранение недостатка генератора без модификации программы микроконтроллера предложил И. Нечаев из г. Курска. Выходная частота генератора tout определяется формулой fout = d-fin/232, где d — код частоты, подаваемый на микросхему синтезатора AD9850; fln — частота кварцевого тактового генератора G1 на рис. 2 исходной статьи. Полагая, что выходная частота должна быть равна значению fneed, введенному с клавиатуры и отображаемому индикатором, имеем формулу для вычисления кода частоты

d = 232fneed/fin=K.fneed,

где К=2 /fin — постоянный коэффициент, на который нужно умножить требуемое значение частоты, чтобы получить ее код.

В исходном устройстве коэффициент К вычисляется целочисленно, в результате чего и образуется погрешность. Если частота тактового генератора равна 100 МГц, коэффициент К должен быть равен 232/ЮЙ = 42,94967296, но в программе он округлен до значения 43, что приводит к пропорциональному повышению частоты генерации на 0,12 %. Например, при необходимой частоте 10 МГц выходная частота будет равна 43-107/42,94967296 = 10011717 Гц.

Такая досадная погрешность существенно снижает эффективность этого генератора и усложняет пользование им, что может оказаться неприятным сюрпризом для тех, кто его уже собрал, так как в описании указана точность установки частоты 1 Гц.

Выходом из этой ситуации может быть изменение частоты кварцевого генератора так, чтобы обеспечить целое значение коэффициента К. Например, для К, равного 43, частота тактового сигнала должна быть 232/43 = 99882960 Гц.

После установки генератора тактового сигнала с этой частотой выходная частота генератора стала соответствовать значению, введенному с клавиатуры и отображаемому индикатором, во всем диапазоне рабочих частот. Аналогично можно скорректировать и другие значения частоты тактового генератора.

dds_9850_dop-1
Рис. 1

В порядке дальнейшего совершенствования устройства в него добавлены дополнительные фильтры и генератор модулирующего сигнала. Изменения в схеме показаны на рис. 1, на котором нумерация элементов продолжена по отношению к рис. 2 исходной статьи. Добавлен функциональный генератор ЗЧ на микросхеме DD3. Он вырабатывает напряжение прямоугольной, треугольной и синусоидальной формы. Сигнал с одного из выходов этого генератора через переключатель SA1.2 и конденсатор С21 поступает на вывод 12 микросхемы AD9850 (DD2). Напряжение на этом выводе определяет ток выходного ЦАП и, следовательно, амплитуду выходного сигнала синтезатора. Постоянный резистор R11, ранее соединенный с этим выводом, удален. С помощью подстроечного резистора R26 эту регулировку можно осуществлять плавно.

Переключателем SA1 (4П2Н) включают генератор ЗЧ и выбирают форму модулирующего сигнала. Необходимую глубину модуляции для каждой формы устанавливают подбором резисторов R22, R24, R25. Подстроечным резистором R21 устанавливают на выходе элемента DD3.3 форму колебаний, близкую к синусоидальной, с амплитудой несколько сотен милливольт.

Так как микросхема AD9850 имеет два равнозначных выхода, в устройстве реализованы два выхода: низкочастотный — 1 Гц... 100 кГц и высокочастотный — от 100 кГц и выше. На каждом выходе установлены соответствующие фильтры: L3L4C9—С11 с частотой среза 100 кГц и L5—L8C12—С16 с частотой среза 33 МГц, имеющий затухание свыше 60 дБ на частотах больше 55 МГц.

Дроссели L3 и L4 — ДМ-0,1 индуктивностью 100 мкГн или аналогичные импортные ЕС24, можно применить дроссели для поверхностного монтажа. Катушки L5—L8 содержат по 13 витков провода ПЭВ-2 0,3, намотанного на оправке диаметром 4 мм. Все конденсаторы — К10-17 или аналогичные импортные.

* * *

Наиболее общий способ устранения недостатка генератора независимо от его тактовой частоты — совершенствование программы микроконтроллера — предложил А. Долгий из г. Москвы. Систематическая погрешность частоты сигнала, генерируемого микросхемой прямого цифрового синтеза (DDS) AD9860, достигает 0,58 % при тактовой частоте 60 МГц. Конечно, генератор, работающий с такой точностью, для практического применения не годится, необходимо найти и устранить причину его неправильной работы. Первое, что показала проверка, — микросхема DDS не виновата. Она старательно исполняет подаваемые микроконтроллером ошибочные команды.

Следующим шагом стал анализ программы микроконтроллера. Выяснилось, что набранное на клавиатуре значение частоты хранится в виде набора десятичных цифр — каждая в отдельном регистре. Программа преобразует десятичное число в 32-разрядный двоичный эквивалент и, умножив его на коэффициент К, получает код частоты для загрузки в микросхему DDS.

dds_9850_dop-1

Казалось бы, все правильно. Но беда в том, что вместо точного значения коэффициента, равного 232До, где f0 — частота кварцевого генератора, Гц, программа использует округленное до ближайшего целого. Для f0 = 60 МГц коэффициент К принят равным 72 вместо 71,582788, а для f0= 100 МГц — 43 вместо 42,949673. Это и приводит к описанной выше погрешности.

При обсуждении возникшей проблемы пришлось услышать мнение, что выполнять вычисления с нужной точностью не позволяют ограниченные возможности микроконтроллера PIC16F84A, который работает только с целыми числами. К счастью, это не так. Он действительно выполняет операции над восьмиразрядными двоичными числами с фиксированной запятой. Но целое — всего лишь частный случай такого числа, в котором двоичная запятая зафиксирована справа от младшего разряда, вес которого принят равным единице.

Ничто не мешает перенести запятую с привычного места на любое число позиций в сторону старшего разряда. Слева от нее будет расположена целая, а справа — дробная часть числа. Вес первого разряда справа от запятой будет равным 1/2, следующего за ним — 1/4 и так далее. Если, например, отвести на хранение целой части числа четыре старших, а дробной — четыре младших разряда восьмиразрядной ячейки памяти, получим возможность хранить в ней числа от нуля до 15,9375 с дискретностью 0,0625 (1/16). Если такая точность недостаточна, числу отводят два, три и более восьмиразрядных регистров (байтов), фиксируя запятую в нужном месте. Алгоритмы выполнения операций над многобайтовыми числами с помощью восьмиразрядного процессора хорошо известны и широко используются.

Оперируя с дробными числами, нужно не забывать нормировать операнды (совмещать их двоичные запятые) перед сложением или вычитанием, а после умножения или деления правильно определять положение запятой в результате. В нашем случае заданное в герцах и представленное 32-разрядным двоичным целым числом значение частоты нужно умножать на коэффициент К, представленный восьмиразрядной целой и 24-разрядной дробной частями. В 64-разрядном результате перемножения двух 32-разрядных чисел целая часть займет 40 старших разрядов. Код для загрузки в микросхему DDS — 32 младших разряда целой части. По существу — это двоичная дробь, равная отношению заданной частоты к частоте кварцевого генератора.

Подпрограмма, реализующая такой алгоритм, была написана и отлажена. Однако выяснилось, что она длиннее заменяемой подпрограммы mulk(), а свободного места в программной памяти микроконтроллера PIC16F84A нет, так как авторский вариант программы занимает ее всю — ровно 1024 слова. Чтобы освободить место в памяти, пришлось обратиться к созданному компилятором языка С, на котором написана исходная программа, промежуточному результату — файлу на языке ассемблера. Как и ожидалось, созданный компилятором ассемблерный текст страдает избыточностью, в нем многое удалось сократить. В результате всех изменений и дополнений длина программного кода уменьшилась с 1024 приблизительно до 800 слов, так что осталось место и для будущих улучшений.

Прежде всего, удален фрагмент от метки _add__code до метки _mulk__end, содержащий подпрограммы _add, _shl, _mul10, _BCDbin и _mulk, "ответственные" за вычисление загружаемого в микросхему DDS кода. Удалена также подпрограмма _validvalue (от метки _valid- value_^code до метки _validvalue__end), проверяющая допустимость заданного значения частоты.

Текст подпрограмм, разработанных взамен удаленных, приведен в таблице. Для удобства они объединены в отдельный файл mulk.inc, который включен в дорабатываемую программу директивой include "mulk.inc". Строка с этой директивой заняла место первого из удаленных фрагментов.

Метки и переменные (например, _arga), "унаследованные" от программы, созданной компилятором языка С, сохранили имена, начинающиеся с символа "подчеркивание". Вновь введенные имена, область действия которых не распространяется за пределы включаемого файла, этой особенности не имеют.

Обратите внимание, подпрограмма jnulk, умножавшая двоичное значение частоты на коэффициент и давшая имя включаемому файлу, теперь состоит из единственной команды возврата и ничего не делает. При желании эту подпрограмму можно было исключить вообще, удалив из основной программы ее вызов.

Нужный двоичный код теперь формирует в один прием подпрограмма _BCDbin. Она поочередно умножает каждый десятичный разряд заданного значения частоты (они занимают восемь ячеек с адресами _BCD—_BCD+7) на соответствующий коэффициент, накапливая результат в 32-разрядной переменной _arga, четыре байта которой хранятся по адресам _arga—_arga+3.

Умножение выполняет подпрограмма mult простейшим способом, складывая с помощью подпрограммы add взятое из таблицы значение коэффициента само с собой на один раз меньше значения десятичной цифры. В результате оптимизации подпрограмма add значительно короче удаленной _add. Вся процедура вычисления загружаемого в микросхему DDS кода занимает немногим более 2 мс. Ее можно ускорить, заменив подпрограмму mult более совершенной.

Заранее рассчитанные 32-разрядные коэффициенты хранятся в таблице, находящейся в еще одном включаемом директивой Include файле KTab.inc. Для автоматического формирования этой таблицы разработана программа КТаЬ, работающая в среде Windows. При ее запуске на экране компьютера будет открыто показанное на рис. 2 окно, в котором необходимо задать (или принять предлагаемые) значения частоты кварцевого генератора и предельной. Сформированная таблица будет отображена на экране. Нажав на экранную кнопку "Сохранить", ее записывают в файл (по умолчанию — KTab.inc).

dds_9850_dop-1
Рис. 2

Как видим, для разряда единиц герц задан коэффициент К1, округленный до целого. При вычислении коэффициента К10 для разряда десятков герц точное значение умножено на 10 и лишь затем округлено и так далее. Коэффициент К10М для разряда десятков мегагерц имеет девять точных десятичных знаков. Конечно, такой способ вычисления кода частоты не позволяет достичь теоретически возможной погрешности f0-10~32 Гц. Однако ошибка не превосходит долей герца, чего на практике более чем достаточно.

Последняя строка таблицы не имеет отношения к коэффициентам. В ней записана константа Fmax, используемая программой микроконтроллера при проверке допустимости значения частоты, набранного на клавиатуре генератора. Первый этап такой проверки происходит во время преобразования десятичного числа в двоичное. Выполняя каждое сложение, подпрограмма add проверяет, не произошло ли переполнение разрядной сетки. Сигнализируя о нем, она заносит единицу в младший разряд переменной _т, который был обнулен подпрограммой _BCDbin в начале преобразования.

Переполнение случается, если задано значение, большее частоты кварцевого генератора. Если не принять мер, то, например, при частоте генератора 40 МГц и заданной 50 МГц будет сформирован и загружен в микросхему DDS код частоты 10 МГц.

Второй этап проверки выполняет подпрограмма _validvalue. Прежде всего, она проверяет младший разряд переменной _т и возвращает основной программе значение 0, если переполнение произошло. Если его не было, подпрограмма сравнивает значение старшего байта двоичного кода частоты (_arga+3) с константой Fmax из таблицы КТаЬ. При содержимом _arga+3 меньше Fmax все в порядке, основная программа получает 1, в противном случае — 0. Так как младшие.байты кода в сравнении не ^участвуют, устанавливать предельную частоту можно лишь с дискретностью fo/256, что на практике вполне достаточно.

В соответствии с известной теоремой Котельникова частота сигнала, формируемого цифровым способом, не может превышать половины частоты квантования. Для микросхемы AD9850 — половины частоты сигнала, подаваемого на ее вывод 9, т. е. частоты кварцевого генератора f0. Однако, подключив к выходу микросхемы осциллограф и задав частоту немного меньше f0/2, увидим на экране ступенчатую кривую, показанную на рис. 3 синей линией и весьма отдаленно напоминающую изображенную красной линией синусоиду заданной частоты. Это не дефект микросхемы. Точно таким же будет выходной сигнал любого ЦАП, на вход которого поданы отсчеты "цифровой" синусоиды, а выходное напряжение в интервалах между отсчетами не изменяется.

dds_9850_dop-1
Рис. 3

Не вдаваясь в теоретические подробности, отметим, что спектр созданного таким способом сигнала содержит кроме основной составляющей с заданной частотой f множество паразитных с частотами f0±f, 2f0±f, 3f0±f и так далее. На рис. 4 показаны спектральная составляющая основной частоты (f=30 МГц при f0= 100 МГц) и ближайшая к ней паразитная (частотой 100-30=70 МГц). Как видим, их амплитуды, соответственно U, и U2, различаются немногим более чем в два раза. Их изменение при перестройке происходит по закону, показанному на рис. 4 голубой линией. Вблизи частоты f0/2 основная и паразитная составляющие практически равны. Именно их биения создают картину, наблюдаемую на экране осциллографа. Выбирая соотношение предельной частоты формируемого сигнала к частоте квантования, следует ориентироваться на требуемую чистоту спектра генерируемого сигнала.

dds_9850_dop-1
Рис. 4

dds_9850_dop-1
Рис. 5

Голубой линией на рис. 5 показана зависимость уровня максимальной паразитной составляющей относительно основной, измеренная на выводе 21 микросхемы DDS. Этот уровень ниже -20 дБ лишь в диапазоне 0...7 МГц. Чтобы расширить рабочий диапазон частот генератора, выходной сигнал DDS необходимо фильтровать.

На выходе примененного С. Кулешовым фильтра Z1 (см. рис. 2 в его статье) зависимость амплитуды спектральных составляющих от частоты принимает вид, показанный на рис. 4 красной линией. Тот же цвет имеет соответствующая кривая на рис. 5. С таким фильтром уровень паразитной составляющей в обычно интересующем радиолюбителей диапазоне 0...30 МГц не превышает -25 дБ.

Формирование сигнала с помощью ЦАП имеет еще один недостаток — заметно зависит от частоты амплитуда основной спектральной составляющей. Как следует из графиков на рис. 4, на частоте 30 МГц она меньше максимальной приблизительно на 15 % и без фильтра, и с фильтром, имеющим плоскую АЧХ в полосе прозрачности. Скомпенсировать падение амплитуды можно с помощью фильтра с подъемом АЧХ в сторону верхних частот.

На рис. 6 изображена схема такого фильтра, отличающегося от рассмотренного выше номиналами элементов и дополнительным звеном L3C9, реализующим нужный подъем АЧХ. Устанавливая его в генератор, необходимо увеличить сопротивление резистора R14 до 560 Ом (на практике может потребоваться подборка). Зависимости для DDS с таким фильтром показаны на рис. 4 и 5 зелеными линиями. Теперь амплитуда выходного сигнала U/ остается практически неизменной в диапазоне 0...30 МГц. Заодно улучшено на 10 дБ и более подавление паразитной компоненты.

dds_9850_dop-1
Рис. 6

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

В рассмотренном выше случае амплитуду "палки" на частоте 70 МГц компаратор уменьшит всего вдвое (на 6 дБ), зато составляющая такой же амплитуды появится на частоте 10 МГц.

В заключение — о технологии подготовки исправленной версии кода, подлежащего загрузке в микроконтроллер генератора. За основу можно взять любой из вариантов файла AD9850.asm, находящихся на сайте журнала "Радио" по адресу <ftp://ftp.radio.ru/pub/ 2004/03/generatorAD9850.zip>. Неважно, на какую частоту кварцевого генератора он рассчитан, необходимо лишь убедиться, что выбранный вариант предназначен для работы с нужным ЖК индикатором — одно- или двустрочным.

Удалите из файла AD9850.asm все лишнее, как сказано в начале статьи, и добавьте в него строку с директивой include, подключающей файл mulk.inc. Этот файл должен находиться в одной папке с "урезанным" AD9850.asm. Туда же следует поместить файл KTab.inc на нужную частоту, полученный с помощью программы «Tab.

Полезно дополнить файл AD9850.asm строкой
_CONFIG _RC_OSC & _WDT_OFF & _PWRTE_ON

Вставьте ее после строки include "p16F84a.inc" в самом начале текста программы. В результате отпадет необходимость задавать конфигурацию микроконтроллера при его программировании. Это будет сделано автоматически.

Ассемблерный файл превращают в загрузочный формата HEX с помощью ассемблера MPASM, входящего в состав среды разработки и отладки программ MPLAB IDE. Если ассемблер выдает большое число сообщений об ошибках, это, скорее всего, следствие того, что он не смог найти файл p16F84a.inc с описанием регистров микроконтроллера. Найдите этот файл вручную и поместите его копию в ту же папку, где находится основной транслируемый файл.

Радио 3-2005.