Занимательная электроника — страница 102 из 128

с ошибкой, так что нумерация строк принципиально важна. Один из рекомендуемых вариантов редакторов для AVR-ассемблера — «самопальный» редактор ASM Editor (не путать с Asmedit!), который сделан на удивление профессионально, хотя и не без некоторых досадных огрехов.

Все сказанное относится к программированию на языке ассемблера, потому что программы для AVR-контроллеров можно писать и на С, C++, специальном языке Proccesing/Wiring (Arduino!) и многих других, включая даже специальные версии Pascal (mikroPascal for AVR[34]). Для тех, кто уже владеет программированием на языках высокого уровня, это может показаться более удобным способом, а такие варианты, как среда Arduino, специально «заточены» под начинающих, не имеющих представления ни о программировании, ни об электронике. Знакомиться со средой Arduino мы еще будем в дальнейшем, и там вы сами сможете пощупать руками все ее достоинства и недостатки. Сейчас же я скажу только, что для углубленного изучения контроллеров я бы не рекомендовал начинать не только со среды Arduino, но и вообще с программирования на С или других языках высокого уровня. Не столь важно то, что в результате на ассемблере получается более быстрый и компактный код, сколько то, что любой посредник (а компилятор С есть именно посредник) в этом деле только мешает понимать, что именно происходит в контроллере.

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

Все, что сказано в этой главе далее, относится только к программированию МК AVR «в чистом виде», т. е. на ассемблере и в средах, ориентированных на его использование.


О конфигурационных битах

Эта напасть свалилась на нас с появлением семейств Tiny и Mega, в «классических» AVR ничего такого не было (точнее, было, но специально заботиться об установке этих битов не требовалось). В англоязычной инструкции конфигурационные биты называют fuse битами. Их появление привело к многочисленным проклятиям на голову фирмы Atmel со стороны армии любителей, которые стали один за другим «запарывать» кристаллы при программировании. Положение усугублялось тем, что в описании этих сущностей используется извращенная логика, — как мы знаем, ячейки любой чистой EEPROM (по принципу ее устройства) содержат единицы, и слово «запрограммированный» по отношению к такой ячейке означает, что в нее записали логический ноль. Термины запрограммированный и незапрограммированный как раз и применяются в фирменных описаниях AVR, и оттуда перекочевали в ряд самодельных программаторов — готовьтесь к тому, что в некоторых программаторах отмеченный галочкой в меню программы бит означает его равенство логической единице, а в других — запрограммированное состояние, т. е. логический ноль. Поэтому разработчики программаторов AS из фирмы Argussoft даже специально предусмотрели в окне программирования конфигурационных ячеек памятку на этот счет (рис. 19.1).



Рис. 19.1.Окно типового состояния конфигурационных ячеек в нормальном режиме работы ATmega8535


В этом окне сейчас приведено безопасное рабочее состояние конфигурационных ячеек для ATmega8535, причем выпуклая кнопка означает единичное состояние ячейки, а нажатая — нулевое (и не путайтесь с этим самым «запрограммированным» состоянием!). Для разных моделей набор fuse битов различный, но означают они одно и то же, потому мы рассмотрим типовое их состояние на этом примере.

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

Самые необходимые пункты тут такие. По умолчанию любая микросхема семейств Mega или Tiny запрограммирована на работу от внутренней RC-цепочки, за что разработчикам большое спасибо, иначе было бы невозможным первичное программирование по SPI — только через параллельный программатор. Для работы с обычным «кварцем», присоединенным по типовой схеме, как мы говорили в главе 18, требуется установить все ячейки CKSELO-3 в единицы (что согласно логике разработчиков означает незапрограммированное их состояние). Заметим, что это и ведет к критической ошибке — решив при поверхностном чтении написанного по-английски руководства, что установка всех единиц означает запрограммировать все ячейки, пользователь смело устанавливает их на самом деле в нули, отчего микросхема переходит в состояние работы от внешнего генератора, и разбудить ее через SPI-интерфейс уже невозможно. Легче всего в этом случае переустановить fuse биты с помощью параллельного программатора либо, за неимением такового, попробовать-таки подключить внешний генератор, как описано в руководстве.

Это самая крупная ошибка, которую можно допустить, но есть и другие менее распространенные. Ячейка SPIEN разрешает/запрещает последовательное программирование по SPI и должна оставаться в нулевом состоянии, иначе МК не «разбудишь» никак, только опять же с помощью параллельного программатора (говорят, правда, через SPI ее и отключить невозможно). Ячейка S8535C (в других моделях она будет иметь другое название или вовсе отсутствовать) — очень важна и определяет режим совместимости с семейством Classic (в данном случае с AT90S8535).

Если ее установить в нулевое состояние, то МК семейства Mega перейдет в режим совместимости. В популярном ATtiny2313, потомке «классического» AT90S2313, такого бита совместимости нет (но, как мы увидим, это не очень существенно). При использовании режима совместимости следует учесть, что состояния МК нельзя перемешивать: если fuse бит совместимости запрограммирован (равен 0), то программа компилируется полностью, как для семейства Classic (в том числе с использованием соответствующего inc-файла, см. далее), иначе она может не заработать.

Еще одна важная ячейка — EESAVE, которая на рис. 19.1 установлена в единицу (режим по умолчанию), но ее целесообразно перевести в нулевое состояние — тогда при программировании памяти программ не будет стираться содержимое EEPROM.

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

Наконец, для нас в дальнейшем будет иметь значение состояние ячеек BODEN и BODLEVEL. Первая, будучи установлена в ноль, разрешает работу так называемой схемы BOD (Brown-out Detection), которая сбрасывает контроллер при снижении питания ниже допустимого порога. Ячейка BODLEVEL и определяет этот самый порог — при установленной в 0 ячейке он равен 4 В, при установленной в 1–2,7 В.

При питании 5 В надо выбирать первое значение, при питании 3,3 В — второе. Это предохраняет контроллер от «недопустимых операций» при выключении питания, но для обеспечения полной сохранности содержимого EEPROM таких мер может оказаться недостаточно, и приходится производить дополнительные действия (см. также главу 18). Все остальные ячейки следует оставить по умолчанию (и тем более ни в коем случае не трогать Lock биты, при установке которых доступ к программе и fuse битам вообще отключается навсегда!). Только учтите, что в разных контроллерах одни и те же узлы могут программироваться по-разному. Так, в рассматриваемом далее ATtiny2313 (и некоторых других, в основном из тех, что способны работать при напряжении питания до 1,8 В) схема BOD устроена иначе: ячеек BODLEVEL там целых три, причем упомянутая ранее BODLEVEL соответствует BODLEVEL0, а при тех же значениях порога ячейки BODLEVEL2: BODLEVEL1 должны быть в состоянии 10. Ячейки BODEN там нет, а выключенному состоянию схемы BOD соответствуют все единицы во всех трех ячейках. Зато там есть любопытный fuse бит CKOUT, который при программировании (установке в ноль) подключает к выводу 6 (PD2) выход тактового генератора, и еще бит CKDIVS, который в том же случае снижает тактовую частоту в восемь раз (например, при кварце 8 МГц МК заработает, как от 1 МГц, что снижает потребление). Поэтому для каждого конкретного контроллера следует сверяться с техническим описанием.

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


Примеры программирования

Написание программ — целое искусство, поэтому здесь можно на нескольких примерах попытаться дать только общее представление о том, как это делается, — заостряя внимание на специфических особенностях программирования для МК, а не программирования вообще. Полного обзора команд и даже комментариев по каждой встречающейся команде вы также здесь не увидите — это потребовало бы отдельной книги (см. [19, 20], а также книгу автора [21]).


Самая простая программа

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



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