Go up
Вы используете устаревший браузер. Подробнее »
Чтобы использовать все возможности сайта, загрузите и установите один из этих браузеров: Используется тема VK-Style © http://Sergey.Pro
Posts The private archive of professor Preobrazhensky
Картинка профиля Профессор Преображенский

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

Сейчас, написав первую статью из цикла, я понимаю, что несколько погорячился и сделал ту же ошибку, что и мои предшественники, поставив словосочетание «для начинающих». Вернее было бы сформулировать тему «Для начинающих программировать на ассемблере», то есть я предполагаю, что читатель уже имеет хотя бы поверхностное представление о том, что такое микроконтроллер, иначе только на знакомство с этой темой у нас уйдет уйма времени. Для тех же, кто совсем не знаком с ними, могу порекомендовать совершенно замечательный на мой взгляд цикл статей С. Рюмика «Микроконтроллеры AVR», опубликованный в журнале Радиоаматор (№№ 1-11 за 2005 год). В этом цикле в качестве базового контроллера выбран ATmega8, однако общие функциональные узлы у вышеназванного контроллера и ATtiny13 практически не отличаются.

Для знакомства же непосредственно с микроконтроллером ATtiny13 я рекомендую книгу А.В. Евстифеева «Микроконтроллеры AVR семейства tiny. Руководство пользователя» (М.: Издательский дом «Додэка-XXI», 2007. — 432 с.). Она содержит переведенные и систематизированные даташиты на весь номенклатурный ряд контроллеров семейства tiny, и, на мой взгляд, должна являться настольной для тех, кто занимается программированием микроконтроллеров.

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

Но все это лирическое отступление. Вернемся непосредственно к повествованию.

Контроллер ATtiny13 несмотря на свой малый размер, имеет весьма неплохие функциональные характеристики. А небольшое количество выводов с лихвой компенсируется количеством функций, которые каждый из них выполняет. Цоколевка и описание выводов представлено ниже:

Таблица взята из вышеназванной книги А.В. Евстифеева.

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

Как видно из рисунка и таблицы, все выводы, за исключением выводов питания, имеет название РВ с последующим порядковым номером. Что же это означает? Все выводы контроллера объединены по 8 штук для удобства работы с ними, а на каждую группу из 8 выводов выделено по три специальных регистра ввода-вывода. Вообще понятие регистров является ключевым при работе в контроллерами, особенно на ассемблере. Рассмотрим более подробно каждый из трех вышеупомянутых регистров. Все они являются однобайтовыми ячейкам в памяти контроллера. Каждый бит их отвечает один из выводов контроллера, причем номер бита в регистре совпадает с номером вывода (например, 0-й бит отвечает за вывод РВ0, 1-й — за РВ1 и т.д.). Все регистры имеют свое имя, по которому к ним обращаются при написании программ. Что же это за имена?

1. Регистр DDRB отвечает за направление передачи информации каждого вывода контроллера. Если какой-либо бит этого регистра равен «0», то соответствующий ему вывод будет входом, а если «1» — то выходом. Причем каждый вывод конфигурируется индивидуально и в любом месте программы. Это значит, что при разных условиях или в разное время один и тот же вывод может быть сконфигурирован как вход либо как выход, причем независимо от остальных выводов.

2. Регистр PINB содержит в себе текущее состояние всех выводов: если на вывод подано напряжение, то в соответствующий бит записывается логическая «1», если напряжение отсутствует — логический «0». В основном этот регистр используется для считывания состояния вывода, находящегося в режиме входа.

3. Регистр PORTB выполняет двоякую функцию в зависимости направления передачи информации. Если вывод работает как цифровой выход, то запись «1» в какой-либо бит регистра PORTB приводит к появлению напряжения на соответствующем выводе, а запись «0» — к исчезновению напряжения. Таким образом, в режиме выхода именно этот регистр определяет состояние каждого вывода. В режиме цифрового входа запись логической «1» в какой-либо бит приводит к подключению встроенного подтягивающего резистора на соответствующем выводе, а запись «0» — к его отключению. Что же это за такая штука — «подтягивающий резистор», и для чего она предназначена? Если вывод работает как цифровой вход, то сопротивление входного буфера достаточно велико, а входной ток — весьма мал. Поэтому любые электрические наводки могут привести к самопроизвольному переключению вывода в произвольное состояние. Чтобы этого не происходило, между входом и источником питания включается резистор сопротивлением несколько десятков килоом, «подтягивающий» потенциал входа к напряжению питания (отсюда и название). Ток, протекающий через этот резистор достаточно мал, чтобы не мешать работе остальной схемы, но достаточно велик, чтобы воспрепятствовать случайным переключениям вывода. Мы часто будем использовать подтягивающие резисторы при работе с кнопками, поскольку когда они не нажаты, выводы, к которым они подключены, фактически «висят» в воздухе и подвержены наводкам.

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

Теперь, когда мы имеем хоть какое-то представление, ЧТО нужно для работы с вводами контроллера, пришла пора узнать, КАК с ними работать.

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

1. Заходим в папку asm, создаем в ней новую папку. Переименовываем в удобное для нас имя. Для определенности я буду называть их по номеру нашего шага. В данном случае «step2».

2. Правой кнопкой щелкаем на файле build.bat и изменяем путь к исходному файлу, указывая вновь созданную папку (step2). У меня после этого содержимое выглядит так:

«F:\Prog\AVR\asm\avrasm32 -fI %F:\Prog\AVR\asm\step2\main.asm
pause»

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

3. Заходим в папку Asmedit и запускаем программу ASM_Ed.exe

4. В открывшемся окне пишем текст программы. На этом пункте остановлюсь более подробно, поскольку он является основным в нашем сегодняшнем занятии, равно как и в последующих.

Что же собой представляет текст ассемблерной программы? Он может включать в себя несколько элементов, записываемых по определенным правилам:

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

— директивы, каждая из которых начинается с символа «.»;

— метки, представляющие собой произвольно названные пользователем места программы, к которым может потребоваться переход. Каждая метка оканчивается символом «:»;

— комментарии, начинающиеся с символа «;». Весь текст от начала комментария до конца строки игнорируется при создании hex-файла и может быть совершенно произвольным;

— пустые строки для лучшей структурированности и читабельности программы.

В каждой строке может быть не более одной команды. Однако одновременное присутствие в строке метки с последующей командой и комментарием допускается.

Используя эти правила, напишем программу, которая будет включать светодиод LED2, пока удерживается нажатой кнопка SB1, и выключать его, если кнопка отпущена. Текст программы представлен ниже:

  1. .include "F:\Prog\AVR\asm\Appnotes\tn13def.inc"
  2. sbi DDRB, 4     ;РВ4 - выход (светодиод LED2)
  3. sbi PORTB, 2    ;Включение подтягивающего резистора на РВ2 (кнопка SB1)
  4. sbic PINB, 2    ;Если РВ2=0 (кнопка нажата), пропустить след. строку
  5. sbi PORTB, 4    ;Установка РВ4 в 1 (выключение светодиода)
  6. sbis PINB, 2    ;Если РВ2=1 (кнопка отпущена), пропустить след. строку
  7. cbi PORTB, 4    ;Установка РВ4 в 0 (включение светодиода)

Разберем его поподробнее. Первая строка содержит директиву «include», написанную по указанным выше правилам с точкой в начале. Назначение ее — включать в текст программы указанный за ней файл. Как я говорил еще в первом шаге, нам потребуется файл «tn13def.inc». В этой строке вам необходимо будет изменить путь, указав расположение папки Appnotes в своем компьютере. Зачем же нам нужно подключать этот файл? Любопытный читатель может заглянуть в него и почитать его содержимое, но, скорее всего, поначалу он мало что поймет там. Пока же скажу, что в нем содержится соответствие имен регистров, которые по умолчанию ассемблер не знает, с их физическими адресами в контроллере.

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

Команда sbi имеет два операнда: первый — имя регистра, второй — номер бита. В результате ее выполнения указанный бит в указанном регистре устанавливается в «1».

Команда cbi по синтаксису аналогична вышеприведенной и выполняет прямо противоположную функцию — сбрасывает указанный бит в указанном регистре в «0».

Команда sbis также аналогична по синтаксису вышеприведенным. Однако в отличие от них она не выполняет никаких операций с регистрами, а лишь проверяет состояние указанного бита в указанном регистре, и если тот равен «1», пропускает следующую за командой строку. В противном же случае следующая за ней строка выполняется, равно как и все остальные за ней.

Команда sbiс является противоположностью команды sbis. Она пропускает следующую строку, если указанный бит регистра равен «0».

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

1 строка. Директивой include подключается файл tn13def.inc, содержащий определения регистров.

2 строка. Командой sbi устанавливается «1» в бит 4 регистра DDRB, тем самым вывод РВ4 переключается на выход. Если посмотреть схему платы (рис. 1 предыдущего шага), можно видеть, что к этому выводу подключен светодиод LED2. После команды и знака «;» написан комментарий, кратко поясняющий смысл выполняемых в строке действий.

3 строка. Той же командой sbi устанавливается «1» в бит 2 регистра PORTB, подключая внутренний подтягивающий резистор к выводу РВ2, к которому подключена кнопка SB1. Поскольку мы не изменяли состояние бита 2 регистра DDRB, этот вывод так и останется входом, что нам, собственно, и нужно.

4 строка. Командой sbic проверяется наличие логического «0» на входе PB2, используя регистр PINB. Если внимательно посмотреть на схему, можно увидеть, что кнопки при нажатии, замыкают соответствующий вывод с общим проводом. Это стандартный прием, поскольку при отпущенной кнопке на выводе присутствует логическая «1» за счет подтягивающего резистора, а при нажатой появляется логический «0» благодаря подключению вывода к общему проводу. Итак, если на выводе РВ2 присутствует логический «0», то есть кнопка нажата, мы пропускаем следующую строку, а если кнопка отпущена, то выполняем ее.

5 строка. В ней командой sbi устанавливается логическая «1» в бит 4 регистра PORTB, тем самым выключая светодиод LED2. Въедливый читатель может поинтересоваться, почему же светодиод выключается, если мы подаем напряжение на выход. Ответ кроется в схеме. Светодиод анодом подключен к проводу питания, а катодом к выводу контроллера. Поэтому если подать на вывод напряжение, то потенциалы анода и катода сравняются, и светодиод погаснет. Если же на вывод выдать логический «0», то к светодиоду будет приложено напряжение, и он зажжется. Таким образом пара строк 4 и 5 выключает светодиод LED2 при отпущенной кнопке.

6 строка. Противоположна по смыслу 4-й. Командой sbis проверяется наличие логической «1» на входе РВ2, то есть проверяется, отпущена ли кнопка. Если кнопка отпущена, то следующая строка пропускается, и происходит переход к следующей за ней. Но поскольку 7-я строка последняя, то происходит переход ко 2-й строке. Если же кнопка нажата, то выполняется строка 7.

7 строка. Противоположна 5-й. Командой cbi бит 4 регистра PORTB сбрасывается в «0», тем самым включая светодиод LED2. Таким образом, пара строк 6 и 7 включает светодиод LED2 при нажатой кнопке SB1.

Как видите, ничего особо сложного мы не совершили. Используя знание всего 3-х регистров и 4-х команд, мы написали нашу первую программу. Что же делать с ней дальше. Если вы еще не забыли, мы продолжаем писать алгоритм создания программы.

5. Написав текст программы в окне редактора, выбираем пункт меню «File», и в открывшемся списке нажимаем «Save As…». В окне сохранения файла выбираем созданную нами папку step2 и указываем имя файла «main», поскольку именно это имя было задано нами в файле «build.bat»

После сохранения окно программы должно иметь следующий вид:

6. Создаем hex-файл. Для этого нажимаем кнопку «II» на панели инструментов. Должно появится окно следующего вида:

Оно извещает нас о том, что ассемблирование прошло без ошибок и создан файл прошивки «main.hex» объемом 6 слов, то есть 12 байт. Замечу, что аналогичная программа на языке Си имела бы как минимум в 5 раз больший объем.

7. Зайдя в папку step2,  обнаруживаем в ней пополнение в виде вновь созданного файла main.hex, который теперь может быть зашит в контроллер любым программатором, что и необходимо выполнить, дабы увидеть результаты работы написанной нами программы. После прошивки контроллера, если схема собрана правильно, все должно работать по разработанному нами алгоритму: при отпущенных кнопках светодиод LED2 должен быть погашен, а во время удержания нажатой кнопки SB1 — зажжен.

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

До следующего шага предлагаю сделать такие задания:

1. Добавить к программе обработку нажатия кнопки SB2 с противоположным алгоритмом: при отпущенной кнопке SB2 светодиод LED1 должен быть зажжен, а при нажатой — погашен.

2. Написать программу управления светодиодом LED2 при помощи обеих кнопок. При нажатии на кнопку SB1 светодиод должен зажигаться и оставаться включенным до тех пор, пока не будет нажата кнопка SB2, которая выключает его до следующего нажатия SB1.

Если у вас возникнут вопросы, задавайте их на форуме или здесь в виде комментариев к статье.

Желаю успехов!

Автор: Сергей Сокол, материал взят с его сайта https://sokolsp.at.ua/


No comments yet.

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong> <pre lang="" line="" escaped="" cssfile="">

Перейти к верхней панели