Altinkaya: турецкие корпуса для РЭА
РадиоЛоцман - Все об электронике

Отладка программ МК AVR и осциллограф. Часть 1

Atmel ATmega48 ATmega1284P

Журнал РАДИОЛОЦМАН, октябрь 2014

В. И. Иволгин, г. Тамбов

Наверняка многим известно, что главное не разработать и изготовить электронное устройство, а отладить его, довести, как говорится, до ума. И, пожалуй, в наибольшей степени это относится к конструкциям с применением микроконтроллеров (МК). Функции таких устройств в целом обычно определяются программой, заложенной в его память, которая чаще всего и становится источником проблем. Ее разработка и написание являются делом непростым, но, к счастью, для этой цели разработаны специализированные программные средства, с помощью которых уже на ранних этапах удается выявить и устранить большинство синтаксических, а также, хотя и в меньшей степени, и логических ошибок. Если говорить конкретно о микроконтроллерах компании Atmel, то для них такой средой является AVR Studio, предоставляющей в этом плане большие возможности и позволяющей выявить и устранить подавляющее большинство ошибок программы. Почему же не все 100%? Причин здесь может быть много, и разных. Ряд из них кроется, например, в особенностях взаимодействия МК с внешними устройствами, которые не всегда отвечают идеальным представлениям об их возможностях. И это может стать причиной того, что некоторые ошибки в программе «вылезут» только при эксплуатации устройства.

Выбираем схему BMS для заряда литий-железофосфатных (LiFePO4) аккумуляторов

Для решения подобных проблем обычно используют тестирование устройства в режиме реального времени посредством использования программных прерываний или контрольных точек и последующего вывода информации о состоянии микроконтроллера на ПК или другое регистрирующее устройство. Использование подобного подхода обычно не сопряжено с особыми сложностями, если на МК уже реализован канал связи с ПК. Тогда, в простейшем случае, в программе для целей отладки в нужных местах временно расставляются операторы, например, такие или им подобные:

                 mov	tmp, RegX
rcall OutPC,

где в первой строке значение интересующего регистра, например, регистра RegX микроконтроллера, переносится во временную переменную tmp (tmp – символическое имя переменной), а во второй через подпрограмму канала связи OutPC уже эта величина выводится в ПК. И еще одна небольшая техническая подробность: для бóльшей универсальности программ в некоторых местах вместо имен конкретных переменных лучше указывать непосредственно сами регистры, названные этими именами. Это вполне возможно благодаря тому, что структура регистровой памяти подавляющего большинства 8-разрядных МК от AVR однотипна. Тогда с учетом приведенных соображений лучше будет переписать этот фрагмент, например, так:

               	mov	r28, RegX
rcall OutPC

Отметим также, что здесь и далее примеры программ и их фрагментов приведены на ассемблере AVRASM2, а их тестирование проводилось на ATmega48 и ATmega1284P.

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

Рассмотрим несколько вариантов организации такого канала связи МК с осциллографом. И начнем с простейшего, требующего использования минимальных ресурсов тестируемого микроконтроллера – 1 вывода и примерно 50-60 байт программной памяти.

Будем исходить из того, что необходимо представить на экране осциллографа значения одного-двух байтов в форме, соответствующей их двоичному коду. Такое представление предполагает использование цифр 0 и 1, записанных в строку группами по 8 знакомест. Нет смысла пытаться в простейшем случае изображать их общепринятыми символами. Вполне достаточно вывести информацию в строке в виде их условных обозначений. Например, 1 изобразить узким прямоугольным импульсом, а 0 – более широким, или наоборот, как это предлагает, например, автор [1]. В этом случае вывод информации будет представляться выводом на экран осциллографа прямоугольных импульсов двух типов, соответствующих битовому представлению байта (байтов). И для этой цели достаточно будет одного свободного вывода микроконтроллера. Правда, не обойдется и без проблем. Ввиду того, что большинство аналоговых осциллографов не обладает возможностями длительного сохранения изображения на экране (о применении для этих целей цифровых осциллографов – несколько позже), для регенерации изображения приходится использовать исследуемый МК. Это приводит к прекращению выполнения основной программы в контрольной точке из-за перевода микроконтроллера в режим постоянного вывода информации.

Основой программного обеспечения при оговоренных выше условиях является подпрограмма OutByte (см. далее), которая формирует последовательность прямоугольных импульсов необходимой длительности в соответствии с битовым представлением байта. Ее размер составляет 42 байта, в ней используются 2 регистра общего назначения – r28, r29, которые без ограничений могут быть задействованы и в основной части программы МК. Первый из них служит для переноса в подпрограмму значения байта для вывода, а информация в r29 восстанавливается после окончания работы подпрограммы до ее начального значения. Информация выводится старшим битом вперед, вывод одного «знакоместа для бита» по времени соответствует 16 тактам рабочей частоты процессора, вывод байта – соответственно, 128 тактов. При частоте 2 МГц это время составит 64 мкс, а частота вывода одного байта – около 15 кГц. Подпрограмма формирования вывода байта OutByte, приведенная ниже, не содержит каких-либо особенностей. Разобраться в ее работе при необходимости помогут содержащиеся в ней комментарии.

              OutByte:			;=== вывод байта на экран осциллографа
push r28 ; r28-сохранить байт, который будет выведен
push r29 ; r29-сохранить значение для восстановления
ldi r29, 8 ; счетчик еще не выведенных бит в байте
ByteCode: ; разложить байт на биты
lsl r28 ; выдвинуть старший бит влево в бит переноса
brcs OutByte_1 ; если с=1, то была 1, перейти на OutByte_1
sbi PortB,0 ; если с=0, то формируем фронт «нуля»
rjmp OutByte_0 ; продолжить формирование 0
OutByte_1: ; формировать 1 (узкий импульс)
cbi PortB,0 ; использована для задержки на 2 такта
sbi PortB,0 ; формирование «фронта» импульса единицы
cbi PortB,0 ; формирование «спада» импульса единицы
cbi PortB,0 ; использована для задержки на 2 такта
rjmp EndOutByte ; переход на проверку – все биты выведены?
OutByte_0: ; продолжить формирование 0 (широкий импульс)
sbi PortB,0 ; использована для задержки на 2 такта
sbi PortB,0 ; использована для задержки на 2 такта
cbi PortB,0 ; формирование «спада» импульса нуля
nop ; использована для задержки на 1 такт
EndOutByte: ; проверка – все биты выведены?
dec r29 ; уменьшить счетчик бит на 1
brne ByteCode ; если r29 не 0, то продолжить вывод битов
pop r29 ; восстановить значение регистра r29
pop r28 ; восстановить значение регистра r28
ret ; завершить подпрограмму OutByte

В этой подпрограмме для подачи сигнала МК на вход осциллографа указан нулевой вывод порта В (PortB,0). Тем не менее, при соответствующей редакции подпрограммы, для этой цели может быть использован любой свободный вывод любого порта. Главное, чтобы при инициализации МК он был установлен как выход. Хотя при отсутствии такового можно попробовать использовать и занятый вывод. Критерии его пригодности для этой цели простые: это должен быть вывод, настроенный как выход, и изменения состояния этого вывода не должны менять режим работы МК-системы на момент вывода байта (байтов). Например, если выбранный вывод управляет включением светодиода индикации, то его можно будет использовать без ограничений, но если это выход с прерыванием по уровню или фронту, то вряд ли. Впрочем, и эту проблему можно снять запретом прерываний на время вывода. Одним словом, практически всегда для вывода байта можно найти подходящий вывод, и необязательно он должен быть специально выделен только для этой цели.

Теперь можно попробовать вывести значение какой-либо переменной, например Flag, из некоторой точки основной программы на осциллограф. Для этого, в соответствии с вышеизложенным, нужно будет разместить в заданной точке тестируемой программы такие строчки кода:

           Contr1:			;=== многократный вывод байта на осциллограф
cli ; запрет прерываний
wdr ; сброс сторожевого таймера
mov r28, Flag ; сохранить в r28 значение переменной Flag
call OutByte ; вызов п/п вывода байта
jmp Contr1 ; вернуться на начало Contr1 и повторить

где назначение строк 4 и 5 уже обсуждалось, а за счет добавления строк 1 и 6 осуществляется выход из основной программы МК и переход к регенерации изображения байта на экране осциллографа. Предотвращение помех со стороны остановленной программы производится запретом в ней прерываний и осуществлением регулярного сброса сторожевого таймера. Для обеспечения корректной работы программы переменная Flag не может совпадать ни с одним из используемых регистров - r28 и r29. Кроме того, при использовании приведенной программы в МК с программной памятью менее 8 кбайт операторы call и jmp должны применяться в другой форме – rcall и rjmp. Объем Contr1 составляет 10 байтов, но поскольку она работает совместно с OutByte, то необходимо учесть и ее соответствующий параметр – 42 байта. Итого: 52 байта.

Но, увы, вопреки ожиданиям получить приемлемый результат в виде изображений условных нулей и единиц удается не сразу. Причина заключается в очень капризной настройке развертки – ее длительности, режимов и уровней порогов синхронизации. Но даже при стабилизации изображения не сразу понятно – синхронизация установилась со старшего бита байта, как положено, или с какого-то случайного? И причина здесь проста. Дело в том, что при непрерывной передаче байта по способу программы Contr1 его начало и конец практически неразличимы. Точнее, для первой посылки байта начало определяется осциллографом совершенно однозначно по срабатыванию синхронизации развертки, а вот признака его окончания, понятного приемнику, т. е. осциллографу, здесь нет. К счастью, организовать его для заявленных условий очень просто. Нужно в базовой программе Contr1 после OutByte перед уходом на повторный вывод ввести задержку Delay_Contr, как это и сделано в нижеприведенной программе Contr2. В этом случае объем программной памяти, занимаемый Contr2 и подпрограммами, обеспечивающими ее работу, составляет в совокупности 68 байт.

     Contr2:			;=== многократный вывод байта со стабилизацией
cli ; запрет прерываний
wdr ; сброс сторожевого таймера
mov r28, Flag ; сохранить в r28 значение переменной Flag
call OutByte ; вызов п/п вывода байта
call Delay_Contr ; задержка для стабилизации изображения
rjmp Contr2 ; задержка окончена, повторить вывод байта

где задержка для стабилизации изображения Delay_Contr содержит нижеприведенный текст и оформлена в виде подпрограммы.

      Delay_Contr:		;=== задержка для стабилизации изображения
push r29 ; сохранить перед использованием
ldi r29, $2A ; установить продолжительность задержки
L_Contr2: ; блок формирования задержки
dec r29 ; уменьшить величину остатка выдержки
brne L_Contr2 ; если r29 не 0,то продолжить задержку
pop r29 ; восстановить значение
ret ; вернуться в основную программу

Длительность задержки здесь установлена примерно равной времени вывода одного байта. Эта величина некритична и может изменяться в широких пределах, но уменьшать ее более чем 4-5 раз вряд ли стоит. Визуально задержка в конце битового потока формирует «хвост» нулевого уровня (признак конца битовой посылки), который при использовании режима ждущей развертки может быть выведен за пределы экрана осциллографа. Но на приведенном ниже рисунке во всех случаях он показан в полном объеме. На Рисунке 1а дано изображение байта, полученное на осциллографе С1-73 при его стандартном использовании. Дешифрировать это изображение не очень удобно, хотя здесь все понятно: короткий по длительности прямоугольный импульс соответствует единичному биту, а более длинный – нулевому. И ошибиться невозможно.

а) Отладка программ МК AVR и осциллограф
б) Отладка программ МК AVR и осциллограф
в) Отладка программ МК AVR и осциллограф
Рисунок 1. Изображение байта 10110101.

Можно попытаться улучшить визуальное восприятие условных нулей и единиц за счет подачи сигнала на вход осциллографа через последовательно включенный резистор в несколько килоом. Резистор и паразитные емкости входа осциллографа и кабеля выполнят роль интегратора, который несколько «завалит» фронты импульсов, вследствие чего различие в длительности импульсов станет рельефнее. Некоторая расфокусировка луча и подбор удобного размера по вертикали также не помешают. И за счет этих мер, контуры импульсов 0 и 1 станут ближе к естественной форме цифр 0 и 1. Такой «модифицированный» вариант изображения этого же байта приведен на Рисунке 1б. На Рисунке 1в дано его же изображение на цифровом осциллографе в режиме векторного отображения. Применение последовательного резистора для коррекции изображения байта в этом случае излишне, хотя и возможно.

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

Следует так же подчеркнуть, что переменная Flag, использованная в обеих программах, является одним из регистров общего назначения (РОН), точнее, имя Flag является символическим именем, присвоенным в программе одному из РОН. И почему это уточнение является важным, станет понятнее после обсуждения структуры статической памяти рассматриваемых микроконтроллеров.

Литература

  1.  «Отладка систем на небольших микроконтроллерах с помощью осциллографа». РадиоЛоцман, 2014, июль, стр. 61.

Окончание

64 предложений от 34 поставщиков
Микроконтроллер AVR 4K-Флэш-память/512-ОЗУ/256-ЭППЗУ+8x10 АЦП, электропитание 2,7...5,5В
ATMEGA48PB-AU
Atmel
29 ₽
ЗУМ-СМД
Россия
ATMEGA48PA-AU
Atmel
29 ₽
ЧипСити
Россия
ATMEGA48PA-AU
Atmel
53 ₽
ChipWorker
Весь мир
ATMEGA48-20MU
Microchip
68 ₽
Электронные компоненты. Бесплатная доставка по России
Для комментирования материалов с сайта и получения полного доступа к нашему форуму Вам необходимо зарегистрироваться.
Имя