Вы находитесь на странице: 1из 81

Валов А.В.

Микропроцессоры и их применение в системах управления


Учебное пособие
Часть 2

Челябинск, 2012
Валов, А.В.
Микропроцессоры и их применение в системах управления: Учебное
пособие / А.В. Валов. – Челябинск: Издательский центр ЮУрГУ, 2012. –
Ч.2. – 81 с.

Учебное пособие предназначено для заочного и очного обучения студентов специальности 1406 по
курсу «Микропроцессоры и их применение в системах управления». Изучаются теоретические и
аппаратные основы принципов построения цифровых вычислительных и управляющих устройств со
средствами сопряжения: микропрограммных автоматов на примере микропроцессорной серии 1804,
однокристальных процессоров по их главной линии I8080, I8086,... , микроконтроллеры серии ATmega,
микроконтроллеры ARM, на примере микроконтроллеров STМ32. Рассмотрены особенности
микроконтроллеров на основе событийно-ориентированного программирования. Рассмотрены также
особенности сигнальных (DSP) процессоров, а также многоядерных микроконтроллеров (семейство
ОМАР), объединяющих ARM и сигнальные процессоры.

© Издательский центр ЮУрГУ, 2012


6 МИКРОКОНТРОЛЛЕР ФИРМЫ ATMEL ATmega8

Для изучения основ программирования микроконтроллеров семейства


AVR фирмы Atmel, которое мы рассмотрим на базе микроконтроллера
ATmega8, потребуется следующее программное обеспечение для ПК:
ассемблер для микроконтроллеров семейства AVR фирмы Atmel. Например,
AVRStudio 4.0 или любой другой удобный для вас ассемблер. Эта программа
позволит переводить мнемоники команд, понятные для человека, в 16-ные
коды, которые уже понимает микроконтроллер, а также сымитировать
виртуально работу контроллера.
Внешний вид таких котроллеров
очень похож на обычные микросхемы,
которые устанавливаются на печатных
платах (рис. 6.1). Поэтому их легко
интегрировать в эти платы. Т.е. они не
требуют отдельного шкафа управления.
Но есть и минусы. Главным из которых
является необходимость сопряжения
микроконтроллера, его уровня напряжения
и типа подводимого сигнала с
Рис. 6.1. Внешний вид напряжением и типом сигнала
микроконтроллера АTmega8 выдаваемого объектом управления.
Между тем, эти микроконтроллеры
снабжены различной периферией (АЦП, компаратором, ШИМ), которая
позволяет использовать их в печатных платах на производстве без
дополнительных обвязок. Наличие этой периферии позволяет называть эти
микросхемы уже не микропроцессорами, а микроконтроллерами. Это
основное отличие микроконтроллера от микропроцессора.
Но разберемся в этом вопросе подробнее.
Основным классификационным признаком микроконтроллера (МК)
является разрядность данных, обрабатываемых арифметико-логическим
устройством. По этому признаку МК делятся на 4-, 8-, 16-, 32- и 64-
разрядные.
Вторым классификационным признаком в настоящее время является
принцип, положенный в основу построения процессорного ядра (технология
построения управляющего устройства): CISC- процессоры (СISC – Complex
Instruction Set Computer – компьютер с комплексным набором инструкций) и
RISC – процессоры (Reduced Instruction Set Computer – компьютер с
сокращенным набором команд).
Третьим классификационным признаком является архитектура
микропроцессора – Неймановская (классическая) и Гарвардская архитектура.
Существуют МК как с классической (Неймановской) архитектурой, так и с
Гарвардской архитектурой.
3
Далее МК условно разбиваются на две группы: микроконтроллеры
общего назначения и специализированные МК.
Структурная схема рынка микроконтроллеров представлена на рис. 6.2.
Микроконтроллеры

Микроконтроллеры Специализированные
общего назначения микроконтроллеры

Микроконтроллеры Микроконтроллеры
для управления для других
приводами специализированных
задач

Микроконтроллеры с
Микроконтроллеры с
Гарвардской
классической
архитектурой
архитектурой
(DSP-контроллеры)

Рис.6.2 Структурная схема рынка микроконтроллеров

Специализированные МК имеют в своей структуре дополнительные


периферийные схемы или функции, предназначенные специально для
использования в конкретных задачах. К группе специализированных МК
относят и контроллеры для управления приводами. Данная группа
контроллеров определяется наличием дополнительных генераторов ШИМ
сигналов, генераторов “мертвого времени”, каналов АЦП, схем прерывания,
таймеров.
Среди производителей наиболее популярных микроконтроллеров
данной серии можно отметить компании производящие микроконтроллеры
как с классической архитектурой – Intel, так и с Гарвардской архитектурой –
Texas Instruments, Analog Devices.
Отдельно выпускаются DSP-МК (DSP – Digital Signal Processor –
цифровой сигнальный процессор, подробнее о DSP процессорах см. главу 9),
ориентированные на использование в системах обработки сигналов.

4
Для справки !!! СISC- и RISC- процессоры
Микропроцессоры с традиционным набором команд – СISC-
процессоры (СISC – Complex Instruction Set Computer – компьютер с
комплексным набором инструкций). Фактически в этой структуре
реализован перенос «центра тяжести» обработки с программного
уровня системы на аппаратный.
Разработчики СISC-процессоров стремились ввести в состав
микропроцессоров как можно большее число различных
арифметических и логических устройств, сопроцессоров и т.д.,
поскольку очевидно, что аппаратная реализация какой-либо функции
обеспечивала более быстрое ее выполнение, чем программная. Да и
длина кода для реализуемых аппаратным путем функций
существенно меньше. Поэтому в 80-х годах процессоры «росли
вширь», оснащались новыми узлами, совершенствуя уже имеющиеся.
В результате появились системы команд, подобные системе
семейства х86, включающие в себя тысячи различных инструкций.
Однако, начиная с некоторого момента, СISC – технология стала
не ускорителем, а тормозом роста производительности систем. Дело в
том, что большое разнообразие команд и различная их длина
существенно усложняют аппаратуру управления внутри процессора.
Большое число действий, которое должен совершить микропроцессор
при выполнении команды, заставляло отводить под устройство
управления большую часть кристалла микросхемы (до 70 % в
процессорах х86). В результате для арифметико-логических
устройств (АЛУ), сопроцессоров и других устройств, повышающих
производительность процессора, оставалось всего 30...40 % площади
кристалла.
В RISC – процессорах «центр тяжести» перенесен на
программные средства, оставлено минимально возможное число
команд, имеющих простую и регулярную структуру. Другими
словами, в RISC – процессорах принята стратегия «длинная
программа – короткие команды» в противовес господствующей
«короткая программа – длинные команды». Аббревиатура RISC
расшифровывается как Reduced Instruction Set Computer – компьютер
с сокращенным набором команд, т. е. речь идет о процессорах,
система команд которых существенно сокращена в сравнении с
системой команд х86.
Четыре основных принципа, которые положены в основу
процессоров группы RISC:
а) любая операция, к какому бы типу она ни принадлежала,
должна выполняться за один такт;
б) операции обработки данных реализуются только в формате
«регистр – регистр». Обмен между памятью и регистрами (т. е.
модификация памяти и чтение из нее необходимых данных)
осуществляется только лишь с помощью специальных команд
чтения/записи;
в) система команд должна содержать минимальное число
наиболее часто используемых простейших команд одинаковой длины:
г) состав системы команд должен быть оптимизирован с учетом
требований компиляторов языков высокого уровня.
Реализация первого принципа осуществляется благодаря
использованию так называемого конвейера команд. С каждым из

5
тактовых импульсов на конвейер вступает новая команда, и несколько
уже обрабатываются на разных его ступенях. Одновременно, также с
каждым из тактовых импульсов, его покидает одна выполненная
команда. И хотя на выполнение каждой затрачивается по-прежнему
от четырех до семи-восьми, каждый из них сопровождается, как это и
требовалось, выполнением одной команды. Следовательно, если для
СISC-процессоров конвейер команд является необязательным (хотя и
желательным) элементом, то для RISC-процессоров он обязателен.
Отметим, что большинство RISC-процессоров имеют не один, а
несколько (от двух до четырех) конвейеров, за что они получили
название суперскалярных (в отличие от скалярных –
одноконвейерных).
Следующая особенность RISC-процессоров – высокая степень
дробления конвейера. Реально RISC-процессоры характеризуются
семидесяти ступенчатыми конвейерами. С увеличением числа
ступеней действия, выполняемые на каждой из них, все более и более
упрощаются. Последнее означает, что уменьшается число
необходимых для этого логических элементов и появляется
возможность повысить тактовую частоту процессора. Не случайно
RISC-процессоры преодолели барьер 100 МГц существенно раньше
СISC-процессоров.
Третья особенность – использование большого числа регистров.
Как правило, в RISC-процессорах их не менее 32 (около 140).
Добавим к этому, что все RISC-процессоры содержат системы
управления кэш-памятью второго уровня, позволяющие работать с
ней на максимальной скорости (в СISC-изделиях взаимодействие с
кэш-памятью обычно происходит на частоте, более низкой, чем
частота самого процессора).
Еще одна особенность RISC-процессоров – развитые средства
прогнозирования ветвлений и переходов.
Если переход предсказан неправильно, процессору необходимо
удалить со всех ступеней конвейера команды, относящиеся к неверно
сделанному предположению, и перезагрузить конвейер. Это особенно
сказывается на работе суперскалярных процессоров – на разных
ступенях трех-четырех конвейеров может находиться довольно много
команд. Поэтому RISC-процессоры характеризуются весьма
эффективными механизмами предсказания ветвлений.
Современный рынок микроэлектроники предлагает широкую
номенклатуру RISC-микроконтроллеров различных производителей,
таких как Microchip Technology Inc., Atmel, Scenix Semiconductors,
Xemics, Texas Instruments, Motorola Semiconductor,
ОАО «АНГСТРЕМ».
Сегодня наибольшая доля мирового рынка МК принадлежит
восьмиразрядным устройствам (около 50 % в стоимостном
выражении). За ними следуют 16-разрядные и DSP-МК (каждая из
групп занимает примерно по 20 % рынка). Внутри каждой группы МК
делятся на CISC- и RISC-устройства. Наиболее многочисленной
группой являются CISC-МК, но в последние годы среди новых МК
наметилась явная тенденция роста доли RISC-архитектуры.

6
Для справки !!! Историческая справка о фирме Atmel и микроконтроллерах
семейства AVR
Фирма Atmel образована в 1984 г. Джорджем и Гюстом Перлигос
в Калифорнии США.
Сначала продукцией Atmel были микросхемы энергонезависимой
памяти всех разновидностей: ЕEPROM с последовательным и
параллельным доступом, Flash.
В 1989 г. фирма впервые выпустила Flash – память с питанием от
одного напряжения – 5 В.
В конце 80-х фирмs Atmel и Intel обменялись лицензиями на
производство МК и памяти, при этом фирме Atmel была передана
лицензия на производство классического МК 8051.
Так фирма Atmel оказалась втянутой в число производителей МК,
котором она очень быстро оказалась на передовых позициях: в 1993 г.
началось производство первых в отрасли МК AT89C51 со встроенной
Flash – памятью. Это означало переворот во всей инженерной
практике, потому что существовавшие ранее МК обладали либо
однократно программируемой, т.е. памятью, либо стираемой, которая
значительно дороже в производстве и работа с ней приводит к
большим потерям времени разработчиков. Число циклов перезаписи
не превышает нескольких десятков, а прямой дневной свет, попавший
на такой кристалл, может привести к стиранию информации. Поэтому
даже мелкосерийные устройства приходилось изготавливать
преимущественно с использованием ОТР ROM, что значительно
рискованнее: изменить в случае даже малейшей ошибки записанную
программу уже было невозможно. Появление Flash – памяти
изменило состояние дел в этой области: именно в результате ее
внедрения стали возможными такие вещи, как программное
обновление BIOS компьютера или «перешивка» управляющих
программ для электронных устройств в случае их модернизации.
В 1995 г. два студента Норвежского университета науки и
технологий в г. Тронхейме, Альф Боген и Вергард Волен, выдвинули
идею 8-ми разрядного RISC-ядра, которую предложили руководству
ATMEL. Идея настолько понравилась, что в уже в 1996г. был основан
исследовательский центр ATMEL в Тронхейме и в конце того же года
выпущен первый опытный МК новой серии AVR под названием
AT90S1200. В название новой архитектуры вошли имена
разработчиков: AVR – Alf+Vergard+RISC. Во второй половине 1997г.
корпорация ATMEL приступила к серийному производству семейства
AVR.

В качестве одного из применения таких микроконтроллеров можно


назвать – построение регуляторов для управления неким объектом
регулирования, например, электроприводом (рис. 6.3).
Так как объект регулирования обычно аналоговый, то необходимо
преобразование из цифрового кода в аналоговый и обратно. Для этого в
микроконтроллере ATmega8 существует АЦП и ЦАП, что делает эти
микроконтроллера весьма выгодными конкурентами по отношению к другим
микроконтроллерам (PIC).

7
Регуля Объект
тор ЦАП регулирования

АЦП

ATmega

Рис. 6.3. Один из вариантов применения микроконтроллеров

На рис.°6.4 представлена структура микроконтроллера с вариантами


применения микроконтроллера.

Рис. 6.4. Структура микроконтроллера и примеры применения

6.1 Общие сведения о микроконтроллере ATmega8


Микроконтроллер содержит:
а) 23 программируемые линии ввода/вывода. Т.е. 23 из 28 ножек
микроконтроллера могут, как принимать, так и отдавать
определенную информацию. Что делать с этой информацией:

8
«отдавать или принимать ее?», определяется состоянием бита
управления для каждой ножки, в регистре управления этого порта;
б) два 8-разрядных таймера/счетчика (T0 и Т2). Любой таймер – это
счетчик импульсов. Только эти импульсы отстоят, друг от друга на
равные во времени отрезки. Поэтому любой таймер можно
использовать как счетчик и наоборот. Производители контроллеров
оставили этот выбор за программистом. Т.е. В каком режиме работает
данный таймер/счетчик – в режиме измерения времени или в режиме
счетчика произвольных импульсов программируется самим
программистом непосредственно в специальных регистрах
управления, где задается эта, и другая информация о режиме работы
таймера/счетчика.
в) каждый таймер/счетчик снабжен предварительным делителем.
Предварительный делитель – это устройство внутри
микроконтроллера, которое подает только кратные определенному
числу импульсы, на вход таймера/счетчика. Т.е., например, таймер
можно запрограммировать считать каждую 10-ую мкс или каждую
10-ую мс;
г) один 16-разрядный таймер/счетчик (T1) с отдельным
предварительным делителем. Этот таймер/счетчик отличается от
предыдущих двух разрядностью, т.е. максимальным числом в
регистрах счета. Итого в микроконтроллере ATmega8 существует три
таймера/счетчика (два – 8-разрядных, один – 16-разрядный);
д) один 6-канальный аналого-цифровой преобразователь (АЦП -
ADC). Из них 4 канала с 10 разрядной точностью и 2 с 8-разрядной
точностью. Переключение между входными каналами АЦП
производится с помощью регистра управления АЦП (ADMUX). В
результате чего ATmega8 может считывать 6 аналоговых сигналов, но
не одновременно, а последовательно, т.е. вначале произошло
считывание аналогового сигнала с одной ножки микроконтроллера
(с 1 канала). Это считанное значение запоминается в программе.
Затем программным путем происходит переключение входа АЦП
(например, с 1 канала на 2) и производится считывание аналогового
сигнала с другой ножки. Это значение также запоминается. Процесс
повторяется, и так далее. В результате чего скорость программы
уменьшиться в 6 раз, если использовать все 6 входов АЦП. Т.к.
программе чтобы получить информацию о шести аналоговых
сигналах необходимо произвести 6 раз преобразование аналогового
сигнал в цифровой код, а любое такое преобразование отнимает
значительную часть времени работы микроконтроллера, то время
выполнение программы увечится в 6 раз;

9
е) три канала ШИМ (PWM). Для вывода аналогового сигнала из
микроконтроллера используется не цифро-аналоговый
преобразователь (ЦАП - DAC), а ШИМ сигнал. Принцип получения
аналогового сигнала с помощью ШИМ представлен на рис. 6.5. С
помощью любого фильтра высоких частот усредняется выходное
напряжение и получается среднее аналоговое значение сигнала. Он и
служит аналоговым выходом. Правда, для получения такого сигнала
необходимо ставить фильтр высоких частот, чтобы получать среднее
значение;
Выход Задание 1
ШИМ Выход Задание 2 = 2*Задание 1
ШИМ
Среднее
Среднее значение
значение

t
t
Рис. 6.5. Принцип действия ЦАП в Atmege8
ж) микроконтроллер ATmega8 содержит 130
высокопроизводительных команд, большинство команд выполняется
за один тактовый цикл. Это значительно повышает
производительность работы микроконтроллера. Правда по сравнению
с процессором КР580В80 данный микроконтроллер содержит,
примерно, в два раза меньше число команд. Поэтому ATmega8 и
называют микроконтроллерами, а также из-за своих размеров;
и) микроконтроллер ATmega8 содержит 32 восьмиразрядных рабочих
регистра общего назначения (РОНов);
к) производительность данного микроконтроллера приближается к 16
миллионам операций в секунду (при тактовой частоте, подключенной
к соответствующим входам микроконтроллера, 16 МГц);
л) рабочая частота 0 – 16 МГц, т.е. частота, которая может быть
подана на соответствующие ножки микроконтроллера;
м) рабочее напряжение 4,5 – 5,5 В, т.е. микроконтроллер получает
однополярное питание приблизительно в 5 В. Соответственно
микроконтроллер и может выдавать сигналы только напряжением, не
превышающим 5 В. Этот сигнал необходимо усиливать перед
подачей его на любые органы управления электроприводом или
технологическим процессом. Также это обстоятельство необходимо
учитывать при подаче информации на входы микроконтроллера;
н) программы микроконтроллера может быть перезаписана до 1000
раз;
п) три программируемых последовательных интерфейса USART, TWI
и SPI, которые служат для связи этого микроконтроллера с другими
внешними устройствами;
10
р) программируемый сторожевой таймер с отдельным встроенным
генератором. Этот таймер служит для того, чтобы прервать
программу, если она «зависла».
6.2 Архитектура микроконтроллера ATmega8
ATmega8 – 8-разрядный КМОП микроконтроллер, основанный на
архитектуре AVR фирмы Atmel (Принстонская система архитектуры).
Контроллер выполняет большинство инструкций за 1 такт, поэтому
вычислительная мощность контроллера равна 1MIPS (миллиону операций в
секунду) на 1 МГц.
Микроконтроллер имеет RISC-архитектуру, но формат команды
двухоперандный, за один такт может быть обращение только к двум
регистрам.
На рис. 6.6 изображена архитектура микроконтроллера ATmega8. Суть и
назначение всех блоков в архитектуре пояснена по мере изложения
материала в этом пункте. На рис. 6.7 изображен сам микроконтроллер (вид
сверху) с номерами ножек и функциональным назначением этих ножек.

Рис. 6.6. Архитектура микроконтроллера ATmega8


Из рис. 6.7 видно, что некоторые ножки микроконтроллера несут на себе
двойную и даже тройную функцию. Цель такого совмещения – это
сэкономить число ножек микроконтроллера, т.е. уменьшить габариты
11
микроконтроллера, т.к. не все
функции микроконтроллера
используются одновременно.
Пример, если учитывать схему
подключения внешнего генератора
импульсов, которую можно заменить
конденсатором, а также, что это
схема для передачи постоянного
сигнала – не помеха, то эти ножки
можно использовать для ввода или
вывода постоянных сигналов. Еще
пример, можно запретить
микроконтроллеру использовать
сигнал Reset (ножка 1). Тогда эту
ножку можно использовать для
ввода или вывода информации в
микроконтроллер. Правда после
такой операции невозможно будет
Рис. 6.7. Назначение ножек перезаписать программу в
микроконтроллера ATmega8 микроконтроллере, т.к. чтобы
выполнить эту операцию
необходимо подать сигнал Reset.
а) PC6 (Reset) – сигнал сброса по прихода нулевого уровня (нуля вольт),
Это инверсный сигнал сброса, т.е. Reset происходит при появлении нуля
вольт на входе, а не 5В, одновременно является 6 битом порта С.
б) Ножки PD0 (RXD), PD1 (TXD) – необходимы для связи
микроконтроллера с другими устройствами по последовательному
интерфейсу UART. А также, одновременно, эти ножки являются 0 и 1
битом порта D. Ножка TXD – это выход передатчика UART. Если разрешена
работа передатчика UART, независимо от состояния бита 1 в регистре DDRD
(регистр направления передачи информации) этот вывод сконфигурирован
как выход. Ножка RXD – выход приемника UART. Если разрешена работа
приемника UART, независимо от состояния 0 бита в регистре DDRD (регистр
направления передачи информации) этот вывод сконфигурирован как
выход.
в) PD2 (INT0) и PD3 (INT1) – это входы внешних прерываний INT0 и
INT1, а также 2 и 3 бит порта D.
г) PD4 (ХСК/T0) – это счетный вход таймера/счетчика 0, если он настроен
как счетчик, а также эта ножка является 4 битом порта D.
д) VСС – питание микроконтроллера. Сюда подается сигнал в 5В. Т.к. без
питания микроконтроллер вообще не работоспособный, то эту ножку не
совместили больше ни с какими функциями.
е) GND – общий провод.

12
ж) PB6 (XTAL1/TOSC1), PB7 (XTAL2/TOSC2) – ножки подключения
внешнего генератора. Одновременно эти ножки являются входами
выходами порта В.
и) PD5 (T1) – вход таймера/счетчика 1, если он настроен на счет
импульсов, т.е. как счетчик. Одновременно – это ножка 5 порта D.
к) PD6 (AIN0) и PD7 (AIN1) – входа аналогового компаратора и
одновременно 6 и 7 бит порта D.
л) PB0 (ICP) – ножка бита 0 порта В. ICP – вход для захвата счета в
таймере/счетчики 1 по выполнению того или иного события на этой
ножке.
м) PB1 (OC1A) – 1 бит порта В и выход ШИМ сигнала таймера/счетчика 1
с А счетчиком, если он конечно подсоединен к этой ножке, и настроен как
ШИМ генератор.
н) PB2 (SS/OC1B) – 2 бит порта В, а также выход канала В
таймера/счетчика 1.
п) PB3 (MOSI/OSC2) – 3 бит порта В, ножка, необходимая для
программирования микроконтроллера, и выходная ножка ШИМ
таймера 2.
р) PB4 (MISO) – 4 бит порта В, а также ножка необходимая для
программирования микроконтроллера.
с) PB5 (SCK) – 5 бит порта В и SCK – вход для тактовой частоты SPI
внешнего соединения.
т) AVСС – напряжение питания АЦП.
у) AREF – напряжение источника внешнего опорного напряжения.
ф) AGND – общий провод для питания АЦП (0 В).
х) РС0 (ADC0) … РС3 (ADC3) – 0–3 биты порта С, и одновременно 0–3
каналы входов для АЦП.
ц) PC4 (ADC4/SDA) – 4 бит порта С, 4 канал АЦП и SDA – шина
подключения TWSI соединения с другим внешним устройством по TWSI
соединению.
ч) PC5 (ADC5/SCL) – 5 бит порта С, 4 канал АЦП и SCL – шина
подключения TWSI соединения с другим внешним устройством по TWSI
соединению.
В более ранних версиях микроконтроллеров серии AVR многие ножки
микроконтроллеров были отданы только одной единственной функции. В
результате число ножек было велико. Затем производители
микроконтроллеров нашли способ их использовать для двух функций. Это
привело к уменьшению габаритов (числа ножек), но одновременно с этим это
привело к невозможности использования одновременно всех функций.
Рассмотрим архитектуру микроконтроллера ATmega8 более подробно
(см. рис. 6.6).
На ножки VCC и GND подается напряжение питания микроконтроллера
– 5 В. На ножку AVCC, AGND подается напряжение питание мультиплексора
АЦП (MUX).

13
Мультиплексор переключает вход АЦП с одной ножки
микроконтроллера на другую. В результате чего, в микроконтроллер можно
заводить 6 аналоговых сигналов с напряжением от 0 до +5 В (ADC0 – ADC5),
но при этом используется только одно АЦП.
Порты В, С и D имеют схожую друг с другом структуру. Поэтому
рассмотрим работу только одного из портов, например, порта В.
Порт В содержит буфер, в котором хранится значение, полученное с
входов порта или значения, которые наоборот необходимо выдать на ножки
порт В. Также порт содержит устройство сопряжения буфера порта и общей
шины (PORTB DIGITAL INTERFACE). Это устройство сопрягает данные
полученные от порта В с общей шиной данных.
Остальные порты микроконтроллера имеют схожую структуру.
Единственное, что они также как и порт В несут на себе еще и
дополнительные функции, рассмотренные выше.
Основным устройством в микроконтроллере является ALU
(арифметическое логическое устройство), которое работает только с 32
регистрами – РОНами (general purpose registers) (рис. 6.8).

Внимание!!! Обратите внимание, что у порта С всего 7 битов, а не 8, как у


остальных портов (см. рис. 6.7).

Рис. 6.8. Расположение РОНов в области памяти


Эти РОНы занимают область памяти SRAM (рис. 6.9). Кроме того, 6
старших регистров образуют двухбайтные X, Y, Z регистры, которые служат
для косвенной адресации.
ALU выполняет, заданную арифметическую операцию над РОНами,
расставляет флаги в регистре статуса (SREG). И посылает результат в общую
шину.
Из общей шины полученные данные могут быть переданы любому
устройству, в том числе различным областям памяти (EEPROM, SRAM,
Flash).

14
Рис. 6.9. Распределение памяти ATmega8

SRAM – статическая оперативная память. Оперативное


запоминающее устройство статического типа SRAM предназначено для
хранения данных, получаемых в процессе работы микроконтроллера. При
выключении напряжения питания микроконтроллера данные в SRAM
теряются.
В адресном пространстве SRAM кроме адресов, по которым выполняется
обращение к ячейкам памяти SRAM, включены 32 адреса для обращения к
регистрам общего назначения РОНам (адреса от 0x00 до 0x1F) рис. 6.8 и 64
адреса для обращения к регистрам ввода-вывода (адреса от 0x20 до 0x5F)
рис. 6.9.
Flash – перезаписываемая флэш память. Постоянное запоминающее
устройство Flash предназначено для хранения кодов команд программы и
констант. Ячейка памяти содержит 16 разрядов, В ней могут храниться код
команды формата "слово" (два байта) или коды двух однобайтных констант.
EEPROM – энергонезависимая память. Постоянное запоминающее
устройство EEPROM предназначено для хранения данных, записанных при
программировании микроконтроллера и получаемых в процессе выполнения
программы. При выключении напряжения питания данные сохраняются.
Одна ячейка памяти содержит 8 разрядов. Здесь обычно хранятся какие-то
константы, к которым происходит очень редкое обращение или те данные,
которые необходимо сохранить даже при пропадании питания. Время
извлечения данных из этой области памяти в несколько раз больше чем из
других областей памяти, поэтому эту память используют редко, чтобы не
увеличивать время одного работы программы. EEPROM память данных
организована как отдельное пространство данных с возможность считывания
и записи отдельного байта или слова (два байта). EEPROM обеспечивает 100
000 циклов стирания/записи.
Кроме звена передачи информации другим устройствам данный
микроконтроллер содержит также SPI (Serial Peripheral Interface) устройство
ввода вывода и передачу байтов при обмене данными с другими
15
устройствами, имеющими порт SPI. А также последовательный порт ввода-
вывода TWSI (Two-Wire Serial Interface), который предназначен для обмена
байтами данных с другими устройствами по двухпроводной шине.
Все выше рассмотренные устройства ввода вывода информации
предназначены для передачи данных от одного устройства другому по
различным сетевым протоколам. Но так как данное учебное пособие
предназначено для изучения принципов программирования контроллеров
серии AVR, то особенности передачи данных от одного устройства другому
рассматривать не будем.
Наиболее надежный и проверенный способ сохранения данных в
EEPROM заключается в установке внешнего монитора питания,
удерживающего МК в состоянии сброса при уменьшении напряжения
питания ниже порогового уровня. Это небольшая микросхема, как правило,
трехвыводная, которая при снижении питания ниже допустимого уровня
заворачивает свой выход на «землю». Если питание в норме, то выход
находится в состоянии «разрыва» и никак не влияет на работу схемы.
6.3 Исследование системы команд микроконтроллера ATmega8
В приложении Г приведена система команд микроконтроллера ATmega8.
Систему команд можно разбить на четыре основных раздела:
В первом, разделе расположены арифметические и логические команды.
В этом разделе располагаются команды, которые выполняют
арифметические операции (сложение, вычитание, умножение, пересылку из
регистра в регистр данных) и логические операции (логическое умножение
«И» или логическое сложение «ИЛИ», отрицание и т.п.).
Во втором, разделе расположены команды безусловного перехода и
перехода по условию.
В третьем, разделе расположены команды работы с битами.
В четвертом, разделе расположены команды управления контроллером,
его режимом работы, а также команды передачи данных от одного
устройства другому. Данный раздел предназначен для специалистов хорошо
владеющих первыми тремя разделами. Поэтому этот раздел в данном
учебном пособии мы вообще не будем рассматривать. Он остается на
самостоятельное изучение, т.к. цель данного учебного пособия научить
основам работы с микроконтроллерами семейства AVR.
Структура ассемблерной программы.
Все микроконтроллеры, включая и микроконтроллер семейства AVR,
исполняют в процессе своей работы команды, двоичные коды которых
записаны в памяти программ. Исполнение программы начинается с команды,
расположенной по нулевому адресу памяти программ. Естественно, что
написание, а тем более отладка программ в двоичных кодах представляет
собой исключительно сложную задачу и весьма неудобную, решение которой
требует колоссальных затрат времени, поэтому разработчиками
микроконтроллерных систем были предложены языки программирования,
16
позволяющие использовать специальные обозначения для команд
микроконтроллера.
Для контроллеров таким языком программирования является язык
ассемблера, по сути представляющий собой совокупность правил, по
которым последовательность команд процессора, записанных в
мнемоническом коде, может объединяться в программу. Для большинства
контроллеров язык ассемблера является единственным языком
программирования. Для контроллеров семейства AVR используется также и
язык программирования С, который существенно ускоряет процессы
написания и отладки программ, однако коды программ полученные на основе
языка С получаются более длинными, нежели, полученные при применении
языка ассемблера.
Программу, написанную на языке Ассемблер или С необходимо
преобразовать в машинные коды, что выполняется в результате компиляции
программы. Компиляция ассемблерной программы выполняется
Ассемблером, переводящим текст с мнемоническими обозначениями в
последовательность команд и данных, записанных уже в двоичном формате,
и пригодном для загрузки в память контроллера.
Особенности мнемонической записи команд AVR- ассемблера такие
же, как и в любых других ассемблерах. Поэтому на этом мы останавливаться
не будем. Отметим только, что AVR-ассемблер не различает регистр букв, в
том числе и в присвоенных программистом именах переменных, констант,
меток и т.д.
Числа по умолчанию считаются десятичными, за исключением числа
с ведущим нулем, которые, если не имеют дополнительных признаков,
воспринимаются как восьмеричные.
Шестнадцатеричные числа можно записывать двояким способом:
0х0А или $0A.
Двоичные числа записываются следующим образом: 0b01001000.
Рассмотрим команды первого раздела. Исследование будем проводить
на простейших примерах с использованием приложения Г.
Пример 6.1. LDI r16,0x0F ;Загрузить в регистр r16 число 0F в Hex формате
Арифметическое LDI r17,0xFF ;Загрузить в регистр r17 число FF
сложение ADD r16,r17 ;r16=r16+r17, т.е. в r16 число 0E
ADC r16,r17 ;Прибавить к r16 еще раз 0F, но кроме того,
;прибавить еще
;флаг С, т.е. r16=0Е+FF+1=0E
Пример 6.2. LDI r16,0x0F ;Загрузить в регистр r16 число 0F в Hex
формате
LDI r17,0xFF ;Загрузить в регистр r17 число FF
ADD r16,r17 ;r16=r16+r17, т.е. в r16 число 0E
ADC r16,r17 ;Прибавить к r16 еще раз 0F, но кроме того,
;прибавить еще флаг С, т.е. r16=0Е+FF+1=0E
Первыми двумя командами заносятся первоначальные данные
в регистры. Затем в третей строке происходит сложение двух
чисел без учета флага С. Но флаг С при этом становится равным 1,
т.к. в результате сложения произошло переполнение и ALU
17
выставил флаг С в 1состояние (регистр SREG). Поэтому в
последней команде результат не изменится, т.к. FF+01=00
(разрядность ограничена одним байтом).
Пример 6.3. LDI r16,0xFF ;Загрузить в регистр r16 число FF
Арифметическое LDI r17,0xF0 ;Загрузить в регистр r17 число F0
вычитание LDI r18,0x0F ;Загрузить в регистр r18 число 0F
SUB r16,r17 ;r16=r16-r17, т.е. в r16 число 0x0F
SUBI r16,0x0E ;r16=r16-0E=0х01
SBC r18,r16 ;r18=r18-r16=0x0F-0x01, т.е. в r18 число 0x0E.
SBCI r18,0xF0 ;r18=r18-F0=01-F0=0x1Е, т.е. в r18 число 0x1Е
Первыми тремя строками происходит загрузка регистров
числами. Затем выполняется команда вычитания содержимого одного
регистра из другого. Обратите внимание, что флаг С примет значение
0. Даже если он имел перед этой командой не нулевое, т.е. единичное,
значение. В последней строке происходит вычитание числа из
содержимого регистра. При этом флаг С устанавливается в 1, т.к.
произошло переполнение при вычитании.

Пример 6.4. LDI r16,0xFF ;Загрузить в регистр r16 число FF


Логическое LDI r17,0xF0 ;Загрузить в регистр r17 число F0
сложение и LDI r18,0x0F ;Загрузить в регистр r18 число 0F
умножение AND r16,r17 ;r16=r16&r17, т.е. в r16 число F0
ANDI r16,0xE8 ;r16=r16&E8, т.е. в r16 число E0
OR r18,r16 ;r18=r18\/r16, т.е. в r18 число EF
ORI r18,0xF0 ;r18=r18\/F0=EF\/F0=FF, т.е. в r18 число FF.
Первые три строки – знакомы, поэтому в дальнейшем опустим
их из описания. В четвертой строке выполним команду логического
умножения, т.е. И (&). В результате чего, в регистре r16 останутся
число F0. Следующей командой происходит логическое умножение
уже не с содержимым регистра, а с числом, непосредственно
заданным в программе. Ответ этого действия – 0E. В следующей
строке происходит операция логического сложения (или). Ответ – EF.
В последней строке происходит логическое сложение, но уже с
числом, непосредственно заданным в программе. Ответ – FF.
Пример 6.5. LDI r16,0xFF ;Загрузить в регистр r16 число FF
Исключающее LDI r17,0xF0 ;Загрузить в регистр r17 число F0
ИЛИ LDI r18,0x0F ;Загрузить в регистр r18 число 0F
EOR r16,r17 ;r16= r16 + r17, т.е. в r16 число 0x0F
COM r16 ;r16=FF – r16=FF-0F=F0, т.е. в r16 число 0xF0
NEG r16 ;r16=00 - r16=00 – F0=10, т.е. в r16 число 0x10
SBR r16,0xF0 ;r16=r16\/F0=10\/F0=F0
CBR r16,0xEF ;r16=r16&(FF-EF)=10&10=10
В этом примере представлено использование команды
исключающего ИЛИ (EOR). Также приведены команды вычитание из
-1 (FF) и нуля.
После использования любой команды всегда необходимо следить за
состоянием флагов регистра статуса SREG. А также за числом тактов,
которые затратит процессор на выполнение той или иной операции. Так одно
и тоже действия можно выполнить различными способами, но процессор
затратит разное время на их выполнения.
Пример 6.6. LDI r16,0xFF ;Загрузить в регистр r16 число FF
18
Инкремент и LDI r18,0x0F ;Загрузить в регистр r18 число 0F
декремент INC r16 ;r16=r16+1, т.е. в r16 число 00
DEC r16 ;r16=r16-1, т.е. в r16 число FF
CLR r18 ;r18=00
SER r18 ;r18=FF
Изучив этот пример, запоминаем как можно быстро увеличить,
или уменьшить содержимое регистра на 1, а также как можно быстро
обнулить содержимое регистра, или, наоборот, записать во все биты 1.
Это самый быстрые и оптимальные способы очистки, уменьшения или
увеличения байта на 1.

Пример 6.7. LDI r16,0x0F ;r16=0F


Умножение LDI r17,0x0F ;r17=0F
LDI r18,0x01 ;r18=01
MUL r16,r18 ;Перемножить два числа в результате в регистрах
;r1:r0=0F×01=00:0F, т.е. в r1=00 r0=0F
FMUL r16,r18 ;r1:r0=0F×01<<1=00:1E, т.е. в r1=00 r0=1E
В этом примере произведено перемножение двух чисел. С
последующим сдвигом на 1 бит. Обратите внимание, что результат
всегда записывается только в определенные два регистра. Т.е.
регистры r1:r0 – это своеобразный аккумулятор. Откуда содержимое
этих регистров необходимо переносить, чтобы не потерять при
следующих операциях, использующих эти регистры.
Среди команд необходимо выделить операции работы с битами
(битовые операции), т.к. очень часто требуется работать программисту не с
целым байтом, а с одним лишь битом.
Пример 6.8. LDI r16,0x01 ;Загрузить в r16 число 01
Команды сдвига LDI r16,0x01 ;r16=01
LSL r16 ;Сдвиг влево 5 раз
LSL r16
LSL r16
LSL r16
LSL r16
LSR r16 ;Сдвиг вправо 1 раз LDI r16,0x0F ;r16=0F
В результате действия этой программы в регистре r16 будет
число 0х10.
Теперь рассмотрим операции установки флагов. Флаги очень важная
часть микроконтроллера. Более подробно о том какие есть флаги в
микроконтроллере ATmega8 можно изучить в приложении Г.
Пример 6.9. SEV ;Установить флаг V = 1 в регистре SREG
Установка бит в SEI ;Установить флаг I (глоб. прерываний) в 1
регистрах SBI PORTB,0 ;Установить биты в регистрах подтягивающих
управления SBI PORTC,1 ;резисторов портов В, С, D
SBI PORTD,2
В первой части этого примера использованы команды, которые
вообще не используют ни какие регистры. Вернее используют регистр
SREG, но об этом микроконтроллер уже получил информацию в коде
этой команды, т.е. написав команду установки или обнуления флага в
регистре SREG. Микроконтроллер знает: «что делать?» (установить
или сбросить бит в SREG) «Над чем делать?» (заданный бит регистра
SREG) «Куда послать результат?» (в регистр SREG) «Что делать
19
дальше?» (следующая команда). Эти команды занимают один байт в
памяти микроконтроллера и выполняются за один такт. Во второй
части, примера используется команда установки бита в других
регистрах управления. Следует обратить внимание, что
производители микроконтроллера учли тот факт, что регистр статус
SREG также является регистром управления микроконтроллера.
Поэтому запись SBI SREG,0 - приведет к ошибке.
Рассмотрим теперь примеры с командами перехода и ветвления. Это
основные команды любой программы.
Пример 6.10. START:
Ветвление и LDI r16,0xF0
переход LDI r17,0x0F ;Загрузка начальных условий
LDI r30,0xFF
LDI r31,0x00
IJMP ;Перейти на адрес [Z]=[r31:r30]
ADD r16,r17 ;Сложить содержимое регистров r16 и r17
.ORG 0x 00 FF ;Указать, что адрес 00FF здесь
RJMP b1 ;перейти на метку b1
LDI r16,0x0E ;записать в r16 число 0Е. Эта команда
;никогда не будет выполнена, т.к. предыдущая команда всегда ее
;обходит
b1:
ADD r16,r17
RJMP START

Пример 6.11. START:


LDI r16,0xF0
LDI r17,0x0F ;Загрузка начальных условий
LDI r30,0xFF
LDI r31,0x00
IJMP ;Перейти на адрес [Z]=[r31:r30]
ADD r16,r17 ;Сложить содержимое регистров r16 и r17
.ORG 0x 00 FF ;Указать, что адрес 00FF здесь
RJMP b1 ;перейти на метку b1
LDI r16,0x0E ;записать в r16 число 0Е. Эта команда никогда
;не будет выполнена, т.к. предыдущая команда всегда ее обходит
b1:
ADD r16,r17
RJMP START
Команды безусловного перехода RJMP и IJMP отличаются тем,
что одна указывает на метку в программе, а другая на адрес,
записанный в регистре Z.
В этом примере, если убрать команду IJMP, то в r16 было бы
записано число FF, а только потом произошел бы переход на метку b1.
С помощью этих команд легко переходить из одной области
программы в другую. Чаще всего используют команду RJMP. Это
команды безусловного перехода, т.е. перехода в любом случаи,
несмотря ни на что. Последняя команда возвращает программу на
начало и все повторяется.

20
Теперь рассмотрим примеры с переходом по условию. Команд перехода
по условию большое разнообразие одни переходят на метку (относительный
переход), другие пропускают следующую команду, только в том случаи, если
какое-то условие было выполнено. Поэтому рассмотрим только часть команд
из этого большого разнообразия. Остальные команды предлагается изучить
по аналогии самостоятельно.
Пример 6.12. LDI r16,0xFF
Команды LDI r17,0x03 ;Загрузка начальных условий
условного m2:
перехода MOV r19,r18 ;Загрузить в r19 содержимое r18
CPSE r18,r19 ;Сравнить содержимое регистров и если они равны,
;то пропустить сл. команду, т.е. RJMP
RJMP m1 ;Переход на метку m1
CP r17,r16 ;сравнить регистры r17 и r16. Расставить флаги
BREQ m1 ;Если флаг Z=1, то на метку m1
LDI r18,0x01 ;Записать в r18 число 01
BRCS m1 ;Т.к. флаг С=1, то происходит переход на m1
LDI r16,0x02 ;Записать в r16 число 02
m1:
RJMP m2 ;переход на метку m2
Теперь рассмотрим пример – как создавать циклы с помощью команд
ветвлений на ATmega.
Пример 6.13. ;-------------------------начальные условия цикла--------------------
Цикл типа FOR LDI r16,0x03 ;Загрузить число выполнений цикла
m1:
;-------------------------Тело цикла---------------------------------------
INC r17 ;Увеличит содержимое регистра r17 на 1

;-------------------------конец цикла-------------------------------------
DEC r16 ;Уменьшить глубину (регистр r16) цикла на 1
BRNE m1
В этом примере рассмотрен процесс создания цикла, который
работает следующим образом. В какой-то регистр помещается число,
соответствующее числу выполнения массива. В примере это регистр
r16. Затем выполняется тело цикла. В примере это прибавление 1 к
регистру r17. Цикл заканчивается тем, что уменьшается число
выполнений массива. При этом расставляются флаги. Последующая
строка выполняет проверку флага Z, если значение r16 еще не ноль, то
происходит переход на начала цикла. Все повторяется до тех пор пока
значение регистра r16 не станет равным нулю. Тогда перехода не
произойдет и программа пойдет дальше. В результате видим, чтобы
создать цикл, необходимо создать три его части: начало цикла, т.е. ту
часть, где происходит установка начальных условий; тело цикла, куда
необходимо поместить те команды, что следует повторить; и, наконец,
конец цикла.
Пример 6.14. LDI r16,0x03 ;Загрузить число выполняемых циклов
Цикл типа while m1:
INC r17 ;Увеличит содержимое регистра r17 на 1
CP r16,r17 ;Сравнить содержимое регистров r16 и r17
BRNE m1 ;Если они равны, то дальше, иначе повторять цикл
В этом примере цикла типа while происходит сравнение двух
21
регистров и расстановка флагов. Этот пример показывает, что не имеет
ни какой разницы, каким образом был установлен флаг, чтобы
зациклить программу. А также он показывает цикл типа while, т.к. если
в тело цикла включить строку скажем CLR r17, то этот цикл не
закончится никогда, т.к. r17 никогда не будет равен r16.
6.4 Работа портов микроконтроллера на прием и выдачу информации
Теперь следует рассмотреть внешние порты управления контроллера (В,
С, D), т.е. научится заводить и выводить информацию из микроконтроллера.
В контроллере ATmega 8 существует только 23 ножки на ввод и вывод,
разбитые на три порта B, C и D. Непонятно почему название началось с
буквы В, а не А. Как в других микроконтроллерах серии. Следует обратить
внимание, что порт С содержит не 8 ножек, как остальные, а только 7.
Каждый порт содержит три регистра:
а) регистры направления вывода/ввода информации DDRD, или
DDRB, или DDRC. Если бит в регистрах установлен, то информация,
с соответствующей биту ножке, – выдается, если сброшен, то
информация – вводится;
б) регистр управления подтягивающими резисторами PORTB,
PORTC, PORTD (рис. 6.10), которые необходимы для стабилизации

VCC

Шина данных
PORT

Подтягивающий
резистор

PIN
Рис. 6.10. Подтягивающие резисторы

уровня сигнала на входе микроконтроллера.


в) существует регистры мгновенных значений потенциалов на входах
портов B, C, D – DINB, DINC, DIND.
Внимание !!! Если вывод порта сконфигурирован как выход, то его переключение
производится через регистр данных (PORTB, PORTC, PORTD), если вывод
сконфигурирован как вход, то его опрос следует производить через
регистр выводов входа порта (PINB, PINC, PIND)

22
Рассмотрим схему подключения
выводов микроконтроллера к реле.
Особенностью данного подключения
являются два факта. Первое, напряжение
питание выходных ножек
микроконтроллера составляет всего 5
В, а также тот факт, что ток на
выходе микроконтроллера не может
превышать 20мА. В результате
максимальная мощность на одной ножке
не превышает 0.1Вт. Поэтому
необходимо подключение усилителей
Рис. 6.11. Подключение реле мощности, например, транзисторов.
Второе, реле – это индуктивность,
поэтому для защиты транзистора к
каждому реле необходимо подключить
диод, как показано на рис. 6.11.
Теперь рассмотрим схему
подключения светодиодов к выводам
микроконтроллера (рис.6.12).
Если рассмотреть схему рис. 6.12, то
видим, что первый светодиод загорится,
если на выходе микроконтроллера будет
0 (0 В), а второй когда будет 1 (+5 В). В
симуляторе микроконтроллера, на
котором и предлагается пройти
обучения, все светодиоды собраны по
схеме светодиода VD2.
Теперь изучим схему подключения
семисегментного индикатора к
Рис. 6.12. Подключение светодиодов микроконтроллеру рис. 6.12. Откуда
видим, что семисегментный индикатор
содержит не семь светодиодов, как следует из названия, а 8. И не 7 ножек
для подключения, а 14 (модель – hp5082-7730). Здесь 8-мой ножкой
(индикатор dp) является точка на индикаторе.
Считаем, что +5 В уже подано на ножку 14(А) семисегментного
индикатора, поэтому, если ножки порта В и С микроконтроллера
сформировать как выход, т.е. записать в регистры DDRB и DDRD число
0xFF, а в регистры PORTB число 0xFE, а в регистре PORTC число 0xFE,
тогда на ножки 13 и 10 семисегментного индикатора будет подано 0 В, а на
остальные ножки будет подано +5 В. В результате на индикаторе (рис. 6.13)
загорится символ «1».

23
Рис. 6.13. Схема подключения семисегментного индикатора к
микроконтроллеру

Пример 6.15. .INCLUDE "m8def.inc" ;Загрузить файл констант для ATmege8


Зажигание двух .CSEG ;Начало сегмента кода
чисел 0 и 1 на ;Непосредственно программа
семисегметных ;--------------------------------------
индикаторах LDI r16,0xFF ;Порт В и С на вывод
OUT DDRB,r16
OUT DDRC,r16
CLR r16 ;Записать 0 в порт В
OUT PORTB,r16
LDI r16,0x04 ;Записать 04 в порт С
OUT PORTC,r16
;-------------------------------------
.EXIT ;Конец сегмента кода

Пример 6.16. .INCLUDE "m8def.inc" ;Загрузить файл констант для ATmege8


.CSEG ;Начало сегмента кода
;Непосредственно программа
;--------------------------------------
LDI r16,0xFF ;Порт В и С на вывод
OUT DDRB,r16
OUT DDRC,r16
CLR r16 ;Записать 0 в порт В
OUT PORTB,r16
LDI r16,0x04 ;Записать 04 в порт С
OUT PORTC,r16
;-------------------------------------
.EXIT ;Конец сегмента кода

24
Пример 6.17. Пусть необходимо запрограммировать ворота гаража. Управление
Программа этими воротами производится с помощью микроконтроллера ATmega8.
открытия/за При нажатии и удержании кнопки SB3 ворота открываются, о чем
крытия свидетельствует зажигание светодиода VD5 и на семисегметных
ворот индикаторах загорается число 0E (OPEN). При появлении сигнала (SA1)
крайнего открытого состояния ворот, двигатель открывания ворот
останавливается, на семисегметных индикаторах загорается число 00,
светодиод VD5 гаснет. Крайнее открытое состояние и крайне закрытое
состояние определяется состоянием тумблеров SA1 и SA2, которые
имитируют работу концевых выключателей. При открывании ворот на
индикаторах загорается число 0E, при закрывании – СE.
.INCLUDE "m8def.inc" ;Подключение файла констант ATmega8
.CSEG ;Начала сегмента кодов
.START: ;Метка начала программы
LDI r16,0xFC
OUT DDRB,r16;инициализация порта В (2 мл.бита на вход. Ост. на
;выход)
OUT DDRC,r16 ;инициализация порта С (2мл.бита на вход. Ост. ;на
выход)
LDI r16,0x06
OUT DDRD,r16 ;Инициализация 1 и 2 бита порта D на выход
IN r16,PINB ;Считать содержимое порта В в регистр r16
SBRC r16,0 ;Если бит 0 порта В сброшен в 0, то пропустить,
; иначе на OPEN
RJMP OPEN
SBRC r16,1 ;Если бит 1 порта В сброшен в 0, то пропустить,
RJMP CLOSE;иначе на CLOSE
STOP: ;Подпрограмма останова ворот
CLR r16
OUT PORTB,r16 ;Погасить все светодиоды и индикация 00
OUT PORTC,r16
OUT PORTD,r16
RJMP START ;Переход на начало программы
OPEN: ;Подпрограмма движения – открывание ворот
IN r16,PINC ;Считать содержимое порта С
SBRC r16,0 ;Если ворота в открытом состоянии, то идти на STOP
RJMP STOP
LDI r16,0x00 ;Первый символ открытия – «0»
LSL r16 ;Два раза сдвинуть влево, т.к. дешифратор подключен
LSL r16 ; к 4 битам порта В, начиная со второго
OUT PORTB,r16
LDI r16,0x0E ;Второй символ открытия – «Е»
LSL r16 ;Два раза сдвинуть влево, т.к. дешифратор подключен
LSL r16 ; к 4 битам порта С, начиная со второго
OUT PORTC,r16 ;Выдать на PORTC
LDI r16,0x04 ;Сигнал на открытие ворот, т.е. на светодиод VD5
OUT PORTD, r16
RJMP START
CLOSE: ;Подпрограмма закрытия ворот
IN r16,PINC ;Считать содержимое порта С
SBRC r16,1 ;Если ворота в крайнем закрытом состоянии,
RJMP STOP ;то идти на подпрограмму останова
25
LDI r16,0x0C ;Первый символ закрывания ворот – «С»
LSL r16 ;Два раза сдвинуть влево
LSL r16
OUT PORTB,r16
LDI r16,0x0E ;Второй символ – «Е»
LSL r16 ;Два раза сдвинуть влево
LSL r16
OUT PORTC,r16
LDI r16,0x08 ;Сигнал на открытие ворот, т.е. на светодиод VD6
OUT PORTD,r16
RJMP START ;Идти на начало
.EXIT ;Конец программы
Вместо светодиодов на микроконтроллер можно подключить реле,
управляющее двигателем открывания и закрывания ворот гаража. А
вместо тумблеров SA1 и SA2 подключить датчики пути (концевые).

Пример 6.18. В некоторых устройствах, применяемых в электроприводах, используется


Перевод не двоичный код, а код Грея. Но в контроллерах используется двоичный код. В
инверсного качестве примера можно назвать абсолютный энкодер, выдающий положения
кода Грея в вала ротора в коде Грея, сигнал с этого энкодера необходимо преобразовать в
двоичный двоичный код, а только затем использовать в системе управления двигателем.
код Перевод Кода Грея в двоичный код проведем согласно таблицы 1. Особенность
этого кода в том, что он более устойчив к помехам, т.к. в нем нет комбинаций где
все биты 111 или все биты 0. Так как в микроконтроллере нет специальных
команд перевода, поэтому перевод будем выполнять побитно, т.е. будем
определять значение бита в предыдущей операции и нынешнее положение бита,
и будем устанавливать в 1 или сбрасывать в 0 выходной бит в зависимости от
значения этих бит.
.INCLUDE "m8def.inc" ;Подключение файла констант ATmega8
.CSEG ;Начала сегмента кодов
START: ;Метка начала программы
;--------------------------------------------------------------
LDI r16,0x00 ;Инициализация входов/выходов
OUT DDRD,r16;Вход – подключение энкодера
LDI r16,0xFF ;Выход
OUT DDRС,r16
;--------------------------------------------------------------
a:
IN r18,PIND ;Код с энкодера
;-------- Перевод инвер. кода Грея в BIN--------------------------------------
MOV r27,r18 ;Сохранить в другом регистре считанный код,
;чтобы не испортить его в дальнейшем преобразовании
;--------------Вычисление 2 бита ---------------
SBRS r27,2
RJMP k17
SBRS r25,3
RJMP k18
;---------------- 3-1 2-1 -----
ORI r25,0x04
RJMP k20
k18:
;---------------- 3-0 2-1 -----
ANDI r25,0xFB
RJMP k20
k17:
26
SBRS r25,3
RJMP k19
;----------------- 3-1 2-0 -----
ANDIi r25,0xFB
RJMO k20
k19:
;----------------- 3-0 2-0 -----
ORI r25,0x04
k20:
;--------------Вычисление 1 бита ---------------
SBRS r27,1
RJMP k21
SBRS r25,2
RJMP k22
;---------------- 2-1 1-1 -----
ORI r25,0x02
RJMP k24
k22:
;---------------- 2-0 1-1 -----
ANDI r25,0xFD
RJMP k24
k21:
SBRS r25,2
RJMP k23
;----------------- 2-1 1-0 -----
ANDIi r25,0xFD
RJMP k24
k23:
;----------------- 2-0 1-0 -----
ORI r25,0x02
k24:
;--------------Вычисление 0 бита ---------------
SBRS r27,0
RJMP k25
SBRS r25,1
RJMP k26
;---------------- 1-1 0-1 -----
ORI r25,0x01
RJMP k28
k26:
;---------------- 1-0 0-1 -----
ANDI r25,0xFE
RJMP k28
k25:
SBRS r25,1
RJMP k27
;----------------- 1-1 0-0 -----
ANDI r25,0xFE
RJMP k28
k27:
;----------------- 1-0 0-0 -----
ORI r25,0x01
k28:
MOV r18,r25
RJMP a
.EXIT

27
6.5 Работа с памятью SRAM микроконтроллера
Для работы со статической памятью SRAM необходимо пользоваться
командами LD и ST, которые позволяют производить чтение (LOAD) и запись
(SAVE) байта памяти SRAM.
Пример 6.19. Очень часто в программах программисту необходимо использовать
Работа с целые массивы чисел, которые необходимо где-то хранить. Для этих
памятью целей хорошо подходит память микроконтроллера. Например, SRAM.
SRAM Научимся считывать и записывать в нее байты информации.
.INCLUDE "m8def.inc" ;подключение файла настроек для ATmega8
.CSEG
CLR r27 ;Задание начального адреса 0x0070
LDI r26,0x70
a:
LDI r17,0xFF ;Запись числа FF в ячейку памяти с
ST X+,r17 ; последующим увеличением адреса этой
ячейки
RJMP a
.EXIT
Проанализировав эту программу и заменив команду ST на LD, получаем
обратный эффект, т.е. чтение из SRAM.
Используя команды ST и LD и косвенные регистры X, Y, Z, легко производить
чтение/запись из/в память.
6.6 Прерывания ATmega8
Внутри микроконтроллера или в связанной с ним внешней среде
могут возникать разнообразные события, которые требуют немедленной
реакции на свое появление, т.е. временной приостановки процесса
обработки основной программы («прерывания») и выполнения другой
программы (процедуры), предназначенной для обслуживания возникшего
события. Соответственно такие события называются прерывающими
событиями. Реакция микроконтроллера на внешнее событие должна
завершаться возвратом к основной программе (рис. 6.14).

Рис.6.14
Совокупность аппаратных и программных средств
микроконтроллеров, предназначенных для организации и обслуживания
прерываний, образует систему прерываний.
Все микроконтроллеры семейства AVR, в том числе и ATmega8, имеют
многоуровневую векторную систему приоритетных прерываний.
Прерывание от внешнего устройства или какого-нибудь внутреннего
устройства микроконтроллера – это просьба прекратить выполнение текущей
программы и перейти на прерывающую подпрограмму с известным адресом.
28
Каждому запросу уже в начале программы присвоен адрес. Здесь можно
расположить только одну команду, например, RJMP, т.е. перейти на
подпрограмму, где уже может располагаться вся подпрограмма выполнения
данного прерывания. В микроконтроллере ATmega8 запретили менять
приоритеты запросов. Они жестко фиксированы адресами. Чем адрес
прерывания младше тем более высокого приоритета прерывания. Самый
высокий приоритет имеет Reset.
Полный перечень векторов прерываний представлен в таблице 6.1.
Перечень представляет также уровень приоритета для каждого прерывания.
Прерывания с младшими адресами имеют больший уровень приоритета.
RESET имеет наивысший уровень приоритета, следующим является INT0 –
Запрос внешнего прерывания 0 и т.д.
Микроконтроллер ATmega8 использует 19 источников прерываний. Эти
прерывания располагают отдельными программными векторами в области
пространства памяти программы. Каждому прерыванию присвоен свой бит
разрешения в регистре масок прерываний, который должен быть установлен
совместно с битом I регистра статуса (SREG). Т.е., есть бит I, который
разрешает прерывания в принципе, а затем необходимо разрешить
конкретное прерывание в регистре масок прерываний.

29
Таблица 6.1 – Таблица векторов прерываний
№ Адрес Источник Комментарии
1 0x000 RESET Сброс по выводу и сторожевому таймеру (Hardware
Pin and Watchdog Reset)
2 0x 001 INT0 Запрос внешнего прерывания 0 (External Interrupt
Request 0)
3 0x 002 INT1 Запрос внешнего прерывания 1 (External Interrupt
Request 1)
4 0x 003 TIMER2 COMP Совпадение при сравнении таймера/счетчика 2
(Timer/Counter2 Compare Match)
5 0x 004 TIMER2 OVF Переполнение таймера/счетчика 2 (Timer/Counter2
6 0x 005 TIMER1 CAPT Overflow)
Захват таймера/счетчика 1 (Timer/Counter1 Capture
Event)
7 0x 006 TIMER1 Совпадение A при сравнении таймера/счетчика 1
COMPA (Timer/Counter1 Compare Match A)

8 0x 007 TIMER1 Совпадение B при сравнении таймера/счетчика 1


COMPB (Timer/Counter1 Compare Match B)

9 0x 008 TIMER1 OVF Переполнение таймера/счетчика 1 (Timer/Counter1


10 0x 009 TIMER0 OVF Overflow)
Переполнение таймера/счетчика 0 (Timer/Counter0
Overflow)
11 0x 00A SPI, STC Завершение пересылки SPI (SPI Serial Transfer
12 0x 00B UART, RXD Complete) приема UART (UART, Rx Complete)
Завершение
13 0x 00C UART, UDRE Регистр данных UART пуст (UART Data Register
Empty)
14 0x 00D UART, TXD Завершение передачи UART (UART, Tx Complete)

15 0x 00E ADC Завершение ADC преобразования (ADC Conversion


16 0x 00F EE READY Complete)
Готовность EEPROM (EEPROM Ready)

17 0x 010 ANALOG Срабатывание аналогового компаратора (Analog


COMP Comparator)
18 0x 011 TWI Two ware serial interface
19 0x 012 SPM_RDY Загрузка программной памяти готова
Среди многообразия прерываний, есть такое особенное – прерывание
захвата. Т.е. при появлении сигнала на определенной ножке
микроконтроллера происходит запись счетного регистра таймера/счетчика 1
в специальные регистры захвата. Данное прерывание можно использовать
как еще одно внешнее прерывание.
Следующая группа прерываний – это прерывания обработки данных
передаваемых другими внешними устройствами (прерывания 11-14 и 18-19).
Данные прерывания не рассматриваем, т.к. данное учебное пособие
посвящено изучению основ микроконтроллера.

30
Прерывания АЦП возникает при завершении преобразования
аналогового сигнала в цифровой сигнал (прерывание 15). Прерывание
компаратора возникает при завершении сравнения двух аналоговых чисел
(прерывание 17).
Среди всех прерываний можно выделить группы прерываний, которые
наиболее важные для нас, как исследователей основ программирования
микроконтроллеров серии AVR. Это внешние прерывания (прерывание 2 и
3) т.е. прерывания, которые происходят при появлении какого-то сигнала
высокого или низкого уровня на соответствующих ножках
микроконтроллера.
Прерывания таймеров (прерывания с 4 по 10), которые можно
разделить на прерывания сравнения, т.е. прерывания, которые возникают при
совпадении счетного регистра таймера с уставкой этого таймера, прерывания
переполнения, которые возникают, если счет таймера превысил разрядность
этого таймера.
Обработка прерываний. В микроконтроллере ATmega8, среди всего
многообразия прерываний, можно выделить два основных вида прерываний
внешние (куда входят прерывания от INT0 и INT1), т.е. прерывания от
внешних источников, и внутренние, т.е. прерывания от различных блоков
микроконтроллера (таймеров, АЦП, регистры передачи данных, …).
Микроконтроллеры ATmega8 содержат два специальных 8-разрядных
регистра масок прерываний: регистр масок внешних прерываний GICR
(General Interrupt Control Registr) и регистр масок прерываний по
таймеру/счетчику TIMSK (Timer/Counter Interrupt Mask). Регистр масок – это
специальный регистры управления микроконтроллером, где указывается
какие прерывания разрешены, а какие – нет. Т.е. здесь указывается
микроконтроллеру на какие прерывания обращать внимание, а на какие нет.
Бит I должен быть установлен в 1, если в программе используются
прерывания, независимо от того, какие прерывания разрешены, ак какие нет
в регистрах масок прерываний.
При возникновении прерывания бит I разрешения глобального
прерывания (Global Interrupt Enable) очищается и все прочие прерывания
запрещаются. Программист с тем, чтобы разрешить вложенные прерывания,
может установить бит I внутри подпрограммы обработки прерывания. Выход
из подпрограммы обработки прерывания происходит по команде RETI, при
этом бит I устанавливается в состояние 1.
Внешние прерывания. Чтобы управлять внешними прерываниями
существует три специальных регистра:
а) MCUR (MCU Control Register)– регистр управления внешними
прерываниями;
б) GICR – регистр масок внешних прерываний;
в) GIFR – регистр флагов внешних прерываний.

31
Регистр MCUCR определяет режим работы прерывания. По какому
уровню будет происходить прерывание по высокому (1) или по низкому (0)
уровню (таблица 6.2).
Таблица 6.2 – Регистр управления внешними прерываниями MCUCR
Бит 7 6 5 4 3 2 1 0
Чтение / R/W R/W R/W R/W R/W R/W R/W R/W
Запись
Номер SE SM2 SM1 SM0 ISC11 ISC10 ISC01 ISC00
перыв.
Нач.знач. 0 0 0 0 0 0 0 0
Bit 7 – SE: Этот бит говорит о необходимости ожидать прерывания от
внешнего источника и программа ничего при этом не выполняет. Этот бит
используется в режиме SLEEP (энергосберегающий режим – «режим сна»).
Bit 6-4 – SM2, SM1, SM0: Выбирают режим ожидания. В этом учебном
пособии не рассматриваются, т.к. рассматриваются только основные режимы
работы.
Bit 3-2 – ISC11, ISC10: Определяют уровень срабатывания внешнего
прерывания INT1 согласно таблице 6.2. Так здесь два бита, то можно
получить 4 комбинации вариантов уровня срабатывания прерывания.
Таблица 6.2 – Выбор уровня срабатывания прерывания INT1
ISC11 ISC10 Комментарий
0 0 Низкий уровень INT1 генерирует запрос на прерывание

0 1 Любое логическое изменение на INT1 генерирует запрос на


прерывание.
1 0 Задний фронт INT1 генерирует запрос на прерывание.
1 1 Передний фронт INT1 генерирует запрос на прерывание.

Bits 1-0 ISC01, ISC00: – Определяют уровень срабатывания внешнего


прерывания INT0 согласно таблице 6.4.
Таблица 6.4 – Выбор уровня срабатывания прерывания INT0
ISC01 ISC00 Комментарий
0 0 Низкий уровень INT0 генерирует запрос на прерывание
0 1 Любое логическое изменение на INT0 генерирует запрос на
прерывание.
1 0 Задний фронт INT0 генерирует запрос на прерывание.
1 1 Передний фронт INT0 генерирует запрос на прерывание.
Оперируя только 4-мя последними битами, определяем уровень
срабатывания внешнего прерывания INT1 и INT0.

32
Теперь рассмотрим следующий регистр управления прерываниями –
регистр GICR, который выставляет маски на внешние прерывания
(таблица 6.5), т.е. запрещает или разрешает эти внешние прерывания.
Таблица 6.5 – Регистр масок внешних прерываний GICR
Бит 7 6 5 4 3 2 1 0
Чтение / R/W R/W - - - - R/W R/W
Запись
Номер INT1 INT0 - - - - IVSEL IVCE
перыв.
Нач.зна 0 0 0 0 0 0 0 0
ч
Bits 7, 6 – INТ1, INT0: - Разрешение запроса внешних прерываний 1 и 0.
При установленных битах INT1, INT0 и установленном бите I регистра
статуса (SREG) разрешаются прерывания по соответствующим выводам
входов сигналов прерываний.
Для того, чтобы не произошло повторного прерывания. Т.е. прерывания
самого себя. Существует регистр флагов внешних прерываний GIFR. Это
третий регистр управления внешними прерываниями. Здесь флаг,
соответствующий данному прерыванию устанавливается в 1, если произошло
прерывание именно этого прерывания. И пока это прерывание не будет
обработано, новое прерывание не произойдет. В таблице 6.6 представлен
регистр GIFR с функциями битов. Как можно видеть из таблицы, если
произошло прерывание по внешнему прерыванию INT1, то бит 7 в регистре
GIFR будет установлен. Аналогично происходит, если пришло прерывание
от INT0. Остальные биты регистра не используются. Они отведены для
использования в других моделях микроконтроллеров серии AVR.
Таблица 6.6 – Регистр флагов внешних прерываний GIFR
Бит 7 6 5 4 3 2 1 0

Чтение / R/W R/W - - - - - -


Запись
Номер INT1 INT0 - - - - - -
перыв.
Нач.знач 0 0 0 0 0 0 0 0

Пример 6.20. В этом примере при появлении внешнего прерывания INT0 4


Внешнее светодиода загораются. А при появлении прерывания INT1, светодиоды
33
прерывание гаснут. Прерывания настроены так, чтобы происходить при любом
изменении уровня срабатывания.
.INCLUDE "m8def.inc" ;Загрузка констант микроконтроллера
.CSEG
.ORG 0x000
RJMP START
.ORG 0x001 ;прерывание INT0
RJMP INT_0
.ORG 0x002 ;прерывание INT1
RJMP INT_1
START: ;начало программы
CLI ;Запрет всех прерываний
LDI r19,HIGH(RAMEND) ;Инициализация стека
OUT SPh,r19
LDI r19,LOW(RAMEND)
OUT SPl,r19
LDI r19,0xF0
OUT DDRD,r19 ;настроить 4 ст.бита порта D на вывод
LDI r19,0x05 ;Настроить внешнее прерывание 1, 0
OUT MCUCR,r19 ;на срабатывание при изменении уровня сигнала
LDI r19,0xC0
OUT GICR,r19 ;Разрешить прерывание INT1 и INT0
SEI ;Разрешить все прерывания
a: ;Пустой цикл
NOP
NOP
RJMP a
INT_0: ;Подпрограмма прерывания 0
LDI r19,0xF0
OUT PORTD,r19 ;Установить 4-е ст. бита порта D в 1
RETI
INT_1: ;Подпрограмма прерывания 1
LDI r19,0x00
OUT PORTD,r19 ;Сбросить все биты порта D в 0
RETI
.EXIT
Проанализировав эту программу, видим, что для того, чтобы
воспользоваться прерывания необходимо: первое, запретить все
прерывания, чтобы во время настройки прерываний не произошли никакие
прерывания, второе, настроить стек, т.к. программа должна знать, куда
возвращаться после выполнения подпрограммы прерываний, и снова
разрешить все прерывания. Затем программа может выполнять любую свою
задачу. В данном случае, это просто пустой цикл. При приходе прерывания
от INT1 или INT0 программа прекращает выполнение своих дел. Запрещает
приходить новым прерываниям путем сброса бита I в регистре SREG.
Переходит на подпрограмму выполнения соответствующего прерывания.
Затем после выполнения этой подпрограммы возвращается к выполнению
отложенной основной программы. Извлекая из стека адрес, при
выполнении которого пришло прерывание
Прерывания таймеров/счетчиков. Прерывание таймеров изучим
также как и внешние прерывания, но уже только по двум регистрам TIFR и

34
TIMSK, т.к. прерывания таймера – внутренние. Здесь нет необходимости
настраивать уровень срабатывания прерывания.
а) TIMSK – регистр масок прерываний таймеров/счетчиков;
б) TIFR – регистр флагов прерываний таймеров/счетчиков.
Рассмотрим регистр TIMSK (таблица 6.7). Это регистр, где определяются
какие из прерываний таймеров/счетчиков разрешены, а какие – нет.
Таблица 6.7 – Регистр масок прерывания по таймерам/счетчикам – TIMSK
Бит 7 6 5 4 3 2 1 0

Чтение / R/W R/W R/W R/W R/W R/W - R/W


Запись
Номер OCIE2 TOIE2 TICIE1 OCIE1A OCIE1B TOIE1 - TOIE0
перыв.
Нач.знач 0 0 0 0 0 0 - 0

Bit 7 – OCIE2: Timer/Counter2 Output Compare Interrupt Enable –


Разрешение прерывания по совпадению таймера/счетчика 2. При
установленном бите OCIE2 и установленном бите I регистра статуса
разрешается прерывание по совпадению содержимого регистра сравнения
OCR2 и счетного регистра TCNT2 таймера/ счетчика 2.
Bit 6 – TOIE2: Timer/Counter2 Overflow Interrupt Enable – Разрешение
прерывания по переполнению таймера/счетчика 2. При установленном бите
TOIE2 и установленном бите I регистра статуса разрешается прерывание по
переполнению таймера/счетчика 2, т.е. при попытке записать в счетный
регистр таймера/счетчика 2 число большее, чем позволяет его разрядность.
Bit 5 – TICIE1: Timer/Counter1 Input Capture Interrupt Enable –
Разрешение прерывания по захвату таймера/счетчика 1. При установленном
бите TICIE1 и установленном бите I разрешается прерывание по захвату
таймера/счетчика 1. Захват счета – это особая функция таймера/счетчика 1.
Подробнее она будет рассмотрена позднее (Часть 4).
Bit 4 – OCE1A: Timer/Counter1 Output Compare A Match Interrupt
Enable – Разрешение прерывания по совпадению регистра уставки A с
счетным регистром таймером/счетчиком 1. При установленном бите OCIE1A
и установленном бите I регистра статуса разрешается прерывание по
совпадению регистра уставки A с счетным регистром таймера/счетчика 1.
Bit 3 – OCIE1B: Timer/Counter1 Output CompareB Match Interrupt
Enable – Разрешение прерывания по совпадению регистра уставки B с
счетным регистром таймера/счетчика 1. При установленном бите OCIE1B и
установленном бите I регистра статуса разрешается прерывание по
совпадению регистра уставки B с счетным регистром таймера/счетчика 1.
Bit 2 – TOIE1: Timer/Counter1 Overflow Interrupt Enable – Разрешение
прерывания по переполнению таймера/счетчика 1.
Bit 1 – Не используется, т.е. таймер 0 может работать только на
переполнение, в этом типе микроконтроллера.

35
Bit 0 – TOIE0: Timer/Counter0 Overflow Interrupt Enable – Разрешение
прерывания по переполнению таймера/счетчика 0. При установленном бите
TOIE0 и установленном бите I регистра статуса разрешается прерывание по
переполнению таймера/счетчика0.
Кроме регистра масок прерываний таймеров/счетчиков существует
регистр флагов прерываний (таблица 6.8), где микроконтроллер узнает какое
прерывание произошло, и соответственно, на какой адрес вектора
прерываний необходимо перейти.
Таблица 6.8 – Регистр флагов прерывания таймеров/счетчиков – TIFR
Бит 7 6 5 4 3 2 1 0

Чтение / R/W R/W R/W R/W R/W R/W - R/W


Запись
Номер OCF2 TOV2 ICF1 OCF1A OCF1B TOV1 - TOV0
перыв.
Нач.знач 0 0 0 0 0 0 0 0

Bit 7 – OCF2: Output Compare Flag 2: – Флаг совпадения


таймера/счетчика2 и данных OCR2. Бит OCF2 устанавливается при
совпадении счетного регистра таймера/счетчика 2 и содержимого регистра
уставки OCR2 (Output Compare Register 2).
Bit 6 – TOV2: Timer/Counter2 Overflow Flag: – Флаг переполнения
таймера/счетчика2. Бит TOV2 устанавливается при переполнении
таймера/счетчика2.
Bit 5 – ICF1: Input Capture Flag 1: – Флаг захвата счетного регистра
таймера/счетчика 1. Бит ICF1 устанавливается в случае появлении
соответствующего сигнала на ножке захвата счета. Этот флаг показывает, что
счетный регистр таймера/счетчика 1 перенесен специальный регистр захвата
– ICR1.
Bit 4 – OCF1A: Output Compare Flag 1A: – Флаг 1A совпадения выхода.
Бит OCF1A устанавливается при совпадении счетного регистра
таймера/счетчика 1 и содержимого регистра уставки А – OCR1A (Output
Compare Register 1A).
Bit 3 – OCF1B: Output Compare Flag 1B: – Флаг 1B совпадения выхода.
Бит OCF1B устанавливается при совпадении счетного регистра
таймера/счетчика 1 и содержимого регистра уставки В – OCR1B (Output
Compare Register 1B).
Bit 2 – TOV1: Timer/Counter1 Overflow Flag – Флаг переполнения
таймера/счетчика 1 Бит TOV1 устанавливается при переполнении
таймера/счетчика 1.
Bit 1 – не используется, т.к. у таймера/счетчика 0 нет прерывание по
совпадению, а есть только прерывание по переполнению

36
Bit 0 – TOV0: Timer/Counter0 Overflow Flag – Флаг переполнения
таймера/счетчика 0. Бит TOV0 устанавливается при переполнении
таймера/счетчика 0.
Хотя таймеры/счетчики будут изучены только в 4 части, но этот
материал был представлен для того, чтобы показать какие прерывания
существуют в микроконтроллере.
Изучив варианты прерываний в микроконтроллере мы только теперь
можем приступить к изучению периферийных устройств микроконтроллера.
6.7Компаратор
Почти в каждой AVR, существует аналоговый компаратор. Это уже
почти стандартное устройство и встречается очень часто во множестве
разных контроллеров. Компаратор позволяет сравнивать между собой два
аналоговых сигнала и выносить свой вердикт 0 – первый сигнал больше
второго, 1 – второй сигнал больше первого.
Применение компаратора весьма разнообразны, например, с помощью
компаратора можно отслеживать уровень заряда аккумулятора по просадке
напряжения. Схема очень проста (рис. 6.14) – стабилитрон VD1 создает
опорное напряжение, которое всегда одинаково, а напряжение с
резистивного делителя зависит от входного напряжения.

Рис. 6.14. Схема контроля напряжения

Например, напряжение батарейки – 8 В. Со стабилитрона,


рассчитанного на 3,3 В, выходит всегда одно и то же напряжение – 3,3 В,
которое попадает на ножку компаратора – AIN0. Разница напряжений между
батарейкой и стабилитроном VD1 приходится на резистор R1. А с
симметричного резистивного делителя (реализованного на R2 и R3) выходит
половина напряжения батареи, т.е. 4В, которая подается на ножку AIN1.
Четыре больше чем 3,3 (3,3 – 4 = –0,7 результат меньше нуля), т.е.
компаратор выдает 0.

37
Теперь, если «просядет» батарейка, т.е. напряжение на батарейке
уменьшится, например до 6 В, то с делителя будет поступать сигнал на вход
AIN1 уже 3 В, а с опорного как было 3,3 В так и осталось, т.е. на AIN0 по-
прежнему выдает напряжение 3,3 В. Но теперь на компараторе ситуация в
корне поменялась – 3 меньше чем 3,3 (3,3 – 3=+0,3), а значит, на выходе
компаратора будет – 1.
Так, например, c помощью компаратора, реализованного на
микроконтроллере ATmega8, можно легко и просто следить за питающим
напряжением и выдавать сигнал тревоги, если батарейка «просядет».
Как выдавать сигналы на соответствующие порты микроконтроллера
«зажигать» и «гасить» светодиоды, было рассмотрено выше. Поэтому
остановимся лишь на программировании и настройки самого компаратора.
Первое, что необходимо помнить, чтобы компаратор заработал его
входы нужно настроить на вход и отключить подтягивающие резисторы.
Таблица 6.9 – Регистр ACSR
Бит 7 6 5 4 3 2 1 0

Чтение / R/W R/W R/W R/W R/W R/W R/W R/W


Запись
Номер ACD AINBG АСО ACI ACIE ACIC ACIS1 ACIS0
перыв.
Нач.знач. 0 0 0 0 0 0 0 0

Второе, необходимо настроить компаратор с помощью регистра


конфигурации компаратора ACSR (таблица 6.9).
Для настройки компаратора необходимо настроить, что подключено к
выводу AIN0, а что к AIN1, куда подсоединен вывод и т.п. Для этого
существует ряд регистров, один из которых – это регистр ACSR.
Bit 7 – ACD: Analog Comparator Disable – Запрет аналогового
компаратора. При установленном в состояние 1 бите ACD аналоговый
компаратор запрещен. Обратите внимание, что при старте микроконтроллера
компаратор разрешен.
Bit 6 – AINBG – Подключение к не инвертирующему входу (AIN0)
внутреннего источника опорного напряжения (0 – не подключён, 1 –
подключён). Величина опорного напряжения составляет 1,22 В.
Bit 5 – ACO: Analog Comparator Output – Выход компаратора. Т.е.
именно этот бит принимает значение 1 или 0, в зависимости от того, что
больше AIN1 или AIN0.
Bit 4 – ACI: Analog Comparator Interrupt Flag – Флаг прерывания no
аналоговому компаратору. Данный бит устанавливается в состояние 1 в
случае формирования компаратором прерывания, определяемого битами
ACIS1 и ACIS0 этого же регистра. Подпрограмма обработки прерывания по
аналоговому компаратору будет выполняться при установленном бите ACIE
и установленном бите глобального прерывания I в регистре SREG.

38
Bit 3 – ACIE: Analog Comparator Interrupt Enable – Разрешение
прерывания аналогового компаратора. Т.е. это бит маски прерывания для
компаратора. При установленном бите ACIE и установленном бите
глобального прерывания I регистра SREG активируется прерывание по
аналоговому компаратору. При сброшенном бите ACIE прерывание
запрещено.
Bit 2 – ACIC: Analog Comparator Input Capture enable – Разрешение
захвата счета таймера/счетчика 1 по состоянию выхода аналогового
компаратора. Установленный в состояние 1 бит ACIC разрешает
срабатывание функции захвата счета таймера/счетчика 1 по переключению
аналогового компаратора. В этом случае выход аналогового компаратора
подсоединяется непосредственно к входной цепи логики захвата входа
таймера/счетчика 1. При очищенном бите ACIC соединения нет. Для запуска
прерывания по захвату входа таймера/счетчика 1 бит TICIE1 в регистре
масок прерываний таймеров TIMSK должен быть установлен в состояние 1.
Подробнее о функции захвата будет изложено в 4 части в параграфе
таймер/счетчик 1.
Bits 1,0 – ACIS1, ACIS0: Analog Comparator Interrupt Mode Select –
Выбор режима прерывания аналогового компаратора. Эти биты определяют
характер, при котором запускается прерывание аналогового компаратора.
Варианты установок показаны в таблице 6.10.
Таблица 6.10 – Установки битов ACIS1 и ACIS0
ACIS1 ACIS0 Режим прерывания
0 0 Прерывание по переключению выхода компаратора
0 1 Не используется
1 0 Прерывание по заднему фронту на выходе компаратора
1 1 Прерывание по переднему фронту на выходе компаратора
Внимание!!! При изменении состояния битов ACIS1 и ACIS0 прерывание аналогового
компаратора должно быть запрещено очисткой бита разрешения
прерывания в регистре ACSR. В противном случае при изменении
состояния битов может произойти прерывание.
Что подключить ко второму аналоговому входу. Определяют целых 5
бит. Бит ACME (3 бит) в регистре специальных функций SFIOR. Это регистр,
содержащий разные биты для разных функций, для которых не нашлось
специального регистра. Биты ACME (регистр SFIOR) ADEN (регистр работы
АЦП ADCSR) подключают, либо вход AIN1, либо один из 6 входов АЦП
микроконтроллера, к входу – компаратора (таблица 6.11). Оставшиеся 3 бита,
хранятся в регистре ADMUX.
Для подключения любого входа АЦП ADC0…ADC6 к входу
компаратора AIN1 необходимо:
1) В регистре SFIOR (регистр специальных функций) выставить бит
ACME.
2) Выключить АЦП, сбросив бит ADEN в регистре настроек АЦП
(ADCSR).

39
3) В регистре ADMUX в разрядах MUX2:MUX1:MUX0 указать номер
входа АЦП.
Таблица 6.11 – Выбор отрицательного (инвертирующего) входа компаратора
ACME ADEN MUX2…0 Вход
0 х ххх AIN1
1 1 ххх AIN1
1 0 000 ADC0
1 0 001 ADC1
1 0 010 ADC2
1 0 011 ADC3
1 0 100 ADC4
1 0 101 ADC5
Примечание: x –любое состояние бита
Производители микроконтроллеров с целью минимизировать свои
изделия постоянно объединяют различные функции. Вот и сейчас, имея в
своем распоряжении 6 входов АЦП, производители объединили входа АЦП и
инверсный вход компаратора аппаратным путем внутри микроконтроллера.
А настройку оставили программисту.
Согласно всему изложенному работу и настройку компаратора можно
изобразить схематически (рис. 6.15). Здесь, чтобы разрешить работу
компаратора, необходимо установить бит ACD регистра ACSR в 0 (см.
описание работы регистра ACSR). Затем производится настройка
подключаемых входов AIN0 и AIN1, путем изменения битов AINBG, ACME
ADEN. Затем производится настройка подключаемого вывода компаратора и
выбор вида прерываний (биты ACIS1 и ACIS0 в регистре ACSR).

Рис. 6.15. Схематический вид компаратора и подключение его входов выходов

40
Если вернутся к примеру с проверкой уровня заряда батарейки, то
использую опорное напряжения 1,22 В, можно упростить схему и исключить
из нее стабилизатор VD1 и резистор R1, и настроить плечи делителя так,
чтобы при 8 В на батарейки на входе AIN1 было чуть больше чем 1,22 В. Т.е.
использовать внутренний источник опорного напряжения.
Пример 6.21. Для того, чтобы можно было использовать опорное напряжение
Контроль компоратора, изменим схему рис. 6.13. Плечи резистора подберем по
уровня соотношению 10 к 1,5 (R2/R3). Возьмем батарейку напряжением 12В.
зарядки Тогда на ножку микроконтроллера AIN1 подается напряжение
аккумулятора 1,5/(1,5+10).12=1,56В. При уменьшении напряжения до уровня 9,5В на
на 12 В выходе делителя будет ниже 1,22В. При уменьшении напряжения ниже
9,5В выдавать сигнал на светодиод «Низкое напряжение» (VD6).
.INCLUDE "m8def.inc" ;Загрузка констант микроконтроллера
.CSEG
.ORG 0x000 ;переход на начало программы
RJMP START
.ORG 0x010 ;прерывание компаратора
RJMP COMPAR
START: ;начало программы
CLI ;Запрет всех прерываний
;--------------------------------------
LDI r19,HIGH(RAMEND) ;Инициализация стека
OUT SPh,r19
LDI r19,LOW(RAMEND)
OUT SPl,r19
;--------------------------------------
LDI r19,0x40
OUT DDRD,r19 ;настроить 8 бит порта D на вывод
;--------------------------------------
LDI r19, 0b 0 1 0 0 1 0 1 1 ;Инициализация компаратора
OUT ACSR,r19 Прерывание по переднему фронту
AIN1 подключить к входу AIN1
AIN0 к опорному напряжению
Разрешить прерывания
Разрешить работу компаратора
SEI ;Разрешить все прерывания
;-------------------------------------------------------
a: ;Пустой цикл
NOP
NOP
RJMP a
;-------------------------------------------------------
COMPAR: ;Подпрограмма прерывания
компаратора
SBI PORTD,6 ;Установить 4-й ст. бита порта D в 1
RETI

41
6.8 Аналоговый цифровой преобразователь
Микроконтроллер общается с «внешним миром» посредством портов
ввода/вывода. В общем случае он может «воспринимать» только цифровые
сигналы – логический ноль или логическую единицу. Например, для
микроконтроллера ATmega8 при напряжении питания 5 В логический ноль –
это напряжение от 0 до 1,3 В, а логическая единица – от 1,8 до 5 В. Довольно
часто возникает потребность измерять напряжения, которые могут
принимать любое значение в диапазоне от 0 до напряжения питания (+5 В).
Для этих целей в составе микроконтроллеров AVR есть аналого-цифровой
преобразователь (АЦП).
Если пока исключить все подробности, то для работы АЦП необходим
источник опорного напряжения (ИОН). Для него – это эталон, по отношению
к которому он измеряет входные сигналы. Микроконтроллеры AVR
позволяют в качестве ИОН использовать:
а) напряжение питания;
б) внутренний опорный источник (2,56 В);
в) напряжение на выводе AREF (внешний ИОН).
Для работы АЦП важным параметром является – предельная частота
дискретизации, которая определяет быстродействие АЦП, и измеряется в
герцах или количестве выборок в секунду (SPS – samples per second). Для
микроконтроллеров AVR эта величина равна 15kSPS (килло семплов в
секунду). Практически АЦП AVRа работает и быстрее, но при этом его
точность ухудшается.
Теорема Котельникова (теорема Найквиста-Шеннона, теорема о
выборке) гласит, что аналоговый сигнал, имеющий ограниченный спектр,
может быть восстановлен однозначно и без потерь по своим дискретным
отсчётам, если частота выборки (дискретизации) превышает максимальную
частоту спектра сигнала более чем в 2 раза. Выражаясь по-простому – если
нам нужно оцифровать аналоговый сигнал с полосой спектра 0 – 7 КГц, то в
идеальном случае частота дискретизации должна быть > удвоенной
максимальной частоты спектра этого сигнала, то есть больше 14КГц. На
практике все намного сложнее. Перед входом АЦП всегда ставят
низкочастотный фильтр, чтобы ограничить спектр сигнала, а частота
дискретизации выбирается еще более высокой. В результате АЦП способно
измерять только аналоговые сигналы с частотами от 0 до 7 КГц.
Для управления АЦП существуют четыре регистра:
а) ADMUX;
б) ADCSR;
в) ADCH и ADCL – регистры результата преобразования.
Результат преобразования АЦП хранится в регистрах ADCH и ADCL.
Регистры ADCH и ADCL особого интереса не представляют, т.к. именно в
них заносится результата преобразования 10-разрядный или 8-разрядный, что

42
определяется номером опрашиваемого АЦП, т.е. эти регистры просто
содержат число пропорциональное аналоговому сигналу.
Таблица 6.12 – Регистр ADCSR
Бит 7 6 5 4 3 2 1 0

Чтение / R/W R/W R/W R/W R/W R/W R/W R/W


Запись
Номер ADEN ADSC АDFR ADIF ADIE ADPS2 ADPS1 ADPS0
перыв.
Нач.знач. 0 0 0 0 0 0 0 0

Регистр ADCSR представлен в таблице 6.12.


Bit 7 – ADEN: Разрешение работы АЦП, т.е. бит подачи напряжения на
АЦП. При бите равном 1 – АЦП разрешено преобразование при 0 –
запрещено.
Bit 6 – ADSC: Разрешение начать преобразование. При установленном
бите в 1 АЦП начинает преобразование аналогового сигнала в цифровой код.
Bit 5 – ADFR: Выбор режима работы АЦП. Единичное, т.е. разовое или
постоянное (циклическое). При установленном бите в 1 АЦП будет работать
в циклическом режиме, т.е. после окончания работы АЦП одного цикла сразу
начинается следующее. При сброшенном бите в 0. АЦП работает в
одиночном режиме преобразования, т.е. преобразовал один раз и
остановился.
Bit 4 – ADIF: Флаг прерывания от АЦП. Устанавливается в 1 при
окончании преобразования аналогового числа в цифровой вид.
Bit 3 – ADIE: Разрешение прерывания АЦП, т.е. это маска прерывания
АЦП. При установленном 1 значении прерывание от АЦП разрешено при 0 –
запрещено.
Bit 2-0 – ADPS2-ADPS0: Выбор коэффициента предделителя тактового
сигнала АЦП (таблица 6.13). Модулю АЦП для работы требуется тактовый
сигнал. Он формируется из тактового сигнала микроконтроллера путем
деления на фиксированные коэффициенты. Для установки коэффициентов
предделителя предназначены биты ADPS2, ADPS1, ADSPS0. Т.е. при
установке внешнего тактового сигнала 16МГц и коэффициента деления – Без
деления. Частота выборке будет равна 15 кГц.

43
Таблица 6.13 – Выбор коэффициента предварительного деления АЦП

ADPS2 ADPS1 ADPS0 Коэффициент деления


0 0 0 Без деления
0 0 1 2
0 1 0 4
0 1 1 8
1 0 0 16
1 0 1 32
1 1 0 64
1 1 1 128
Вторым, регистром управления АЦП является регистр ADMUX,
который обычно называют регистром выбора канала АЦП, т.к. именно в нем
происходит выбор канала АЦП (таблица 6.14).
Таблица 6.14 – Регистр ADMUX
Бит 7 6 5 4 3 2 1 0
Чтение / R/W R/W R/W R R/W R/W R/W R/W
Запись
Номер REFS1 REFS0 ADLAR - MUX3 MUX2 MUX1 MUX0
перыв.
Нач.знач 0 0 0 0 0 0 0 0
Bits 7, 6 – REFS1, REFS0: Определяют источник опорного напряжения,
либо это внешний источник опорного напряжения, либо источник питания
АЦП, либо внутренний источник питания АЦП. Выбор источника опорного
напряжения производится согласно таблице 6.15.
Таблица 6.15 – Выбор источника опорного напряжения для АЦП
REFS1 REFS0 Комментарий
0 0 Внутренний источник – выключен, а источник AREF - вкл.
0 1 Внешний источник AVCC
1 0 Не используется
1 1 Внутренний источник V = 2.56В
Bit 5 – ADLAR: ADC Left Adjust Result. Направление выравнивания
сигнала. У микроконтроллера семейства AVR АЦП – 10-ти разрядный, а сам
процессор 8-ми. Поэтому результат преобразования хранится в двух
регистрах (ADCH, ADCL). Бит ADLAR задает направление выравнивания
результата преобразования. 0 – выравнивание вправо (в ADCH заняты 2
младших бита, ADCL занят весь), 1 – выравнивание влево (ADCH занят весь,
в ADCL только 2 старших бита).
Bit 4 – зарезервирован для других моделей микроконтроллеров.
Bits 3:0 – MUX3:0: Analog Channel Selection Bits. Биты выбора канала
АЦП (таблица 6.16). Остальные комбинации бит, что не представлены в
таблице, не используются.

44
Таблица 6.16 – Выбор номера канала АЦП
MUX3 MUX2 MUX1 MUX0 Канал
0 0 0 0 ADC0
0 0 0 1 ADC1
0 0 1 0 ADC2
0 0 1 1 ADC3
0 1 0 0 ADC4
0 1 0 1 ADC5
1 1 1 0 Подкл. вх. АЦП к напряжению 1.23В
1 1 1 1 Подкл. вх. АЦП к напряжению 0В

Схематически работу АЦП представим также как и работу компаратора


(рис.6.16).

Рис. 6.15. Структура АЦП

Рис. 6.16. Структура АЦП


Здесь к мультиплексору подключены 6 каналов АЦП, выведенные на
соответственные ножки, а также сигнал с напряжением в 0 и 1,23 В
(Вх. АЦП). Выбор между этими каналами происходит с помощью битов
MUX3 – MUX0 регистра ADMUX. Также можно заметить, что регистр
ADMUX управляет источниками опорного напряжения АЦП.
Выход мультиплексора (Вх. АЦП) подключен к преобразователю, т.е.
непосредственно к АЦП, а также этот выход может быть подключен к входу
компаратора AIN1. Преобразователь управляется регистром ADCSR и

45
записывает преобразованное значение в регистры ADCH и ADCL. Откуда эти
значения передаются по необходимости в шину данных микроконтроллера.
Пример 6.22. В этом примере задается аналоговая величина с помощью
Индикация потенциометров. Этот сигнал воспринимается микроконтроллером и
аналоговой выдается на семисегментные индикаторы лабораторного стенда.
величины .INCLUDE “m8dec.inc” ;подключение файла констант
.CSEG
.ORG 0x00 ;начальный адрес программы
RJMP START ;Переход на начало программы, т.е. обойти адреса
прерываний
.ORG 0x0E ;Адрес вектора прерывания АЦП
RJMP ADC1
START: ;Начало программы
CLI ;Запрет всех прерываний

;----------------------------------------------------------------------
LDI r19,0b 1 1 0 0 1 1 1 1 ;Инициализация АЦП
Максимальный предделитель
ADIE = 1 Разр. прерыв. АЦП

Одноразовое преобразование
ADSC = 1 Начать преобразование
ADEN = 1 Подключить АЦП
OUT ADCSR, r19
LDI r19,0b 0 1 1 0 0 0 0 1
Подключить канал ADC1

ADLAR=1 Выравнивание вправо


Источник опорного напр. – AVCC
OUT ADMUX, r19
;--------------------------------------------------------------------
LDI r19, HIGH(RAMEND) ;Инициализация стека
OUT sph, r19
LDI r19,LOW(RAMEND)
OUT spl, r19
;--------- Настройка входов/выходов ---------------------
LDI r19, 0xFF
OUT DDRB,r19
LDI r19, 0xFD
OUT DDRС,r19
;-------------------------------------------------------------------
SEI ;Разрешить прерывания
LOOP: ;Пустой цикл
SBI ADCSR,6 ;Разрешить преобразование
NOP
NOP
RJMP LOOP

46
;------------------------------------------------------------
ADC1: ;Подпрограмма прерывания АЦП
IN r19, ADCН ;Считать старший байт АЦП
MOV r20, r19
LSR r20 ;Выровнять младшую тетраду байта
LSR r20 ;под биты вывода порта В
LSR r20
OUT PORTB, r20
MOV r20, r19
LSL r20 ;Выровнять старшую тетраду байта
OUT PORTC, r20 ;под биты вывода порта С
RETI ;Возврат из прерывания
;-------------------------------------------------------------
.EXIT ;Конец программы
6.9 Прерывания таймеров
Прерывания таймеров (прерывания с 4 по 10) (см. таблицу 6.1), которые
можно разделить на прерывания сравнения, т.е. прерывания, которые
возникают при совпадении счетного регистра таймера с уставкой этого
таймера, прерывания переполнения счета, которые возникают, если счет
таймера превысил разрядность этого таймера.
В микроконтроллере ATmega 8 существует три независимых таймера
таймер 0, 1 и 2. Таймер 1 состоит из двух 16 разрядных таймеров. А таймер 0
и 2 – 8 разрядные таймеры. Каждый таймер обладает своими особенностями,
которые более подробно будут рассмотрены при изучении каждого из
таймеров.
Для управления прерываниями таймеров/счетчиков существуют два
регистра:
а) TIMSK – регистр масок прерываний таймеров/счетчиков;
б) TIFR – регистр флагов прерываний таймеров/счетчиков.
Рассмотрим регистр TIMSK (таблица 6.17). Это регистр, масок таймеров,
в котором определяется: какие из прерываний таймеров/счетчиков
разрешены, а какие – нет.
Таблица 6.17 – Регистр масок прерывания по таймерам/счетчикам – TIMSK
Бит 7 6 5 4 3 2 1 0

Чтение / R/W R/W R/W R/W R/W R/W - R/W


Запись
Номер OCIE2 TOIE2 TICIE1 OCIE1A OCIE1B TOIE1 - TOIE0
перыв.
Нач.знач. 0 0 0 0 0 0 - 0

Bit 7 – OCIE2: Timer/Counter2 Output Compare Interrupt Enable –


Разрешение прерывания по совпадению таймера/счетчика 2. При
установленном бите OCIE2 и установленном бите I регистра статуса
разрешается прерывание по совпадению содержимого регистра сравнения
OCR2 и счетного регистра TCNT2 таймера/ счетчика 2.
47
Bit 6 – TOIE2: Timer/Counter2 Overflow Interrupt Enable – Разрешение
прерывания по переполнению таймера/счетчика 2. При установленном бите
TOIE2 и установленном бите I регистра статуса разрешается прерывание по
переполнению таймера/счетчика 2, т.е. при попытке записать в счетный
регистр таймера/счетчика 2 число большее, чем позволяет его разрядность.
Bit 5 – TICIE1: Timer/Counter1 Input Capture Interrupt Enable –
Разрешение прерывания по захвату таймера/счетчика 1. При установленном
бите TICIE1 и установленном бите I разрешается прерывание по захвату
таймера/счетчика 1. Захват счета – это особая функция таймера/счетчика 1.
Подробнее она будет рассмотрена позднее (Часть 4).
Bit 4 – OCE1A: Timer/Counter1 Output Compare A Match Interrupt
Enable – Разрешение прерывания по совпадению регистра уставки A с
счетным регистром таймером/счетчиком 1. При установленном бите OCIE1A
и установленном бите I регистра статуса разрешается прерывание по
совпадению регистра уставки A с счетным регистром таймера/счетчика 1.
Bit 3 – OCIE1B: Timer/Counter1 Output CompareB Match Interrupt
Enable – Разрешение прерывания по совпадению регистра уставки B с
счетным регистром таймера/счетчика 1. При установленном бите OCIE1B и
установленном бите I регистра статуса разрешается прерывание по
совпадению регистра уставки B с счетным регистром таймера/счетчика 1.
Bit 2 – TOIE1: Timer/Counter1 Overflow Interrupt Enable – Разрешение
прерывания по переполнению таймера/счетчика 1.
Bit 1 – Не используется, т.е. таймер 0 может работать только на
переполнение, в этом типе микроконтроллера.
Bit 0 – TOIE0: Timer/Counter0 Overflow Interrupt Enable – Разрешение
прерывания по переполнению таймера/счетчика 0. При установленном бите
TOIE0 и установленном бите I регистра статуса разрешается прерывание по
переполнению таймера/счетчика0.
Кроме регистра масок прерываний таймеров/счетчиков существует регистр
флагов прерываний (таблица 6.18), где микроконтроллер узнает какое
прерывание произошло, и соответственно, на какой адрес вектора
прерываний необходимо перейти.
Таблица 6.18 – Регистр флагов прерывания таймеров/счетчиков – TIFR
Бит 7 6 5 4 3 2 1 0

Чтение / R/W R/W R/W R/W R/W R/W - R/W


Запись
Номер OCF2 TOV2 ICF1 OCF1A OCF1B TOV1 - TOV0
перыв.
Нач.знач 0 0 0 0 0 0 0 0

48
Bit 7 – OCF2: Output Compare Flag 2: – Флаг совпадения
таймера/счетчика2 и данных OCR2. Бит OCF2 устанавливается при
совпадении счетного регистра таймера/счетчика 2 и содержимого регистра
уставки OCR2 (Output Compare Register 2).
Bit 6 – TOV2: Timer/Counter2 Overflow Flag: – Флаг переполнения
таймера/счетчика2. Бит TOV2 устанавливается при переполнении
таймера/счетчика2.
Bit 5 – ICF1: Input Capture Flag 1: – Флаг захвата счетного регистра
таймера/счетчика 1. Бит ICF1 устанавливается в случае появлении
соответствующего сигнала на ножке захвата счета. Этот флаг показывает, что
счетный регистр таймера/счетчика 1 перенесен специальный регистр захвата
– ICR1.
Bit 4 – OCF1A: Output Compare Flag 1A: – Флаг 1A совпадения выхода.
Бит OCF1A устанавливается при совпадении счетного регистра
таймера/счетчика 1 и содержимого регистра уставки А – OCR1A (Output
Compare Register 1A).
Bit 3 – OCF1B: Output Compare Flag 1B: – Флаг 1B совпадения выхода.
Бит OCF1B устанавливается при совпадении счетного регистра
таймера/счетчика 1 и содержимого регистра уставки В – OCR1B (Output
Compare Register 1B).
Bit 2 – TOV1: Timer/Counter1 Overflow Flag - Флаг переполнения
таймера/счетчика 1 Бит TOV1 устанавливается при переполнении
таймера/счетчика 1.
Bit 1 – не используется, т.к. у таймера/счетчика 0 нет прерывание по
совпадению, а есть только прерывание по переполнению
Bit 0 – TOV0: Timer/Counter0 Overflow Flag - Флаг переполнения
таймера/счетчика 0. Бит TOV0 устанавливается при переполнении
таймера/счетчика 0.

6.10 Работа таймеров/счетчиков микроконтроллера ATmega8

Микроконтроллеры ATmega8 оснащены тремя таймерами/счетчиками


общего назначения – двумя 8-разрядными и одним 16-разрядным.
Любой таймер – это счетчик, но в режиме таймера счетный вход таймера
подключен к генератору импульсов, который создает импульсы через равные
промежутки времени. А в режиме счетчика счетный вход импульса считает
произвольные импульсы на счетном входе.
Как отмечалось выше, каждый таймер микроконтроллера ATmega8
может работать в различных режимах:
а) в режиме счетчика внешних сигналов;
б) в режиме обычного таймера (задержка времени на включение);
в) в режиме ШИМ, т.е. ЦАП.
Для каждого таймера существует ряд регистров, которые и управляют
состоянием таймеров.

49
Таймер/счетчик 0
Таймер/счетчик 0 – это таймер, который может работать только на
переполнение. Т.е. задавать уставку для этого таймера/счетчика нельзя.
Вернее сказать, что она уже задана и равна максимальному числу – FF, по
превышению которого таймер/счетчик 0 и сработает, т.е. выдает сигнал
прерывания по переполнению. Единственное, что позволили делать нам
производители, так это выбирать дискрету работу таймера, т.е. задавать
коэффициент деления несущей частоты для таймера/счетчика 0. В результате
таймер/счетчик 0 можно запрограммировать на задержку времени, равную
одному из 5-ти значений:
(FF+1)*1024*(1/fCk) с,
(FF+1)*256*(1/fCk) с,
(FF+1)*64*(1/fCk) с,
(FF+1)*8*(1/fCk) с,
(FF+1)*1*(1/fCk) с,
Здесь FF – максимальное число, которое может быть записано в
таймер/счетчик 0; fck – частота генератора импульсов.
При частоте тактового сигнала в 1 МГц таймер счетчик может работать
с задержкой 0,26 с, 0,065 с, 0,016 с, 0,002 с и 0,000256 с. При использовании
другого генератора тактового сигнала эти величины задержек также
изменятся.
Для управления таймером/счетчиком 0 существует два регистра:
 TCCR0 – регистр управления таймером/счетчиком 0;
 TCNT0 – регистр счета.
В первом регистре TCNT0 происходит непосредственно сам счет. Т.е.
это регистр, где микроконтроллер считает события или дискреты времени,
т.е. запоминает, сколько он уже насчитал. Гораздо больший интерес
представляет второй регистр – TCCR0, т.к. именно в нем производится
управление таймером/счетчиком 0, т.е. задание коэффициента предделителя.
В таблице 6.19 представлены функции каждого бита в регистре TCCR0. Из
таблицы видно, что в данном регистре используются только три младших
бита, которую и задают коэффициент предделителя или подключают этот
таймер/счетчик к внешнему тактовому сигналу. Остальные биты не
используются и зарезервированы для других моделей микроконтроллеров.
Таблица 6.19 – Регистр управления таймером/счетчиком 0 (TCCR0)
Бит 7 6 5 4 3 2 1 0
Чтение / R/W R/W R R/W R/W R/W R/W R/W
Запись
Номер - - - - - CS02 CS01 CS00
перыв.
Нач.знач 0 0 0 0 0 0 0 0

50
Bits 2 – 0: CS02 – CS00 – биты отвечающие за выбор источника
тактового сигнала и коэффициента предделителя. Выбор источника
тактового сигнала определяется таблицей 6.20.
Таблица 6.20 – Выбор источника тактового сигнала таймера/счетчика 0
CS02 CS01 CS00 Описание
0 0 0 Stop условие – таймер/счетчик 0 остановлен
0 0 1 CK
0 1 0 CK / 8
0 1 1 CK / 64
1 0 0 CK / 256
1 0 1 CK / 1024
1 1 0 Внешний тактирующий сигнал на выводе T0, передний фронт
1 1 1 Внешний тактирующий сигнал на выводе T0, задний фронт.

Пример 6.23. Пусть перед программистом стоит задача, заставить светодиод


Использование «моргать» при возникновении какого-либо условия, например, сигнала
таймера/счетчика аварии. Для того, чтобы заставить светодиод “моргать”, необходимо
0 задать где-то интервал времени, в течении которого светодиод
светится, а также интервал времени в течении которого он потушен.
Если задаться дополнительным условием, что эти два интервала равны
друг другу, то не хватает еще одного – устройства которое бы следила
за часами, т.е. считала интервал времени. В качестве такого устройства
можно использовать таймер/счетчик 0.
.INCLUDE "m8def.inc" ;Подключение файла констант
.CSEG
.ORG 0x00
RJMP START ;Переход на начало программы
.ORG 0x09
RJMP Timer0 ;Прерывание таймера/счетчика 0
START: ;Начало программы
LDI r17,0x80 ;Загрузка константы в r17
CLI ;Запрет всех прерываний
;------------------------------------------------------------
LDI r19, HIGH(RAMEND) ;Инициализация стека
OUT sph, r19
LDI r19,LOW(RAMEND)
OUT spl, r19
LDI r19,0x40 ;Только 6 бит порта D на вывод
OUT DDRD,r19
;------------------------------------------------------------
LDI r19,0x01 ;Разрешить прерывание от таймера 0
OUT TIMSK,r19
LDI r19,0x05 ;Установить делитель равный 1024
OUT TCCR0,r19
;------------------------------------------------------------
SEI ;Разрешить прерывание
A1: ;Пустой цикл
NOP
RJMP A1
Timer0: ;Подпрограмма обработки прерывания таймера 0
51
ADD r18,r17 ;Прибавить к r18 константу в r17
SBRC r18,7 ;Проверить 7 бит в r18, если сброшен, то
;пропустить следующую команду
RJMP VD_CLR ;Переход на подпрограмму гашения светодиода
VD_SET: ;Зажечь светодиод
LDI r16,0x40
OUT PORTD,r16
RETI
VD_CLR: ;Погасить светодиод
CLR r16
OUT PORTD, r16
RETI
.EXIT
Таймер/счетчик 1
Рассмотрим теперь таймер/счетчик 1. Таймер/счетчик 1 обладает рядом
особенностей:
а) Это 16-разрядный таймер/счетчик 1, т.е целых два 8-битных
регистра отведены под счет, а не один как в таймере/счетчика 0,
рассмотренном выше. В результате таймер/счетчик 1 может считать
не до 255, а до 65535. Это значительно расширяет временные
интервалы счета таймера/счетчика 1.
б) У таймера/счетчика 1 существует один 16-ти разрядный регистр
захвата счета, т.е. регистр, куда происходит запись 16-ти разрядного
регистра счета при появлении внешнего сигнала или при выполнении
каких-то внутренних условий.
в) Таймер/счетчик 1 содержит два регистра управления, т.к. все
возможности управления этим таймером не поместились в один 8-
битный регистр управления.
г) Таймер/счетчик 1 содержит два 16-ти разрядных регистра уставок
А и В.
Таймер/счетчик 1 поддерживает две функции сравнения счета, т.е.
используется два регистра сравнения A и B – OCR1A и OCR1B и один регистр
счета TCNT1. Это означает следующее, что у таймера/счетчика 1 существует
один 16-разрядный регистр счета и два регистра уставок. Соответственно и
два прерывания по совпадению счета: с регистром уставки А и с регистром
уставки В. Это позволяет говорить не об одном аппаратно реализованном 16-
ти разрядном таймере/счетчике 1, а о двух зависимых 16-ти разрядных
таймеров/счетчиков, т.к. в качестве счетного регистра используется один и
тот же 16-разрядный регистр счета.
У таймера/счетчика 1 есть 16-ти разрядный регистр захвата счета (ICR1).
Это 16-разрядный регистр, куда записывается счет непосредственного счета,
из 16-разрядного регистра таймера/счетчика 1 (TCNT1) при выполнении
определенных условий. Функция захвата счета таймера/счетчика 1
обеспечивает сохранение содержимого таймера/счетчика 1 в регистр захвата
счета, запускаемая, либо внешним событием на ножке захвата счета

52
таймера/счетчика 1 PB0/(ICP), либо условием захвата счета
таймера/счетчика 1 может служить выход с компаратора микроконтроллера
(см. п.6.2), т.е. по результатам сравнения двух аналоговых сигналов может
быть вынесен вердикт о запоминании (захвате) счета.
Для управления таймером/счетчиком 1 существует 5 16-разрядных
регистров, в которых задается: две уставки таймера, производится счет, а
также задается режим работы таймера:
а) TCCR1A, TCCR1B – регистры выбора режима работы
таймера/счетчика 1;
б) TCNT1H, TCNT1L – регистр счета, т.е. регистры в которых
производится счет времени или событий;
в) OC1AH, OCR1AL – регистр уставки А;
г) OCR1BH, OCR1BL – регистр уставки В;
д) ICR1H, ICR1L – регистр захвата счета, т.е. регистр куда
переносится состояния счетного регистра (TCNT1H, TCNT1L) при
появлении внешнего сигнала на ножке захвата счета.
Регистрами управления TCCR1A и TCCR1B производится управление
таймером/счетчиком 1.
Так как работа таймеров/счетчиков в общем случаи невозможна без
прерываний, то для управления прерываниями таймера/счетчика 1
существует регистр масок прерываний – TIMSK (Timer/Counter Interrupt Mask
Register), который устанавливает разрешение/запрет того или иного
прерывания таймера/счетчика 1.
Рассмотрим два регистра управления таймером/счетчиком 1 (TCCR1A
таблица 6.21 и TCCR1B таблица 6.23). Не удачным решением производителей
было назвать два регистра управления – TCCR1A и TCCR1B, т.к. в
таймере/счетчике 1 можно задавать две уставки (А и B). Что приводит к
путанице.
Таблица 6.21 – Регистр управления таймером/счетчиком 1 – TCCR1A
Бит 7 6 5 4 3 2 1 0

Чтение / W R/W R/W R/W R/W R/W R/W R/W


Запись
Номер COM1A1 COM1A0 COM1B1 COM1B0 FOC1A FOC1B WG WG
перыв. M11 M10
Нач.знач 0 0 0 0 0 0 0 0

Bits 7, 6 – COM1A1, COM1A0: Compare Output Mode1A – Управляющие


биты COM1A1 и COM1A0 определяют состояние выходной линии
таймера/счетчика 1 OC1A. Правда при этом необходимо учитывать, в каком
именно режиме работает таймер/счетчик 1 в нормальном (обычном) или в
ШИМ режиме, т.к. от этого кардинально зависит куда и как подключается
выходная линия (таблица 6.22).

53
Таблица 6.22 – Подключение выходной линии таймера/счетчика 1 в Aрежиме
Режим COM1A1 COM1A0 Описание
0 0 Таймер/счетчик 1 отсоединен от выходного вывода
Нормаль OC1A
ный 0 1 Подключение выходной линии OC1A к
режим таймеру/счетчику 1
1 0 Очистка выходной линии OC1A (установка в
состояние 0).
1 1 Установка выходной линии OC1A (установка в сост.
1).
0 0 Таймер/счетчик 1 отсоединен от выходного вывода
ШИМ OC1A
режим 0 1 СТС режим таймера/счетчика 1 канала A
1 0 Прямой ШИМ таймера/счетчика 1 канала A
1 1 Инверсный ШИМ таймера/счетчика 1 канала A

Bits 5,4 – COM1B1, COM1B0: Управляющие биты COMB1 и COM1B0


управляют выходной линией таймера/счетчика 1 OC1B. Правда необходимо
учитывать в каком режиме работает таймер/счетчик 1 в ШИМ или в
нормальном (обычном) режиме (таблица 6.23).
Таблица 6.23 – Подключение выходной линии таймера/счетчика 1 в В режиме
Режим COM1B1 COM1B0 Описание
0 0 Таймер/счетчик 1 отсоединен от выходного вывода OC1B
Нормаль
0 1 Подключение выходной линии OC1B к таймеру/счетчику 1
ный
режим 1 0 Очистка выходной линии OC1B (установка в состояние 0).
1 1 Установка выходной линии OC1B (установка в сост. 1).
0 0 Таймер/счетчик 1 отсоединен от выходного вывода OC1B
ШИМ
0 1 СТС режим таймера/счетчика 1 канала В
режим
1 0 Прямой ШИМ таймера/счетчика 1 канала В
1 1 Инверсный ШИМ таймера/счетчика 1 канала В

Bit 3 – FOC1A: Force Output Compare for channel A. Выход сравнения


для канала А.
Bit 2 – FOC1B: Force Output Compare for channel A. Выход сравнения
для канала В.
Теперь рассмотрим регистр TCCR1B (таблица 6.24), а затем вернемся к
оставшимся битам регистра TCCR1A.

54
Таблица 6.24 – Регистр управления таймером/счетчиком 1 TCCR1B
Бит 7 6 5 4 3 2 1 0

Чтение / R/W R/W R R/W R/W R/W R/W R/W


Запись
Номер ICNC1 ICES1 - WGM13 WGM12 CS12 CS11 CS10
перыв.
Нач.знач 0 0 0 0 0 0 0 0

Bit 7 – ICNC1: Input Capture1 Noise Canceller – Установка режима


подавления шума на входе захвата таймера/счетчика 1. При сброшенном в
состояние в 0 бите ICNC1 функция подавления шума входного триггера
захвата запрещена. Вход захвата переключается по первому
нарастающему/падающему фронту, поступившему на вывод входа захвата
PB0(ICP). При установленном в состояние 1 бите ICNC1 выполняются
четыре последовательных опроса состояния вывода PB0(ICP) и все четыре
выборки должны иметь одинаковый (высокий или низкий) уровень.
Bit 6 – ICES1: Input Capture1 Edge Select – Выбор фронта срабатывания
на входе захвата счета таймера/счетчика 1. При сброшенном в состояние 0
бите ICES1 содержимое таймера/счетчика1, по заднему фронту сигнала на
выводе PB0(ICP) пересылается в регистр захвата ICR1. При установленном в
1 бите ICES1 содержимое таймера/счетчика 1 пересылается в регистр захвата
ICR1 по нарастающему фронту на PB0(ICP).
Bit 5 – в микроконтроллере ATmega8 не используется. Зарезервирован
под другие модели.
Bits 2, 1, 0 – CS12, CS11, CS10: Clock Select – Выбор источника тактовой
частоты. Установкой состояния данных битов производится выбор источника
тактового сигнала (в том числе коэффициента предварительного деления)
(таблица 6.25).
Таблица 6.25 – Выбор источника тактового сигнала таймера/счетчика 1
CS12 CS11 CS10 Описание
0 0 0 Stop условие – таймер/счетчик 1 остановлен
0 0 1 CK
0 1 0 CK / 8
0 1 1 CK / 64
1 0 0 CK / 256
1 0 1 CK / 1024
1 1 0 Внешний тактирующий сигнал на выводе T1, задний фронт
1 1 1 Внешний тактирующий сигнал на выводе T1, передний фронт
Теперь рассмотрим оставшиеся биты регистров TCCR1A и TCCR1B,
которые определяют режим работы таймера/счетчика 1, т.е. нормальный
режим или ШИМ режим.
Bits 1,0 (регистр TCCR1A) и Bits 4, 3 (регистр TCCR1B) – WGM13,
WGM12, WGM11, WGM10: Выбор режима счета (работы таймера/счетчика 1
(таблица 6.26).
55
Таблица 6.26 – Выбор режима работы таймера/счетчика 1
Режим WG WG WG WG Комментарий Максимум
M13 M12 M11 M10 счета
0 0 0 0 0 Нормальный (обычный) режим 0xFFFF
таймера/счетчика 1
1 0 0 0 1 Обычный 8-битный ШИМ 0x00FF
2 0 0 1 0 Обычный 9-битный ШИМ 0x01F
3 0 0 1 1 Обычный 10-битный ШИМ 0x03FF
4 0 1 0 0 СТС режим OCR1A
5 0 1 0 1 Быстрый ШИМ 8-битный 0x00FF
6 0 1 1 0 Быстрый ШИМ 9-битный 0x01F
7 0 1 1 1 Быстрый ШИМ 10-битный 0x03FF
8 1 0 0 0 Обычный ШИМ с точной фазой и ICR1
частотой
9 1 0 0 1 Обычный ШИМ с точной фазой и OCR1A
частотой
10 1 0 1 0 Обычный ШИМ ICR1
11 1 0 1 1 Обычный ШИМ OCR1A
12 1 1 0 0 СТС режим ICR1
13 1 1 0 1 Зарезервировано (не используется) -
14 1 1 1 0 Быстрый ШИМ ICR1
15 1 1 1 1 Быстрый ШИМ OCR1A
Как видно из таблицы 6.25 таймер/счетчик 1 обладает 15-тью ШИМ
режимами. ШИМ – это широтно-импульсная модуляция, т.е. модуляция
(управление) напряжением или током, путем изменением ширины импульсов
при неизменной их величине. Т.е. ШИМ режим – это по сути аналоговый
выход, если судить по средней величине напряжения на выходе.
Режим ШИМ СТС – это частотная модуляция, т.к. время следования
импульсов всегда совпадает со временем следования паузы. В этом режиме
таймер/счетчик 1 считает до максимального значения, по достижении
которого сбрасывается в 0, вывод OCR1 переключается. Максимальное
значение счета, в этом случаи, определяется регистром уставкой таймера
счетчика 1 (рис. 6.17), т.е. этим регистром задается частота работы
таймера/счетчика 1 в СТС режиме.

56
Рис. 6.17. Режим ШИМ - СТС
Быстрый ШИМ (рис. 6.18) – этот
режим почти аналогичен СТС режиму.
Отличие в том, что максимум счета
определяется, не фиксированной
величиной, а регистром задающий
максимум счета (см. таблицу 6.29), а
уставка задается регистром уставки.
Переключение выводной линии
таймера/счетчика 1 в этом режиме
происходит при достижении уставки или
максимума счета.
Кроме быстрого ШИМ, существует
обычный ШИМ – это реверсивный счет.
Т.е. таймер/счетчик 1 считает до
Рис. 6.18. Быстрый ШИМ
максимального значения, по достижению
которого направления счета меняется, и
таймер/счетчик считает от
максимального числа до нуля, где снова
меняет направление счета (рис. 6.19).
Изменяя только регистр уставки для
ШИМ и максимум счета ШИМ,
получается 16 вариантов ШИМ,
представленных в таблице 6.25. Но
подробное изучение каждого режима
работы ШИМ не представляется
необходимым в этом пособии. Здесь
представлено только возможность
программирования таймера/счетчика 1 в
различных ШИМ режимах. Даны
Рис. 6.19. Обычный режим ШИМ некоторые основные моменты. Более

57
подробно с каждым из вариантов ШИМ вам предлагается разобраться
самостоятельно.
Так как ШИМ режим – это изменяющийся меандр, то называть его
аналоговым выходом в полном смысле нельзя. Для того, чтобы превратить
его в аналоговый выход необходимо использовать фильтры (рис. 6.20 или
рис. 6.21).

Рис. 6.20. Пассивный фильтр Рис. 6.21. Активный фильтр 1-го порядка

Теперь вернемся к изучению таймера/счетчика 1. Кроме регистров


управления TCCR1A, TCCR1B таймер/счетчик 1 содержит 16-разрядный
регистр счета, состоящий из двух 8 разрядных регистров (TCNT1H, TCNT1L).
Также таймер/счетчик 1 содержит два 16-разрядных регистра уставки –
OCR1A и OCR1B. Т.е. счетный 16 разрядный регистр – один, а 16-разрядных
регистров уставок два, по совпадению счета с каждой из уставок происходит
прерывание. Это значительно расширяет возможности программиста. Такие
бы функции можно было бы сделать и на других двух таймеров, но увы,
такая возможность существует только в таймере/счетчике 1.
Таймер/счетчик 1 обладает очень интересной и полезной функцией –
функция запоминания, захвата (capture) заключается в запоминании счета,
сформированного в базовом счетчике (TCNT1), в специальном регистре
захвата (ICR1) при изменении значения определенного внешнего или
внутреннего сигнала.
Пример 6.24. В этом примере с одного канала АЦП задается уставка на
Изучение ШИМ таймер 1 в режиме А, с другого на канал В. Обратите внимание, что
таймера/счетчика в этом примере происходит считывание с двух каналов АЦП, двух
1 разных аналоговых сигналов. Выводы OC1A и OC1B
подключаются на светодиоды.
.INCLUDE "m8def.inc" ;Подключение файла констант
.CSEG
.ORG 0x00
RJMP START
.ORG 0x00E ;Прерывание АЦП
RJMP ADC_obchee
START: ;Начало программы
CLI ;Запрет всех прерываний

58
;---------------------------
LDI r19,0b11101000 ;Инициализация АЦП
OUT ADCSR, r19
LDI r19,0b01100000
OUT ADMUX, r19
;--------------------------
LDI r19, HIGH(RAMEND) ;Инициализация стека
OUT sph, r19
LDI r19,LOW(RAMEND)
OUT spl, r19
;---------------------------
LDI r19,0xFF
OUT DDRB,r19 ;Регистр порта В на вывод
LDI r19,0xFC
OUT DDRC,r19 ;мл.бита на ввод остальные на вывод
;--------------------------
LDI r19,0b 1 0 1 0 0 0 0 1 ;Инициализация таймера 1
Выбор режима ШИМ (8 разр. обычный)
Подключить вывод прямого ШИМ канала В
Подключить вывод прямого ШИМ канала А

OUT TCCR1A,r19
LDI r19,0b 0 0 0 0 1 001
Частота квантования СК
Выбор режима ШИМ (8 разр. обычный)
OUT TCCR1B,r19
SEI ;Разрешить прерывания
LOOP: ;Пустой цикл
SBI ADCSR,6 ;Разрешить еще одно прерывание АЦП
NOP
RJMP LOOP
ADC_obchee: ;Прерывание АЦП
IN r16,ADCH ;Считать старший байт АЦП
SBIS ADMUX,0 ;Проверить номер, подключенного АЦП
RJMP ADC0 ;Идти на подпрограмму обработ. АЦП0
RJMP ADC1 ;Идти на подпрограмму обработ. АЦП1
;--------------------------------------------
ADC1: ;Подпрограмма обработки АЦП1
LDI r19,0b01100000 ;Переключить мультиплексор АЦП на 0
OUT ADMUX, r19
OUT OCR1AL,r16 ;Выдать содержимое на уставку А
RETI ;Возврат из прерывания АЦП
;----------------------------------------
ADC0: ;Подпрограмма обработки АЦП0
LDI r19,0b01100001 ;Переключить мультиплексор АЦП на 1
OUT ADMUX, r19
OUT OCR1BL,r16 ;Выдать содержимое на уставку В
RETI ;Возврат из прерывания АЦП
.EXIT

59
Пример 6.25. .INCLUDE "m8def.inc" ;Подключение файла констант
Использование .CSEG
таймера/счетчика .ORG 0x00 ;Перейти на начало
1 как счетчика и RJMP START
изучение .ORG 0x005 ;Прерывание захвата таймера 1
функции захвата RJMP Zahvat_T1 ;Перейти на подпрограмму
счета. START: ;Начало
CLI ;Запрет всех прерываний
LDI r19, HIGH(RAMEND) ;Инициализация стека
OUT sph, r19
LDI r19,LOW(RAMEND)
OUT spl, r19
LDI r19,0xFE
OUT DDRB,r19;Регистр порта В на вывод, кроме 0 бита-захвата
счета
LDI r19,0xFF
OUT DDRC,r19 ;Все на вывод
LDI r19,0x00
OUT DDRD,r19 ;Все на ввод
LDI r19,0b00000000 ;Инициализация таймера 1
OUT TCCR1A,r19
LDI r19,0b11000111 ;передний фронт внешнего сигнала
OUT TCCR1B,r19
LDI r19,0b00100000 ;разрешить прерывание захвата
OUT TIMSK,r19
SEI ;Разрешить прерывания
LOOP: ;Пустой цикл
NOP
RJMP LOOP
Zahvat_T1: ;Подпрограмма обработки захвата
IN r19,ICR1L ;Считать младший бит регистра захвата
LSR r19
LSR r19
OUT PORTB,r19 ;Выдать на индикацию
IN r19,ICR1L
LSL r19
LSL r19
OUT PORTC,r19
RETI ;Возврат из прерывания
.EXIT
Таймер/счетчик 2
Восьмиразрядный таймер/счетчик 2 получает тактовый сигнал, или
непосредственно от генератора импульсов, или после прохождения его через
предварительный делитель. Но особенностью работы таймера/счетчика 2
заключается в том, что у него нет счетного входа, т.е. он не может
непосредственно считать импульсы на входе. Но возможно считывать
импульсы с какой-либо ножки и увеличивать счет в регистре счета. Поэтому
он, по-прежнему, называется таймером/счетчиком, а не просто таймером.

60
Установки управляющих сигналов (настройки) хранятся в регистрах
управления таймером/счетчиком 2 – TCCR2.
Таймеры/счетчик 2 можно использовать, не только как 8-разрядные
таймер/счетчик, но и как широтно-импульсные модулятор (ШИМ), в отличии
от таймера/счетчика 0.
Для управления таймером/счетчиком 2 существует три регистра
а) TCCR2 – регистр выбора режима работы;
б) TCNT2 – регистр счета;
в) OCR2 – регистр уставки.
Регистр TCCR2 определяет режим работы таймера/счетчика 2. Описание
этого регистра приведено в таблице 6.27.
Таблица 6.27 – Регистр TCCR2
Бит 7 6 5 4 3 2 1 0

Чтение / W R/W R/W R/W R/W R/W R/W R/W


Запись
Номер FOC2 WGM20 COM21 COM20 WGM21 CS22 CS21 CS20
перыв.
Нач.знач 0 0 0 0 0 0 0 0

Bit 7 – FOC2: Force Output Compare. Бит FOC2 установлен в 1, когда


биты WGM20 и WGM21 определяют режим нормальной работы
таймера/счетчика 2. Однако, для гарантии бит должен быть установлен на 0,
когда таймер/счетчик 2 работая в режиме ШИМ. Работу различных ШИМ
режимов поясним на рис. 6.22 – рис. 6.24.
FF
уставка

Выход

Рис.6.22. СТС режим

61
FF

уставка
Выход

Инверсный
выход
Рис.6.23. Неполный ШИМ (Fast PWM) режим

FF
уставка

Выход
Инверсный
выход

Рис. 6.24 Обычный PWM (ШИМ) режим

Bits 6 и 3 – WGM21 и WGM20: Waveform Generation Mode. Эти биты


определяют режим работы таймера/счетчика 2 согласно таблице 6.28. В
отличии от таймера/счетчика 1. Здесь гораздо меньше вариантов работы
ШИМ.
Таблица 6.28 – Режим работы таймера/счетчика 2
WGM21 WGM20 Комментарий
0 0 Нормальный режим таймера
0 1 Режим работы обычного ШИМ
1 0 СТС – ШИМ режим (частотная модуляция)
1 1 Быстрый ШИМ (Fast PWM)
Bits 5 и 4 – COM21 и COM20: Compare Output Mode. Управляющие
биты COM21 и COM20 определяют подсоединение к выходной линии OC2
таймера/счетчика 2, т.е эти биты устанавливают состояние выходного вывода
таймера/счетчика 2 PB3(OC2). Поскольку это альтернативная функция
вывода порта, то соответствующий бит направления вывода должен быть
установлен в состояние 1 (регистр DDRB). Управляющая конфигурация
показана в таблице 6.29.

62
Таблица 6.29 – Подсоединение линииOC2
COM21 COM20 Комментарий
0 0 Таймер/счетчик 2 отсоединен от линии OC2
0 1 Таймер/счетчик 2 подсоединен к линии OC2
1 0 Линия OC2 подсоединена к сигналу 0
1 1 Линия OC2 подсоединена к сигналу 1
Bits 2, 1, 0 – CS22, CS21, CS20: Clock Select bits 2,1 and 0 - Биты выбора
тактовой частоты таймера/счетчика 2 подключают вход таймера/счетчика к
определенному источнику сигнала импульсов согласно таблице 6.30. Изучив
внимательно таблицу, видим, что таймер/счетчик 2 не может быть
подсоединен к внешнему выводу. Он может только считать временные
интервалы.
Таблица 6.30 – Источник входного сигнала таймера/счетчика 2
CS22 CS21 CS20 Описание
0 0 0 Таймер/счетчик 2 остановлен.
0 0 1 CK
0 1 0 CK / 8
0 1 1 CK / 32
1 0 0 CK / 64
1 0 1 CK / 128
1 1 0 CK / 256
1 1 1 CK / 1024

63
Пример 6.26. .INCLUDE "m8ef.inc";Подключение файла констант
Программа .CSEG ;Сегмент кода
регулирования .ORG 0
угла управления RJMP START ;Перейти на начало программы
тиристором .ORG 0x003 ;Прерывание по совпадению таймера 2
RJMP T2
.ORG 0x009 ;Прерывание по переполнению таймера 0
RJMP T0
.ORG 0x00E ;Прерывание АЦП
RJMP ADC1
START: ;Начало программы
CLI ;Запрет всех прерываний
LDI r19,0b 1 1 0 0 1 1 1 1 ;Инициализация АЦП
Максимальный предделитель
ADIE=1 Разр. прерыв. АЦП
Одноразовое преобразование
ADSC=1 Начать преобразование
ADEN=1 Подключить АЦП
OUT ADCSR, r19
LDI r19,0b 0 1 1 0 0 0 0 1
Подключить канал ADC1

ADLAR=1 Выравнивание вправо

Источник опорного напр. AVCC


OUT ADMUX, r19
;----------------------------------------------------------------------------------------
LDI r19, HIGH(RAMEND) ;Инициализация стека
OUT sph, r19
LDI r19,LOW(RAMEND)
OUT spl, r19
;----------------------------------------------------------------------------------------
LDI r19, 0xFC
OUT DDRB,r19 ;Регистр порта В на вывод, кроме мл.2х бит
OUT DDRС,r19 ;Регистр порта С на вывод, кроме мл.2х бит
LDI r19,0xFF
OUT DDRD,r19
;-----------------------------Инициализация таймера 2------------------------
LDI r19,0b1 0 0 0 0 0 0 0
Таймер 2 остановлен

Нормальный режим работы


Таймер отсоединен от выходной
линии
OUT TCCR2,r19
;------------------Генерация импульсов положительной и -----
;отрицательной полуволны синусоиды-------
64
LDI r19,0b 0 0 0 0 0 0 1 1
OUT TCCR0,r19 Предделитель СК/64
LDI r19,0b10000001 ;разрешить прерывание таймера 2
;по совпадению и таймера 0 по
;переполнению
OUT TIMSK,r19
SEI ;Разрешить прерывания
K1:
SBRC r16,7
RJMP K2
LDI r19,0b1 0 0 0 0 0 0 0
Таймер 2 остановлен

Таймер отсоединен от выходной линии


Нормальный режим работы
OUT TCCR2,r19
LDI r19,0x00
OUT PORTD,r19
RJMP K1
K2:
LDI r19,0b1 0 0 0 0 1 0 0

Таймер 2 запустить с частотой СК/64

Таймер отсоединен от выходной линии


Нормальный режим работы
OUT TCCR2,r19
OUT OCR2,r28 ;Уставка таймера 2
RJMP K
ADC1: ;Подпрограмма прерывания АЦП
IN r28, ADCН ;Считать старший байт АЦП
RETI
;--------------------------------- Прерывание Т2 по совпадению ----------------
--
T2:
LDI r19,0x80
OUT PORTD,r19
MOV r20, r28
LSR r20 ;Выровнять младшую тетраду байта
LSR r20 ;под биты вывода порта В
LSR r20
ANDI r20,0x3C
OUT PORTB, r20
MOV r20, r19
LSL r20 ;Выровнять старшую тетраду байта
ANDI r20, 0x3C ;под биты вывода порта С
OUT PORTC, r20
65
SBI ADCSR,6
RETI

;----------------------------- Прерывание Т0 по переполнению ----------------


T0:
LDI r16,0x80 ;Бит 7 в r17 через равные промежутки
ADD r17,r16 ;времени, то 1, то 0
RETI
;------ -----------------------------------------------------------------------------------
.EXIT
Теперь изучив все таймеры/счетчики микроконтроллера ATmega 8 заметим
такую особенность. Таймеров/счетчиков всего – три. В документации на
микроконтроллер сказано, что он обладает тремя выходными каналами
ШИМ, но таймер/счетчик 0 вообще не обладает выходом для ШИМ режима,
а значит не может работать в ШИМ режиме. Для устранения этого
противоречия обратим внимание на таймер/счетчик 1, у которого есть
возможность записать две уставки (А и В). Кроме того, рассмотрев рис. 6.7,
видим, что у таймера/счетчика 1 две выходные ножки (PB2/OC1B и
PB1/OC1A), т.е. таймер/счетчик 1 может выдавать два ШИМ сигнала. Кроме
того, в микроконтроллере имея только один свободный таймер можно
реализовать столько ШИМ выходов, сколько свободных ножек у
микроконтроллера. Для этого используются свободные регистры РОНы
микроконтроллера, которые служат счетными регистрами и регистрами
уставками. Эта операция делается программным путем, а не с помощью
аппаратных средств заложенных в микроконтроллер.

66
БИБЛИОГРАФИЧЕСКИЙ СПИСОК

1. ATmega8 и ATmega8L. Техническая документация / Atmel. – 303 c.


2. Гребнев, В.В. Микроконтроллеры семейства AVR фирмы Atmel. /
В.В. Гребнев. – М.: ИП РадиоСофт, 2002 – 176 с.
3. Евстифеев, А.В. Микроконтроллеры AVR семейства Classic фирмы
"ATMEL" / А.В. Евстифеев. – М.:Издательский дом " Додэка – XXI",
2002. – 288с.
4. Ревич, Ю.В. Практичексое программирование микроконтроллеров
Atmel AVR на языке ассемблера. / Ю.В. Ревич. – СПб.: БХВ-Петербург,
2008. – 384с.

67
ПРИЛОЖЕНИЕ Г
(справочное)
СИСТЕМА КОМАНД ATMEGA8
Принятые следующие сокращения:
Регистры и операнды:
Rd: Регистр назначения (и источник) в регистровом файле. Т.е. это тот регистр,
куда будет направлен результат после определенной операции в ALU.
Rr: Регистр источник в регистровом файле. Второй регистр, подаваемый на вход
ALU.
K: Литерал или байт данных (8 бит).
k: Данные адреса константы для счетчика программ.
b: Бит в регистровом файле или I/O регистр.
s: Бит в регистре статуса
X,Y,Z: Регистр косвенной адресации (X=R27:R26, Y=R29:R28, Z=R31:R30)
P: Адрес I/O порта
Стек
STACK: Стек для адреса возврата и опущенных в стек регистров.
Регистр статуса – SREG представлен в таблице Г.1
Таблица Г.1 – Регистр статуса - SREG - размещен в пространстве I/O
Бит 7 6 5 4 3 2 1 0

Чтение/ R/W R/W R/W R/W R/W R/W R/W R/W


Запись
Номер I T H S V N Z C
перыв.
Нач.знач 0 0 0 0 0 0 0 0

Bit 7 – I: Global Interrupt Enable - Разрешение глобального прерывания.


Бит разрешения глобального прерывания для разрешения прерывания
должен быть установлен в состояние 1. Управление разрешением
конкретного прерывания выполняется регистрами маски прерывания GICR и
TIMSK. Если бит глобального прерывания очищен (в состоянии 0), то ни
одно из разрешений конкретных прерываний, установленных в регистрах и
GICR, ни TIMSK, не действует. Бит I аппаратно очищается в 0 после
появлении прерывания и устанавливается снова в 1 командой RETI (возврат
из подпрограммы обработки прерывания).
Bit 6 – T: Bit Copy Storage - Бит сохранения копии. Команды
копирования бита BLD (Bit LoaD) и BST (Bit STore) используют бит T как бит
источник и бит назначения при операциях с битами. Командой BST бит
регистра регистрового файла копируется в бит T, командой BLD бит T
копируется в регистр регистрового файла.

68
Продолжение приложения Г

Bit 5 – H: Half Carry Flag – Флаг полупереноса. Флаг полупереноса


указывает на полуперенос в ряде арифметических операций, т.е. при
переходе 1 из одной тетрады байта в другую он устанавливается в 1.
Bit 4 – S: Sign Bit, S = N+V - Бит знака. Бит S всегда находится в
состоянии, которое определяется логическим состоянием флага
отрицательного значения N и дополнением до двух флага переполнения V.
Bit 3 – V: Two’s Complement Overflow Flag – Дополнение до двух флага
переполнения. Дополнение до двух флага V поддерживает арифметику
дополнения до двух.
Bit 2 – N: Negative Flag – Флаг отрицательного значения. Флаг
отрицательного значения N указывает на отрицательный результат ряда, т.е.
устанавливается в 1, если после выполнения какой-то команды в ALU в
старшем разряде байта (или слова) находится 1.
Bit 1 – Z: Флаг нулевого значения. Устанавливается в 1 состояние, если
результат в ALU после выполнения заданного арифметического действия
равен нулю.
Bit 0 – C: Флаг переноса. Устанавливается в единичное состояние, если
результат имеет большую разрядность, чем приемник результата.

69
Продолжение приложения Г

Таблица Г.2 – Система команд микроконтроллера ATmega 8


Команда Операнды Функция Комментарии Флаг Число
и тактов
Rd, Rr Rd<-Rd+Rr+C Z,C,N, 1
ADC Сложить с переносом
V,H
Rd, Rr Rd<-Rd+Rr Z,C,N, 1
ADD Сложить без переноса
V,H
Rdh:Rdl, k Сложить Rdh:Rdl<- Z,C,N, 2
ADIW непосредственное Rdh:Rdl+K V,S
значение со словом
Rd, Rr Выполнить логическое Rd<-Rd&Rr Z, N, 1
AND
AND V
Rd, K Выполнить логическое Rd<-Rd&K Z, N, 1
AND с V
ANDI
непосредственным
значением
Rd Арифметически Rd(n)<-Rd(n+1) Z, C, 1
ASR
сдвинуть вправо n=0…6 N, V
BCLR s Очистить флаг SREG(s)<-0 None 1
Rd, b Загрузить T флаг в бит Rd(b)<-T None 1
BLD
регистра
s, k Если SREG(s)=1 None 1/2
Перейти, если бит в
BRBC тогда PC<-
регистре статуса очищен
PC+k+1
s, k Перейти если бит в Если SREG(s)=0 None 1/2
BRBS регистре статуса тогда PC<-
установлен PC+k+1
k Перейти, если флаг Если C=0, тогда None 1/2
BRCC
переноса очищен PC<-PC+k+1
k Перейти, если флаг Если C=1, тогда None 1/2
BRCS
переноса установлен PC<-PC+k+1
k Если Z=1, тогда None 1/2
BREQ Перейти, если равно
PC<-PC+k+1
k Перейти, если больше Если N+V=0, None 1/2
BRGE или равно (с учетом тогда PC<-
знака) PC+k+1
k Перейти если флаг Если H=0, тогда None 1/2
BRHC
полупереноса очищен PC<-PC+k+1
k Перейти, если флаг Если H=1, тогда None 1/2
BRHS полупереноса PC<-PC+k+1
установлен
k Перейти, если Если I=0, тогда None 1/2
BRID глобальное прерывание PC<-PC+k+1
запрещено

70
Продолжение приложения Г
Продолжение таблицы Г.2
Команда Операнды Функция Комментарии Флаг Число
и тактов
k Перейти, если глобальное Если I=1, тогда None 1/2
BRIE
прерывание разрешено PC<-PC+k+1
k Перейти если меньше (без Если C=1, тогда None 1/2
BRLO
знака) PC<-PC+k+1
k Если N+V=1, None 1/2
Перейти если меньше чем (со
BRLT тогда PC<-
знаком)
PC+k+1
k Если N=1, тогда None 1/2
BRMI Перейти если минус
PC<-PC+k+1
k Если Z=0, тогда None 1/2
BRNE Перейти если не равно
PC<-PC+k+1
k Если N=0, тогда None 1/2
BRPL Перейти если плюс
PC<-PC+k+1
k Перейти если равно или Если C=0, тогда None 1/2
BRSH
больше (без знака) PC<-PC+k+1
k Если T=0, тогда None 1/2
BRTC Перейти если флаг T очищен
PC<-PC+k+1
k Перейти если флаг T Если T=1, тогда None 1/2
BRTS
установлен PC<-PC+k+1
k Перейти если переполнение Если V=0, тогда None 1/2
BRVC
очищено PC<-PC+k+1
k Перейти если переполнение Если V=1, тогда None 1/2
BRVS
установлено PC<-PC+k+1
BSET s Установить флаг SREG(s)<–1 None 1
Rr, b Переписать бит из регистра T <-Rr(b) T 1
BST
во флаг T
k Выполнить длинный вызов PC<-k None 4
CALL
подпрограммы
CBI P, b Очистить бит в регистре I/O P <-0 None 2
Rd, K Rd<-(0xFF – Z,N,V 1
CBR Сбросить биты в регистре
Rd)*K
CLC Очистить флаг переноса C<-0 C 1
CLH Очистить флаг полупереноса H<-0 H 1
Очистить флаг глобального I<-0 I 1
CLI
прерывания
Очистить флаг N<-0 N 1
CLN
отрицательного значения
CLR Rd Очистить регистр Rd <-Rd+Rd Z,N,V 1
CLS Очистить флаг знака S<-0 S 1
CLT Очистить флаг T T<-0 T 1
CLV Очистить флаг переполнения V<-0 V 1
Очистить флаг нулевого Z<-0 Z 1
CLZ
значения
Rd Выполнить дополнение до Rd<-0xFF-Rd Z,C,N, 1
COM
единицы V

71
Продолжение приложения Г
Продолжение таблицы Г.2
Команда Операн Функция Комментарии Флаги Число
ды тактов
Rd, Rr Rd–Rr Z,N,V, 1
CP Сравнить
C,H
Rd, Rr Rd–Rr–C Z,N,V, 1
CPC Сравнить с учетом переноса
C,H
Rd, K Rd–K Z,N,V, 1
CPI Сравнить c константой
C,H
Rd, Rr Сравнить и пропустить если Если Rd=Rr, то None 1/2/3
CPSE
равно РС=PC+2or3
DEC Rd Декрементировать Rd=Rd-1 Z,N,V 1
EOR Rd, Rr Выполнить исключающее OR Rd=Rd+Rr Z,N,V 1
ICALL Вызвать подпрограмму косвенно PC <- Z None 3
IJMP Перейти косвенно PC<-Z None 2
Rd, P Загрузить данные из порта I/O в Rd<-P None 1
IN
регистр
INC Rd Инкрементировать Rd=Rd+1 Z,N,V 1
Rd, Rr R1:R0=(Rd*Rr) Z,C 2
FMUL Дробное незнаковое умножение
<<1
Rd, Rr R1:R0=(Rd*Rr) Z,C 2
FMULS Дробное умножение со знаком
<<1
Rd, Rr Дробное умножение знакового с R1:R0=(Rd*Rr) Z,C 2
FMULSU
незнаковым <<1
JMP k Перейти PC < -k None 3
LD Rd,X Загрузить косвенно Rd <- [X] None 2
Rd,X+ Загрузить косвенно Rd <- [X] X<- None 2
LD
инкрементировав впоследствии X+1
Rd, -X Загрузить косвенно X <- X-1 Rd <- None 2
LD
декрементировав предварительно [X]
Загрузить непосредственное Rd <- K None 1
LDI Rd, K
значение
Загрузить непосредственно из Rd <- [k] None 1
LDS Rd, k
СОЗУ
LPM Загрузить байт памяти программ R0 <- [Z] None 3
Rd(n+1)<-Rd(n) Z,C,N, 1
LSL Rd Логически сдвинуть влево
Rd(0)<-0 V
Rd(n)<-Rd(n+1) Z,C,N, 1
LSR Rd Логически сдвинуть вправо
Rd(7)<-0 V
MOV Rd,Rr Копировать регистр Rd<-Rr None 1
MUL Rd,Rr Перемножить R1:R0<-Rd*Rr Z,C 2
Rd Rd<-0x00-Rd Z,C,N, 1
NEG Выполнить дополнение до двух
V,H
NOP Выполнить холостую команду None 1

72
Продолжение приложения Г
Продолжение таблицы Г.2
Команда Опера Функция Комментарии Флаги Число
нды тактов
OR Rd, Rr Выполнить логическое OR Rd<-Rd\/Rr Z,N,V 1
Rd, K Выполнить логическое OR с Rd<-Rd\/K Z,N,V 1
ORI
непосредственным значением
P, Rr Записать данные из регистра в P<-Rr None 1
OUT
порт I/O
POP Rd Загрузить регистр из стека STACK<-Rd None 2
PUSH Rr Поместить регистр в стек Rr<-STACK None 2
k Вызвать подпрограмму PC<-PC+k+1 None 3
RCALL
относительно
RET Вернуться из подпрограммы PC<-STACK None 3
RETI Вернуться из прерывания PC<-STACK I 3
RJMP k Перейти относительно PC<-PC+k+1 None 2
Rd Rd(0)<-C Z,C,N, 1
ROL Сдвинуть влево через перенос Rd(n+1)<-Rd(n) V
C<-Rd(7)
Rd Rd(7)<-C Z,C,N, 1
Сдвинуть вправо через
ROR Rd(n)<-Rd(n+1) V
перенос
C<-Rd(0)
Rd,Rr Rd<-Rd-Rr-C Z,N,V, 1
SBC Вычесть с переносом
C,H
Rd,K Вычесть непосредственное Rd<-Rd-K-C Z,N,V, 1
SBCI
значение с переносом C,H
SBI P,b Установить бит в регистр I/O I/O(P,b)<-1 None 2
P,b Пропустить если бит в Если P(b)=0, то None 1/2/3
SBIC
регистре I/O очищен РС=PC+2or3
P,b Пропустить если бит в Если P(b)=1, то None 1/2/3
SBIS
регистре I/O установлен РС=PC+2 or 3
Rdl,k Вычесть непосредственное Rdh:Rdl<- Z,C,N, 2
SBIW
значение из слова Rdh:Rdl-K V,H
SBR Rd,b Установить биты в регистре Rd(b)<-1 None 1
Пропустить если бит в Если Rr(b)=0, то None 1/2/3
SBRC Rr,b
регистре очищен РС=PC+2or3
Пропустить если бит в Если Rr(b)=1, то None 1/2/3
SBRS Rr,b
регистре установлен РС=PC+2or3
SEC Установить флаг переноса C<- 1 C 1
Установить флаг H<- 1 H 1
SEH
полупереноса
Установить флаг глобального I<- 1 I 1
SEI
прерывания
Установить флаг N<- 1 N 1
SEN
отрицательного значения
SER Rd Установить все биты регистра Rd<-0xFF None 1
SES Установить флаг знака S<-1 S 1

73
Окончание приложения Г
Продолжение таблицы Г.2
Команда Операн Функция Комментарии Флаги Число
ды тактов
SET Установить флаг T T<-1 T 1
SEV Установить флаг V<-1 V 1
переполнения
SEZ Установить флаг нулевого Z<-1 Z 1
значения
SLEEP Установить режим SLEEP None 1
ST X,Rr Записать косвенно из [X]<-Rr None 2
регистра в СОЗУ с
использованием индекса X
ST Y,Rr Записать косвенно из [Y]<-Rr None 2
регистра в СОЗУ с
использованием индекса Y
ST Z,Rr Записать косвенно из [Z]<-Rr None 2
регистра в СОЗУ с
использованием индекса Z
STS k,Rr Загрузить непосредственно [k]<-Rr None 2
в СОЗУ
SUB Rd,Rr Вычесть без переноса Rd<-Rd-Rr Z,C,N,V, 1
H
SUBI Rd,K Вычесть непосредственное Rd<-Rd-K Z,C,N,V, 1
значение H
SWAP Rd Поменять тетрады местами Rd(3…0)<- None 1
Rd(7…4)
Rd(7…4)<-
Rd(3…0)
TST Rd Проверить на ноль или Rd<-Rd&Rd Z,N,V 1
минус
WDR None Сбросить сторожевой None None 1
таймер

74
ПРИЛОЖЕНИЕ Д
(справочное)
ДИРЕКТИВЫ АССЕМБЛЕРА AVR
Д.1. Общая информация
Программа пишется с помощью транслятора (переводчика с языка
мнемоники на язык 16-ных кодов, понятных микроконтроллеру), основой
которого является ассемблер AVR.
Ассемблер – это инструмент, с помощью которого создается программа
для микроконтроллера. Ассемблер транслирует ассемблируемый исходный код
программы в объектный код, который может использоваться в симуляторах
или эмуляторах AVR. Также ассемблер генерирует код, который может быть
непосредственно введен в программную память микроконтроллера.
При работе с ассемблером нет никакой необходимости в
непосредственном соединении с микроконтроллером.
Исходный файл, с которым работает ассемблер, должен содержать
мнемоники, директивы и метки.
Перед каждой строкой программы можно ставить метку, которая
является алфовитно-цифровой строкой, заканчивающейся двоеточием
(Пример: START:, a1: , …). Метки используются как указания для
безусловного перехода и командах условного перехода.
Строка программы может быть в одной из четырех форм:
[Метка:] директива [операнды] [Комментарий]
[Метка:] команда [операнды] [Комментарий]

Комментарий (Комментарий имеет следующую форму: ;[Текст]).


Операнды можно задавать в различных форматах:
 десятичный (по умолчанию): 10 или 255
 шестнадцатеричный (два способа): 0х0А, $0А
 двоичный: 0b00001010
 восьмеричный (впереди ноль): 010 или 077
Пример:
START: LDI r19,0xFF ;Занести в r19 число FF

75
Продолжение приложения Д

Д.2. Синтаксис директив


Все директивы ассемблера представлены в таблице Б.1.
Таблица Д. 1 – Директивы ассемблера AVR
Директива Описание
BYTE Зарезервировать байт под переменную
CSEG Сегмент кодов
DB Задать постоянным(и) байт(ы) в памяти
DEF Задать символическое имя регистру
DEVICE Задать для какого типа микроконтроллера компилировать
DSEG Сегмент данных
DW Задать постоянное(ые) слово(а) в памяти
EQU Установите символ равный выражению
ESEG Сегмент EEPROM
EXIT Выход из файла
INCLUDE Включить исходный код из другого файла
LIST Включить генерацию *.LST – файла
NOLIST Выключить генерацию *.LST – файла
ORG Начальный адрес программы
SET Установите символ равный выражению
MACRO Начало макрокоманд
ENDMACRO Конец макрокоманд
Синтаксис всех директив следующий: .[директива]
Пример: .CSEG
То есть перед директивой должна стоять точка. Иначе ассемблер
воспринимает это как метку.
Дадим несколько пояснений наиболее важным директивам ассемблера:
CSEG – Code segment. Директива CSEG указывает на начало сегмента
кодов. Ассемблируемый файл может иметь несколько кодовых сегментов,
которые будут объединены в один при ассемблировании.
Синтаксис: .CSEG
Пример:
.DSEG ;Начало сегмента данных
vartab: .BYTE 4 ;Резервируется 4 байта в СОЗУ
.CSEG ;Начало сегмента кодов
const: .DW 2 ;Записать 0x0002 в программной памяти
mov r1 ,r0 ;Что-то делать

DSEG – Data Segment. Директива DSEG указывает на начало сегмента


данных. Ассемблируемый файл может содержать несколько сегментов
данных, которые потом будут собраны в один при ассемблировании. Обычно
сегмент данных состоит лишь из директив BYTE и меток.
Синтаксис: .DSEG

76
Продолжение приложения Д
Пример:
.DSEG ; Начало сегмента данных
Var1: .BYTE 1 ; Резервировать 1 байт под переменную
table: .BYTE tab_size ; Резервировать tab_size байтов.
.CSEG
LDI r30,LOW(Var1)
LDI r31,HIGH(Var1)
LD rl, Z
ESEG – EEPROM Segment. Директива ESEG указывает на начало
сегмента EEPROM памяти. Ассемблируемый файл может содержать несколько
EEPROM сегментов, которые будут собраны в один сегмент при
ассемблировании. Обычно сегмент EEPROM состоит из DB и DW директив
(и меток). Сегмент EEPROM памяти имеет свой собственный счетчик.
Директива ORG может использоваться для размещения переменных в нужной
области EEPROM.
Синтаксис: .ESEG
Пример:
.DSEG
var1: BYTE 1 ;Зарезервировать 1 байт в области памяти
данных
tаble: .BYTE tab_size ;Зарезервировать таблицу данных
.ESEG
eevarl: .DW 0xFF FF ;Записать 1 слово FF FF в EEPROM
.ORG – установить адрес программы. Директива ORG присваивает
значения локальным счетчикам. Используется только совместно с
директивами .CSEG, .DSEG, .ESEG.
Синтаксис .ORG адрес
Пример:
.DSEG ;Начало сегмента данных
.ORG 0x37 ;Установить адрес СОЗУ на 37h
variable: .BYTE 1 ;Зарезервировать байт СОЗУ по адресу 37h
.CSEG ;Начало сегмента данных
.ORG 0x10 ;Установить счетчик команд на адрес 10h
MOV r0, r1 ;Чего-нибудь делать
.DB – определить байт(ы) в программной памяти или в EEPROM.
Директива DB резервирует ресурсы памяти в программной памяти или в
EEPROM. Директиве должна предшествовать метка. Директива DB задает
список выражений, и должна содержать, по крайней мере, одно выражение.
Размещать директиву следует в сегменте кодов или в EEPROM сегменте.
Список выражений представляет собой последовательность выражений,
разделенных запятыми. Каждое выражение должно быть величиной между -
128 и 255.

77
Продолжение приложения Д

Если директива указывается в сегменте кодов и список выражений


содержит более двух величин, то выражения будут записаны так, что 2 байта
будут размещаться в каждом слове Flash - памяти.
.DW – Определить слово(а) в программной памяти или в EEPROM.
Директива DW резервирует ресурсы памяти в программной памяти или в
EEPROM. Директиве должна предшествовать метка. Директива DW задает
список выражений, и должна содержать, по крайней мере, одно выражение.
Размещать директиву следует в сегменте кодов или в EEPROM сегменте.
Список выражений представляет собой последовательность
выражений, разделенных запятыми. Каждое выражение должно быть
величиной между -32768 и 65535.
Синтаксис: LABEL: .DW список выражений
Пример:
.CSEG
varlist: .DW 0, 0xFFFF, 0b 0011 1000 1010 1010, -32768, 65535
.ESEG
eevarlist: .DW 0, 0xFFFF, 10

.DEF - Присвоить имя регистру. Директива DEF позволяет присвоить


символическое имя регистру. Регистр может иметь несколько символических
имен.
Синтаксис: .DEF Имя = Регистр
Пример:
.DEF temp = R16
.DEF ior = R0
.CSEG
LDI temp, 0хF0 ;Загрузить 0xF0 в регистр temp
IN ior,0x3F ;Прочитать SREG в регистр ior
EOR temp

.EQU – Присвоить имя выражению. Директива EQU присваивает


значение метке. Эта метка может быть использована в других выражениях.
Значение этой метки нельзя изменить или переопределить.
Синтаксис: .EQU метка = выражение
Пример:
.EQU io_offset = 0x23
.EQU porta_ = io_offset + 2
.CSEG ; Начало сегмента кодов
CLR r2 ;Очистить регистр r2
OUT porta_, r2 ;Записать в porta_ содержимое регистра r2
.INCLUDE -вставить другой файл. Директива INCLUDE говорит
ассемблеру начать читать из другого файла. Ассемблер будет выполнять
работу с этим файлом до конца или до директивы EXIT. Включаемый файл
может сам включать директивы INCLUDE.

78
Продолжение приложения Д

Синтаксис: .INCLUDE "имя файла"


Пример:
.EQU SREG = 0x3F ;Регистр статуса
.EQU sphigh = 0х3E ;Старший байт указателя стэка
.EQU splow = 0x3D ;младший байт

.INCLUDE “iodefs.asm” ;Включить файл iodefs.asm


IN r0, SREG ;Прочитать регистр статус

.EXIT – выйти из файла. Директива EXIT позволяет ассемблеру


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

.DEVICE – Указать для какого микроконтроллера пишется программа.


Директива позволяет пользователю сообщить ассемблеру, для какого типа
устройства пишется программа. Если ассемблер встретит команду, которая
не поддерживается указанным типом микроконтроллера, то будет выдано
сообщение. Также сообщение появится в случае, если размер программы
превысит объем имеющейся в этом устройстве памяти.
Синтаксис:.DEVICE AT90S1200 | AT90S2313 | AT90S2323 | AT90S2333
AT90S4414 I AT90S4433 | AT90S4434 | AT90S8515 | AT90S8534 ATtiny 11 |
ATtiny 12 | ATtiny 22 | ATmega603 | ATmega103| …
Пример:
.DEVICE ATmega8
.CSEG
.ORG 0000
Директивы .MACRO и .ENDMACRO обрамляют участок программы
[макроопределение), который должен ассемблироваться каждый раз, когда в
поле для мнемокодов команд и директив ассемблера появляется имя, заданное
директивой .MACRO. В макроопределении вместо конкретных имен и
значений могут вводиться обобщенные обозначения параметров @0, @1 @9.
В макровызове после имени указываются значения параметров для
данного макровызова в порядке их номеров.
Синтаксис – MACRO Имя @1 @2
Пример.
.MACRO ADD16 @0,@1, @2, @3
ADD @0,@1
ADDC @2,@3
.ENDMACRO
.CSEG
ADD16 R4, R10, R5, R11

79
Окончание приложения Д

Д.3. Некоторые особенности программирования


Память данных почти полностью доступна программе пользователя и
большинство команд ассемблера предназначено для обмена данными с ней.
Команды пересылки данных предоставляют возможность непосредственной
и косвенной адресации ячеек СОЗУ, непосредственной адресации регистров
ввода/вывода и регистров общего назначения. Так как каждому регистру
сопоставлена ячейка памяти, то обращаться к ним можно не только
командами адресации регистров, но и командами адресации ячеек СОЗУ.
Пример:
MOV r10,r15 ;Cкопировать регистр R15 в регистр R10
Делает абсолютно, то же самое, что и команда:
LDS r10,$0015 – загрузить в регистр R10 содержимое ячейки с адресом
0x0015, т.е. РОН 15.
То же самое относится и к регистрам ввода/вывода. Для них
предусмотрены специальные команды:
IN Rd,P – загрузить данные из порта I/O с номером Р в регистр Rd
OUT P,Rd – записать данные из регистра Rd в порт I/O с номером Р.
Для работы с данными, расположенными в памяти программ,
предусмотрена команда LPM – загрузить байт памяти программ, на который
указывает регистр Z в регистр r0.
При работе с портами ввода/вывода следует учитывать следующую
особенность. Если вывод порта сконфигурирован как выход, то его
переключение производится через регистр данных (PORTB, PORTC, PORTD),
если вывод сконфигурирован как вход, то его опрос следует производить
через регистр выводов входа порта (PINB, PINC, PIND).
Особенностью использования арифметических и логических команд является
то, что некоторые из них работают только с регистрами R16 - R31.

80
Оглавление
6 МИКРОКОНТРОЛЛЕР ФИРМЫ ATMEL ATmega8 ........................................ 3
6.1 Общие сведения о микроконтроллере ATmega8 ......................................... 8
6.2 Архитектура микроконтроллера ATmega8 ................................................ 11
6.3 Исследование системы команд микроконтроллера ATmega8 .................. 16
6.4 Работа портов микроконтроллера на прием и выдачу информации ....... 22
6.5 Работа с памятью SRAM микроконтроллера ............................................. 28
6.6 Прерывания ATmega8 ................................................................................. 28
6.7 Компаратор ................................................................................................. 37
6.8 Аналоговый цифровой преобразователь ................................................... 42
6.9 Прерывания таймеров ................................................................................ 47
6.10 Работа таймеров/счетчиков микроконтроллера ATmega8 ........................ 49
БИБЛИОГРАФИЧЕСКИЙ СПИСОК ............................................................... 67
ПРИЛОЖЕНИЕ Г. СИСТЕМА КОМАНД ATMEGA8 ..................................... 68
ПРИЛОЖЕНИЕ Д. ДИРЕКТИВЫ АССЕМБЛЕРА AVR ................................. 75

81

Вам также может понравиться