Самая простая программа для МК

June 27, 2010 by admin Комментировать »

Давайте напишем сначала самую простую программу, которая будет вклю­чать светодиод сразу при включении питания и больше ничего не делать. Для примера возьмем контроллер ATtiny2313, схема подключения которого вме­сте с программирующим разъемом показана на рис. 19.2.

clip_image002

Рис. 19.2. Схема подключения ATtiny2313

Подробности

Обратим внимание на RC-цепочку (R1 и С1), которая подсоединена к выводу Reset. Она служит для более надежного сброса контроллера при не слишком качественном источнике питания, если установление напряжения затягивает-ря. В техническом описании указано, что по выводу Reset уже имеется встро­енный фильтр дребезга с «подтягивающим» резистором, так что эта цепочка оказывается вроде бы и ненужной (ее установка рекомендовалась для семей­ства Classic, где фильтра не было). Тем не менее, для более надежной работы МК рекомендуется во всех случаях устанавливать резистор R1 с номиналом 3—5 кОм (встроенный резистор имеет слишком большой номинал). Что каса­ется конденсатора С1, то если для управления сбросом применяется внешний монитор питания, как описано в главе 18, то, разумеется, он будет только ме­шать, в остальных случаях он необязателен, но делает работу схемы более стабильной. Резисторы R2—R4 при наличии профаммирующего разъема ус­танавливать обязательно, в противном случае надежность схемы снижается.

Заметим, что в схеме на рис. 19.2 показана только небольшая часть функцио­нальности входных/выходных линий, которые все, включая даже Reset (но ис­ключая, конечно, выводы подсоединения кварца и питания), имеют как мини­мум две, а большинство даже три функции. Подробно со всеми этими функциями можно ознакомиться в техническом описании, частично вы с ними познакомитесь из дальнейшего изложения.

Светодиод мы сразу взяли двухцветный — в целях дальнейшего усовершен­ствования схемы. Светодиод L56 (можно также взять L57 или малогабарит­ный L36) светится зеленым, если плюс питания находится со стороны ключа (скоса на корпусе), и красным — если наоборот. Здесь мы его подключили к выводам PD5 и PD6 порта D. Таким образом, если на этих выводах будет одинаковый уровень (неважно, единица или ноль), то светодиод погашен, если разный — то в зависимости от того, на каком выводе единица, светоди­од будет гореть красным или зеленым. Токоограничивающий резистор R5 при логическом уровне на выходе порта примерно 4,5 В обеспечит ток через светодиод около 5 мА.

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

1. Конфигурирует нужные выводы порта D (PD5 и PD6) на выход.

2. Устанавливает на выводе PD6 логическую единицу (логический ноль на выводе PD5 устанавливается по умолчанию).

И все, программа будет состоять всего из двух команд? Увы, не все так про­сто. В регистры портов записывать непосредственное значение нельзя, мож­но только командой out переносить информацию из какого-нибудь рабочего регистра. Поэтому добавится третья команда — сначала мы установим нуж­ные биты в некоем рабочем регистре, специально выбранном для этих целей из числа регистров общего назначения (РОН), затем загрузим весь получен­ный байт в регистр порта. Причем установить непосредственное значение можно также не в любом из РОН, а только в регистрах с номерами с 16 по 31, поэтому выберем себе регистр г16 в качестве рабочего. Тогда последователь­ность команд будет выглядеть так:

Idi г16,ObOllOOOOO ;устанавливаем биты номер 5 и 6 в регистре г1б out DDRD,rl6 ;выводим это значение в регистр направления порта D sbi PortD,6 ;устанавливаем в единицу бит б регистра данных, порта D

Здесь idi — команда загрузки непосредственного значения (load immediate), out — команда вывода в какой-либо регистр вврда/вывода (РВВ), sbi (set bit input/output)— команда установки бита с выбранным номером в РВВ. А что означает запись obOliooooo? Это хорошо знакомое нам двоичное представ­ление числа, Ob впереди означает, что это именно двоичная запись. Таким образом в данном случае удобнее отсчитывать биты, но если мы запишем это же число в hex-форме 0x60 (или $60), или даже просто десятичное 96, ничего не изменится. Заметим, что способ установки значений РВВ через команду out — не единственный, можно было бы установить биты 5 и 6 регистра ddrd двумя командами sbi (есть и другие способы).

Подробности

Обратите внимание на синтаксис команд — сначала пишется, куда писать, а потом, через запятую, откуда или что. Это справедливо для всех команд и для всех ассемблеров. Ка>кдая команда пишется в отдельной строке. Весь текст после точки с запятой ассемблером игнорируется и предртавляет собой комментарии, которые нужно писать обязательно, иначе вы через пару меся­цев и сами в программе не разберетесь. Если комментарий переходит на дру­гую строку, то точку с запятой нужно ставить заново, в начале строки. В отли­чие от знака перевода строки, все пробелы и табуляции игнорируются (а там, где есть другой разделительный знак, в данном случае запятая, как видите, пробелов вообще может не быть), так что украшать текст отступами можно, а для удобства чтения и нужно. Строчные и прописные буквы не различаются: записи LDI, Ldi и Idi ознзчают одно и то же.

Ну и все? Можно скопировать это в Блокнот, сохранить с расширением .asm и компилировать в hex-файл? Ишь разбежались— нет, не все. Во-первых, кнГкаких таких ddrd и PortD AVR-ассемблер «не понимает». Если соответст­вия кодов команд и их мнемонических обозначений (ldi), а также обозначе­ний рабочих регистров (г1б) и их адресов «зашиты» в ассемблере, то РВВ могут меняться от модели к модели, а их названия и вообще могут быть вы­браны совершенно произвольным образом. Сам ассемблер «понимает» толь­ко конкретные числа, представляющие собой адреса этих регистров. Но пи­сать программу без мнемонических обозначений бьшо бы крайне неудобно, так как программа оказалась бы совершенно нечитаемой (вторая команда, к примеру, тогда выглядела бы так: out $11, г 16). Поэтому к нашей программе надо «пристегнуть» файл с мнемоническими обозначениями, который по­ставляется Atmel, и в данном случае называется tn2313def.inc (при компиля­ции он должен находиться в одной директории с файлом программы). Это делается почтив точности как в языке С, строкой: .include "tn2313def,inc" /точка впереди обязательна!

Если вы заглянете внутрь файла tn2313def.inc, то увидите, что он состоит из строк, начинающихся с директивы .equ. Мы могли бы не включать его в программу (хотя в память процессора он все равно не записывается, ибо не содержит команд, а только определения переменных), а лишь дописать к программе в начале текста строки:

.equ DDRD = $11 .equ PortD = $12

Мы часто будем применять директиву . equ, которая устанавливает соответ­ствие между числами и их обозначениями, наряду с другой полезной дирек­тивой— .def. Если провести аналогии с языком Turbo Pascal, то директива .equ (от англ. equal — равно) полностью аналогична определению констант, а .def (от англ. define— определить) аналогична определению переменных, с единственным отличием: тип переменной здесь не указывается, ибо он один-единственный— число размером один байт (а вот в директиве .equ может быть указано число любого размера, а также и отрицательное, но, ес­тественно, только целое).

Неудобно каждый раз писать г1б и помнить, что это у нас рабочая перемен­ная для всяких текущих надобностей, потому лучше дописать еще такую строку:

.def temp * rl6 /рабочая переменная, от слова temporary (временный)

Окончательно исходный текст программы будет выглядеть так: /программа зажигания светодиода /процессор Tiny2313, частота 4 МГц .include "tn2313def.inc"

.def temp = rl6 /рабочая переменная

Idi temp,ObOllOOOOO /устанавливаем биты номер 5 и 6 в temp

out DDRD,temp /выводим это значение в регистр направления порта D

sbi PortD,6 /устанавливаем в единицу бит 6 регистра данных порта D

sleep

.exit

Программа займет в памяти программ контроллера ровно 8 байт. Последняя команда sleep означает остановку процессора и й^ыход в режим экономии — ведь должен процессор что-то делать по окончании программы? Директива .exit предназначена для ассемблера и означает конец программы, указывать ее необязательно.

А зачем мы в заголовочном комментарии указали тактовую частоту процес­сора? В данном случае она не имеет значения (лишь бы контроллер работал), но при использовании любых процедур, связанных со временем, это критич­но. И поскольку можно забыть, на какую частоту вы рассчитывали при напи­сании программы, следует ее на всякий случай указывать в комментариях.

Оставить комментарий

микросхемы мощности Устройство импульсов питания пример приемника провода витков генератора выходе напряжение напряжения нагрузки радоэлектроника работы сигнал сигнала сигналов управления сопротивление усилитель усилителя усиления устройства схема теория транзистора транзисторов частоты