Оглавление
- Arduino
- Переменные
- Принцип работы
- Объявление переменных
- __________________синтаксис цикла while_____________________________
- Создание проекта для Atmega8 в программной среде CodeVision
- Установка 0 в произвольном бите регистра порта
- Общие сведения о портах микроконтроллеров AVR
- Генератор тактовой частоты
- _____________________________________________________________________
- Пояснение части кода программы
- Инкремент и декремент
- Три условия для желающих освоить микроконтроллер
- Распиновка Atmega8
- Работа схемы
- Установка драйвера для USBASP в Windows 10
- Установка WinAVR в Atmel Studio
- ________________________________________________________
- 2.1 Архитектура 8-и разрядного AVR
- Обращение
Arduino
Это удобная платформа, выполненная в виде электронного конструктора, что подходит для быстрого создания различных устройств. В плате уже есть всё необходимое в виде самого микроконтроллера, его обвязки и программатора. Пойдя по этому пути, человек получит следующие преимущества:
- Низкий порог требований. Не нужно обладать специальными навыками и умениями для разработки технических устройств.
- Широкий спектр элементов будет доступен для подключения без дополнительной подготовки.
- Быстрое начало разработки. С Arduino можно сразу переходить к созданию устройств.
- Наличие большого количества учебных материалов и примеров реализаций различных конструкций.
Но есть и определённые минусы. Так, Arduino программирование Atmega8 не позволяет глубже окунуться в мир микроконтроллера и разобраться во многих полезных аспектах. Кроме этого, придётся изучить язык программирования, что отличается от применяемых AVR (C/Assembler). И ещё: Arduino имеет довольно узкую линейку моделей. Поэтому рано или поздно возникнет необходимость использовать микроконтроллер, что не используется в платах. А в целом это неплохой вариант работы с Atmega8. Программирование через Arduino позволит получить уверенный старт в мире электроники. И у человека вряд ли опустятся руки из-за неудач и проблем.
Переменные
Переменные в программировании используются для хранения разнообразных данных. Переменной в общем случае называют область памяти, имеющей имя, которое также часто называют идентификатором.
Определяя для переменной имя мы как бы называем этим же именем и область памяти, куда впоследствии в программе будут записываться значения переменной. С целью улучшения читаемости программы желательно использовать осмысленные названия переменных.
В языке С (Си) к именам переменных предъявляются следующие требования:
- можно использовать строчные и прописные буквы, цифры и символ подчёркивания (в С имеет статус буквы);
- первым символом в имени переменной обязательно должна быть буква;
- не допускается использование пробелов в имени переменной;
- длина имени переменной не ограничена;
- имя переменной не должно совпадать с зарезервированными ключевыми словами языка Си;
- заглавные и строчные буквы в именах переменных различаются, к примеру, переменные a и A – это разные переменные.
Список зарезервированных ключевых слов (которые нельзя использовать в качестве имен переменных), приведен на следующем рисунке.
Чтобы начать пользоваться переменной она обязательно должна быть объявлена. Обычно объявления переменных производятся в начале функций (хороший стиль), но также можно производить их объявление в любом месте тела функции.
При объявлении переменной вы обязательно должны указать ее тип. В зависимости от типа переменной компилятор резервирует ей место в памяти. Наиболее часто используемыми типами данных в языке Си для микроконтроллеров AVR являются char (символьный тип) и int (целочисленный тип).
Принцип работы
В предыдущих пунктах мы оперировали абстрактными понятиями, теперь пришло время перейти к реальным и практическим примерам. Принцип работы любого, даже самого сложного контроллера, сводится к следующему алгоритму:
Он принимает определённые переменные или другие данные, которые прежде должны быть преобразованы в двоичный сигнал. Это необходимо, поскольку на низшем уровне система способна воспринимать лишь 2 состояния – есть сигнал или нет сигнала. Такой принцип называют аналоговым. Существует аналогичный алгоритм, когда сигнал присутствует постоянно, но меняется по частоте – цифровой
У них множество различий, как в областях применения, так и в особенностях работы сигнала, но суть одна – процессор способен воспринимать лишь значения 0 и 1, или true и false, и не важно, какими путями микропроцессоры и микроконтроллеры будут их считывать.
Во внутренней памяти устройства хранится набор специальных инструкций, который позволяет, путем базовых математических преобразований, выполнять какие-то действия с полученными данными. Именно эти базовые операнды и берутся на вооружение компилируемых языков программирования, когда необходимо написать библиотеку готовых функций
Остальные нюансы языков программирования – это уже синтаксис и теория алгоритмов. Но в результате, всё сводится к базовым операндам, которые превращаются в двоичный код и обрабатываются внутренней системой процессора.
Всё, что было получено и сохранено после обработки, выдается на выход. На самом деле, данный пункт выполняется всегда, единственная разница, что выходом может быть и преобразование состояния объекта какой-то системы. Простейшим примером станет замыкание электрической цепи, в случае, если на специальный датчик подать ток, вследствие чего загорится лампочка. Здесь всё зависит от типа устройства, так, 8051 микроконтроллер может выполнять несколько видов выводов, имея 14 пинов, а какой-то другой – всего один, ведь у него 1 пин на выход. Количество выходов влияет на многопоточные свойства девайса, иными словами, возможность выводить информацию сразу на несколько устройств или совершать несколько действий одновременно.
В целом, любой моно или поликристальный блок работает по этому алгоритму, разница лишь в том, что второй – способен параллельно выполнять несколько расчетов, а первый имеет конкретный список действий, который должен выполнить последовательно.
Это напрямую влияет на скорость работы устройств, и именно из-за этой характеристики 2-ух ядерные девайсы мощнее, чем 1-ядерные, но имеющие большую герцовку (способность выполнять большее количество преобразований за единицу времени).
Но почему микроконтроллер овен не способен выполнять некоторые действия, характерные для 8051, и какая классификация вообще существует в данной сфере?
Объявление переменных
Переменные в языке С объявляют в операторе описания. Оператор описания состоит из спецификации типа и списка имён переменных, разделённых запятой. В конце обязательно ставится точка с запятой.
Объявление переменной имеет следующий формат:
спецификатор_типа идентификатор …
Модификаторы — ключевые слова signed, unsigned, short, long.Спецификатор типа — ключевое слово char или int, определяющее тип объявляемой переменной.Идентификатор — имя переменной.
Примеры объявления переменных: char s;int x, y, z;unsigned long long t;
Инициализация значения переменной при объявлении
Язык С в отличие от многих других языков программирования позволяет при объявлении переменной сразу ее проинициализировать, то есть присвоить ей начальное значение, что, конечно же, удобно для экономии кода программы. Выглядит это, к примеру, следующим образом:
int a = 100;
С помощью данной записи мы объявляем переменную a целого типа и сразу же в нее записываем число 100.
При этом желательно для улучшения читабельности программы не смешивать инициализируемые переменные и просто объявляемые в одной строке.
__________________синтаксис цикла while_____________________________
while(condition){ statement1; statement2; statement3;}while – имеет условие выполнения (condition), оно записано в скобках () и тело цикла, оно заключено между фигурными скобками {}. В качестве условия цикла может выступать переменная, константа, выражение или функция, возвращающая значение. Перед каждым выполнением цикла происходит проверка условия, если условие истинно, цикл выполняется, если условие ложно, цикл не выполняется. Любое ненулевое значение в скобках оператор воспримет как истину, и цикл будет выполняться. while(1){ //этот цикл будет выполняться бесконечно statement1; statement2; statement3;}
Создание проекта для Atmega8 в программной среде CodeVision
Необходимо выполнить следующую последовательность действий.
Шаг 1. Создайте новый проект в CodeVision, выбрав пункт меню File -> New -> Project. В появившемся диалогом окне нажмите Yes.
Шаг 2. Откроется CodeWizard. Кликните в ней на первой опции, то есть AT90, затем нажмите OK.
Шаг 3. Выберите свой микроконтроллер, в нашем случае им будет Atmega8.
Шаг 4. Кликните на Ports (порты). В нашем проекте на передающей стороне мы будем подсоединять кнопку на вход и 4 линии будем использовать на выход. То есть мы должны сконфигурировать 4 контакта Atmega8 на выход. Кликните на Port D, сконфигурируйте в нем биты 7, 6, 5 и 4 на выход.
Шаг 5. Выберите Program -> Generate, Save and Exit. Теперь более половины вашей работы по программированию микроконтроллера Atmega8 можно считать выполненной.
Шаг 6. Создайте новую папку на рабочем столе чтобы записывать туда наши файлы.
У нас будет 3 диалоговых окна (будут появляться последовательно одно за другим) для сохранения наших файлов.
Сделайте то же самое (что и на представленном рисунке) с двумя другими диалоговыми окнами – то есть сохраните предлагаемые ими файлы.
После этого рабочая область программы будет выглядеть примерно следующим образом:
Теперь большая часть работы по программированию микроконтроллера Atmega8 нами выполнена с использованием такой удобной программной среды как CodeVision. Теперь нам необходимо только дописать несколько строк кода для передающей и приемной части чтобы закончить проект.
Для приемной стороны повторите рассмотренные шаги, отличие будет состоять только в том, чтобы сконфигурировать контакт B0 PortB на выход потому что мы будем подключать к нему светодиод.
Установка 0 в произвольном бите регистра порта
Если мы хотим сконфигурировать отдельно вывод (контакт) PD2 как вход, то необходимо в соответствующий бит регистра DDRD записать 0. Для этого можно использовать следующую команду.
DDRD &= ~(1<<2);
В этом случае результат сдвига единицы на две позиции влево инвертируется с помощью операции побитного инвертирования, которая в языке С обозначаемой знаком «~».
В результате операции инверсии мы получаем вместо нулей единицы, а вместо единиц — нули. Данная логическая операция также называется операцией НЕ (английское название NOT).
Итак, в результате операции (1<<2) мы получили число 00000100, следовательно после проведения инверсии («~») мы получим число 11111011.
Получившееся число при помощи операции побитного логического умножения & умножается на число, хранящееся в регистре DDRD, и результат затем записывается в регистр DDRD.
Логическое умножение, по другому называемое операцией И (английское название AND), выполняется по следующим правилам:0*0=00*1=01*0=01*1=1
То есть если хотя бы один из операндов операции равен 0, то и результат операции равен 0.
Таким образом, сдвинутая нами влево на две позиции единица (1<<2) превращается при инвертировании («~») в ноль и умножается на соответствующий бит регистра DDRD, поэтому каким бы не было состояние данного бита, то при операции умножения на 0 данный бит становится равным 0. Схематично данный процесс представлен на следующем рисунке.
Общие сведения о портах микроконтроллеров AVR
Порты микроконтроллеров AVR — это устройства ввода/вывода, позволяющие микроконтроллеру передавать или принимать данные. Стандартный порт микроконтроллера AVR содержит восемь разрядов данных, которые могут передаваться или приниматься параллельно. Ножки микроконтроллера также называют пинами, контактами или выводами. Порты обозначаются латинскими буквами А, В, С и т.д. Количество портов зависит от конкретной модели микроконтроллера.
Kонфигурирование каждой линии порта (задание направления передачи данных) может быть произведено программно в любой момент времени. Входные буферы портов построены по схеме триггера Шмитта. Для линий, сконфигурированных как входные, также имеется возможность подключения внутреннего подтягивающего резистора сопротивлением 35…120 кОм между входом и проводом питания. Kроме того, если вывод (вход) с подключенным внутренним подтягивающим резистором подключить к общему проводу, он может служить источником тока.
Обращение к портам производится через регистры ввода/вывода, причем под каждый порт в адресном пространстве ввода/вывода за-резервировано по 3 адреса. По этим адресам размещаются три регистра: регистр данных порта PORTx, регистр направления данных DDRx и регистр выводов порта PINx. Разряды этих регистров имеют названия: Px7…Px0 — для регистров PORTx, DDx7…DDx0 — для регистров DDRx и PINx7…PINx0 — для регистров PINx.
Действительные названия регистров (и их разрядов) получаются подстановкой названия порта вместо символа «x», соответственно для порта A ре¬гистры называются PORTA, DDRA, PINA, для порта B — PORTB, DDRB, PINB и т.д.
Следует заметить, что «регистры» PINx на самом деле регистрами не являются, по этим адресам осуществляется доступ к физическим значениям сигналов на выводах порта. Поэтому они доступны только для чтения, тогда как регистры PORTx и DDRx доступны и для чтения, и для записи.
Таким образом, запись в порт означает запись требуемого состояния для каждого вывода порта в соответствующий регистр данных порта PORTx. А чтение состояния порта выполняется чтением либо регистра данных порта PORTx, либо регистра выводов порта PINx. При чтении регистра выводов порта PINx происходит считывание логических уровней сигналов, присутствующих на выводах порта. А при чтении регистра данных порта PORTx происходит считывание данных, находящихся в регистре-защелке порта – это справедливо как для входных, так и для выходных контактов.
Любой порт микроконтроллера AVR можно сконфигурировать как вход или как выход. Для этой цели используется регистр DDRx. На вход или выход можно сконфигурировать сразу весь порт или только отдельный его вывод (контакт, пин).
Регистр DDRx определяет, является тот или иной вывод порта входом или выходом. Если некоторый разряд регистра DDRx содержит логическую единицу, то соответствующий вывод порта сконфигурирован как выход, в противном случае — как вход. Буква x в данном случае должна обозначать имя порта, с которым вы работаете. Таким образом, для порта A это будет регистр DDRA, для порта B — регистр DDRB и т. д.
Генератор тактовой частоты
Но самым важным для нас в настоящее время является блок «Oscillator Circuits/Clock Generation» (Схема генератора/Генератор тактовой частоты).
В программе часто возникает необходимость сделать временную задержку в ее выполнении — паузу. А точную паузу можно организовать только методом подсчета времени. Время считаем исходя из количества тактов генератора микроконтроллера.
Да и не лишним будет заранее просчитать: успеет ли МК выполнить тот или иной фрагмент программы за отведенное для этого время.
В даташите ищем соответствующую главу: «System Clock and Clock Options» (Тактовый генератор и его параметры). В ней видим раздел «Clock Sources» (Источники тактового сигнала), в котором имеется таблица с перечнем видов тактовых сигналов. В этом разделе указано, что данный МК имеет встроенный тактовый RC-генератор. В разделе «Default Clock Source» имеется указание о том, что МК продается уже настроенным для использования встроенного RC-генератора. При этом тактовая частота МК — 1 МГц.
Из раздела «Calibrated Internal RC Oscillator» (Калиброванный RC-генератор) узнаем, что встроенный RC-генератор имеет температурный дрейф в пределах 7,3 — 8,1 МГц. Может возникнуть вопрос: если частота встроенного тактового генератора 7,3 — 8,1 МГц, то как была получена частота 1 МГц? Дело в том, что тактовый сигнал попадает в схемы микроконтроллера через программируемый делитель частоты (Об это рассказано в разделе «System Clock Prescaler»).
В данном микроконтроллере он имеет несколько коэффициентов деления: 1, 2, 4 и 8. При выборе первого мы получим частоту самого тактового генератора, при включении последнего — в 8 раз меньше, т.е., 8/8=1 МГц. С учетом вышесказанного получаем, что тактовая частота данного МК при включенном делителе с коэффициентом 8 будет в пределах от 7,3/8 = 0,9125 МГц (9125 КГц) до 8,1/8 = 1,0125 МГц.
Обратите внимание на один ну очень важный факт: стабильность частоты дана при температуре МК 25 градусов по шкале Цельсия. Вспомним, что внутренний генератор выполнен по RC схеме
А емкость конденсатора очень зависит от температуры!
_____________________________________________________________________
Мы хотим, чтобы светодиод моргал с частотой видимой нашему глазу. Это единицы, десятки герц. Допустим, мы выбрали 1 Гц. Мой микроконтроллер работает на частоте 8 МГц, длительность одного такта =1/8000000 Гц = 125 нс. Сигнал частотой 1 Гц имеет период повторения 1 c. Светодиод будет гореть только половину периода — 0,5с. Делим 0,5 с на 125 нс и получаем искомое число тактов – 4000000. Это число укладывается в диапазон типа unsigned long int. Следующая строчка нашей программы – вызов функции:__delay_cycles(4000000);Далее – гасим светодиод и снова вызываем функцию задержки:PORTC = 255;__delay_cycles(4000000);5 шаг алгоритма – вернуться на шаг 2. По сути дела нам нужно повторить кусок программы, зациклить его. Для этих целей в Си существуют три типа циклов: for, while и do. Мы используем while.
Пояснение части кода программы
Мы напишем программу для включения/выключения светодиода удаленно, использую связь через радиочастотные модули. В этой части статьи мы рассмотрим лишь ключевые особенности кода программы, текст всей программы будет приведен в конце статьи.
Код для передающей части
Первым делом подключите заголовочный файл delay.h чтобы использовать функции задержки в программе.
Теперь рассмотрим главный цикл в конце тела программы. В этом цикле While мы будем передавать 0x10 байт на PORTD когда кнопка нажата и байт 0x20 когда кнопка не нажата. Можно использовать любые другие значения – но их необходимо будет изменить и на приемном конце.
Код для приемной части
Первым делом здесь необходимо объявить переменные, которые будут использоваться для хранения символов, принимаемых от приемного радиочастотного модуля.
Теперь рассмотрим главный цикл в конце программы. В этом цикле мы будем хранить принимаемые байты в переменной символьного типа (char) и сравнивать их с теми, которые мы передавали на передающей стороне. Если результат сравнения положительный, то мы в соответствии с их значениями будем включать/выключать светодиод, подключенный к PORTB.0.
Инкремент и декремент
В тех случаях, когда необходимо изменить значение переменной на 1, вместо стандартных арифметических операций сложения и вычитания часто применяют такие операции как инкремент или декремент – для них в языке С существует удобная и интуитивно понятная форма записи..
Инкремент – операция увеличения значения переменной на 1.
Пример использования: z++; // значение переменной z будет увеличено на 1
Декремент — операция уменьшения значения переменной на 1.
Пример использования: z- -; // значение переменной z будет уменьшено на 1
Есть две формы записи этих операций: постфиксная (x++) и префиксная (++x). Если эти операции выполняются совместно с операцией присваивания «=», то первой выполняется префиксная запись.
Примеры: m = n++;
Допустим, что значение переменной n было равно 7. Тогда в m будет записано значение 7, после чего значение переменной n будет увеличено на 1. Таким образом, в m будет 7, а в n — 8.
m =- -n;
Если значение n было равно 3, то сначала будет выполнено уменьшение n до 2, а затем это значение будет присвоено переменной m. Таким образом, n и m будет присвоено значение 2.
Три условия для желающих освоить микроконтроллер
1. Желание и настойчивость в достижении поставленной цели
Этот пункт, на мой взгляд, — самый главный. Не будет желания, а еще хуже — настойчивого желания, то и не будет результата. Главное не пасовать и не останавливаться, проявите настойчивость — и все получится (и не только в деле освоения микроконтроллеров).2. Знание устройства микроконтроллера.
Немаловажный фактор. Ведь, согласитесь, не зная как устроен микроконтроллер, что он имеет в своем распоряжении, как это все работает, — мы не сможем использовать все возможности микроконтроллера, выжать из него все, на что он способен.
Возможно и не стоит очень глубоко копаться во «внутренностях» микроконтроллера, но основное, так сказать — азы, мы знать должны (этим мы и будем заниматься на страницах сайта — изучать азы работы с микроконтроллером).3. Знание команд управления микроконтроллерам.
Микроконтроллер, как собака (такое вот интересное сравнение), будет смотреть на нас умными глазами и вилять своим хвостом, пока не подадим ему команду на выполнение каких-то действий.
В отличие от умной собаки, микроконтроллер понимает намного больше команд — более 130 штук.
Так вот, чтобы микроконтроллер не только вилял хвостом, но и выполнял нужную нам работу, — необходимо знать команды управления им.
Сразу хочу сказать, для начала не надо зубрить все 130 команд, достаточно будет знания и половины (и даже меньше). К тому же, многие команды дублируют друг-друга. Но чем больше команд мы будем знать, тем эффективней мы сможем управлять микроконтроллером и тем красивее и элегантнее будут выходить из-под нашего пера программы.
Итого, если у вас есть настойчивое желание освоить микроконтроллер, тогда продолжаем.
Распиновка Atmega8
На следующей странице публикуется расположение выводов данного микроконтроллера при использовании разных типов корпусов:
Советую этот листок из даташита распечатать и иметь под рукой. В процессе разработки и сборки схемы очень полезно иметь эти данные перед глазами.
Внимание!
Обратите внимание на такой факт: микросхема микроконтроллера может иметь (и имеет в данной модели) несколько выводов для подключения источника питания. То есть имеется несколько выводов для подключения «земли» — «общего провода», и несколько выводов для подачи положительного напряжения
Изготовители микроконтроллеров рекомендуют подключать соответствующие выводы вместе, т.е., минус подавать на все выводы, помеченные как Gnd (Ground — Земля), плюс — на все выводы помеченные как Vcc.
При этом через одинаковые выводы МК не должны протекать токи, так как внутри корпуса МК они соединены тонкими проводниками! То есть при подключении нагрузки эти выводы не должны рассматриваться как «перемычки».
Работа схемы
Схема для передающей стороны приведена на следующем рисунке.
В схеме необходимо сделать следующие соединения:
- Pin D7 of atmega8 -> Pin13 HT12E.
- Pin D6 of atmega8 -> Pin12 HT12E.
- Pin D5 of atmega8 -> Pin11 HT12E.
- Pin D4 of atmega8 -> Pin10 HT12E.
- Кнопка to Pin B0 of Atmega.
- Резистор 1 МОм между pin15 и 16 of HT12E.
- Pin17 of HT12E к контакту данных передающего модуля.
- Pin 18 of HT12E to 5V.
- GND pin 1-9 and Pin 14 of HT12E and Pin 8 of Atmega.
Схема для приемной стороны приведена на следующем рисунке.
В схеме необходимо сделать следующие соединения:
- Pin D7 of atmega8 -> Pin13 HT12D.
- Pin D6 of atmega8 -> Pin12 HT12D.
- Pin D5 of atmega8 -> Pin11 HT12D.
- Pin D4 of atmega8 -> Pin10 HT12d.
- LED to Pin B0 of Atmega.
- Pin14 of HT12D к контакту данных приемного модуля.
- Резистор 47 кОм между pin15 и 16 of HT12D.
- GND pin 1-9 of HT12D and Pin 8 of Atmega.
- Светодиод к pin 17 of HT12D.
- 5V to pin 7 of Atmega and pin 18 of HT12D.
Общий вид конструкции приведен на следующем рисунке:
Установка драйвера для USBASP в Windows 10
Если вы используете интерфейс JTAG, вам может потребоваться установка драйвера для USBASP если он не установился автоматически. Если вы не установите этот драйвер, то вы не сможете найти порт USBASP в программе Atmel Studio. Скачать драйвер USBASP можно по этой ссылке — http://www.mediafire.com/file/z576zrku371qyjs/windows-8-and-windows-10-usbasp-drivers-libusb_1.2.4.0-x86-and-x64-bit.zip/file.
После скачивания драйвера выполните следующую последовательность действий:
1. Распакуйте из архива скачанные файлы и поместите их на рабочий стол.
2. Подсоедините модуль USBASP v2.0 к своему компьютеру.
3. Откройте в Windows диспетчер устройств (Device Manager).
4. Теперь вы можете увидеть подсоединенный USBASP в списке устройств.
5. Кликните правой кнопкой мыши по “USBasp” и выберите “Обновить драйвер (Update Driver)”.
6. Select “Произвести поиск драйвера на своем компьютере (Browse my computer for driver software)”.
7. Найдите в открывшемся окне распакованную папку с драйвером для USBASP и щелкните «Открыть».
8. Если установка драйвера прошла успешно, то вы увидите сообщение примерно такое же как на нижеприведенном рисунке – в этом случае вам уже не нужно выполнять дальнейшие инструкции в этом разделе статьи.
9. Если вы увидите сообщение об ошибке как на приведенном рисунке, то вы в этом случае должны отключить цифровую подпись драйвера.
Чтобы сделать выполните следующие шаги:
— нажмите кнопку Shift и удерживая ее нажатой перезагрузите свой компьютер (кликните Restart в меню Windows пока держите ее нажатой);
— когда ваш компьютер перезагрузится не отпускайте кнопку Shift до тех пор пока не увидите “Advanced Options (Расширенные настройки)” на синем экране;
— отпустите кнопку Shift и кликните на “Startup Settings”;
— кликните на “Troubleshoot (Устранение проблем)”;
— выберите “Advanced Options (Расширенные настройки)”;
— после этого вы увидите на экране список расширенных опций и кнопку “Restart” в правом нижнем углу – кликните на ней;
— подождите пока компьютер снова перезагрузится. После этого вы увидите на экране ряд настроек;
— в открывшемся списке настроек выберите пункт “Disable Driver Signature Enforcement (Отключить цифровую подпись драйвера)”. Чтобы ее выбрать просто нажмите кнопку «7» на вашей клавиатуре (не путать с кнопкой «F7»);
— после нажатия этой кнопки компьютер перезагрузится и цифровая подпись драйвера будет отключена;
— после этого снова выполните шаги 1-8 из данного раздела статьи и драйвер для программатора USBASP будет успешно установлен.
Установка WinAVR в Atmel Studio
1. В пункте меню “Tools (Инструменты)” выберите “External Tools (Внешние инструменты)”.
2. У вас откроется окно, где вы должны будете ввести имя вашего инструментального средства.
3. В пункте “Title (название)” введите имя вашего внешнего инструментального средства. Можно выбрать любое имя, но в рассматриваемом примере мы выбрали имя “USBasp”. Поставьте галочку в пункте ”Use Output Window” и снимите галочку с пункта “Prompt for arguments” как показано на нижеприведенном рисунке.
4. Теперь ведите “Command”. Там будет необходимо указать путь к “avrdude.exe” – его вы можете найти в папке где установлена WinAvr. Просто найдите “WinAVR-20100110” на диске “C” вашего компьютера – куда вы устанавливали WinAvr.
5. Введите аргументы. Это самый важный шаг в этой последовательности действий поскольку от них будет во многом зависеть корректность работы приложения. Поскольку в рассматриваемом нами случае мы используем внешние инструментальные средства, то можно ввести следующие аргументы:
6. Больше аргументов можно найти по этой ссылке.
7. Введите аргументы в поле для ввода аргументов. Оставьте поле “Initial directory (Начальный директорий)” без изменений.
8. После заполнения всех полей нажмите “Apply” и затем “Ok”.
В результате этих шагов вы сможете использовать внешние инструментальные средства чтобы загружать программы в микроконтроллер. Проверим это с помощью тестового проекта (программы) “blink.c”. Файл main.c вы можете найти в конце этой статьи. Теперь скопируйте main.c в Atmel studio.
________________________________________________________
Для каждого типа микроконтроллера есть свой заголовочный файл. Для ATMega8535 этот файл называется iom8535.h, для ATMega16 – iom16.h. По идее мы должны в начале каждой программы подключать заголовочный файл того микроконтроллера, который мы используем. Умные люди немного облегчили нам жизнь и написали заголовочный файл ioavr.h. Препроцессор обрабатывает этот файл и в зависимости от настроек проекта включает в нашу программу нужный заголовочный файл. Итак, следущая строчка программы #include <ioavr.h> В нашей программе мы будем использовать задержку. Задержку можно реализовать программно и аппаратно. Сейчас нас интересует программная задержка. IAR содержит библиотеку, в которой уже есть готовая функция задержки. Нам нужно подключить к нашей программе эту библиотеку. Как это сделать? Каждая библиотека имеет свой заголовочный файл в котором описано какие фукции она содержит. Этот файл мы и должны включить в программу. Делается это, как вы догадались с помощью директивы #include.#include <intrinsics.h> Основу любой сишной программы составляют функции, и любая программа на Си имеет хотя бы одну функцию – main().Вообще-то на примере main() не хотелось бы объяснять синтаксис функций, потому что main() хоть и является функцией, но вызывается не как обычно, а автоматически. С этой функции микроконтроллер начинает выполнение написанной нами программы. Вызовы всех других функций, наших или библиотечных, должны быть записаны в коде. Как вызывается функция, мы увидим дальше.У функции есть заголовок – int main(void) и тело – оно ограниченно фигурными скобками {}. В тело функции мы и будем добавлять наш код.
2.1 Архитектура 8-и разрядного AVR
AVR использует Гарвардскую архитектуру с раздельной памятью и шиной для программы и данных. Он имеет регистровый файл из 32 8-и разрядных рабочих регистров общего назначения с временем доступа один тактовый цикл. 32 рабочих регистра – один из ключей к эффективному Си программированию. Эти регистры имеют такие же функции, как и традиционные аккумуляторы, только их 32 штуки. За один такт AVR может передать два произвольных регистра арифметическому логическому устройству, выполнить операцию и записать результат обратно в регистровый файл. Инструкции в памяти программ выполняются на одном конвейерном уровне. Пока одна команда выполняется, следующая извлекается из памяти. Эта концепция позволяет выполнять команды за один такт. Большинство инструкций AVR имеют 16-и разрядный формат. Каждый адрес памяти программ содержит 16 или 32 разрядные инструкции. Для более детальной информации почитайте раздел “AVR CPU Core” в документации на микроконтроллеры.
Обращение
Доступны следующие адресные пространства:
- Регистры общего назначения адресуются по их номерам (0–31), хотя полное 5-битное число не сохраняется в командах, которые могут работать только с подмножеством этих регистров.
- Регистры ввода-вывода имеют выделенное 6-битное адресное пространство, нижняя половина которого является адресуемой по битам; некоторые части имеют регистры ввода-вывода вне этого адресного пространства, которые называются «расширенным вводом-выводом» и доступны только как отображаемый в память ввод-вывод в адресном пространстве данных.
- Адресное пространство данных отображает 32 регистра общего назначения, все регистры ввода-вывода (включая те, которые также доступны через адресное пространство ввода-вывода) и ОЗУ; к нему можно обращаться либо прямо, либо косвенно через регистры указателя X, Y и Z, при необходимости с добавлением RAMPX, RAMPY и RAMPZ соответственно.
- Программная память ( флеш- память ) имеет отдельное адресное пространство, адресованное как 16-битные слова для получения инструкций.
- Для получения постоянных данных память программ адресуется побайтово через регистр указателя Z, при необходимости добавляемый RAMPZ.
- В некоторых устройствах EEPROM отображается в памяти; в других случаях к нему нельзя напрямую обращаться, а вместо этого доступ к нему осуществляется через регистры ввода-вывода адреса, данных и управления.
- Регистры общего назначения, регистр состояния и некоторые регистры ввода-вывода имеют битовую адресацию, причем бит 0 является наименее значимым, а бит 7 — наиболее значимым.
Первые 64 регистра ввода-вывода доступны как через ввод-вывод, так и через адресное пространство данных. Таким образом, у них два разных адреса. Обычно они записываются как от «0x00 (0x20)» до «0x3F (0x5F)», где первый элемент — это адрес ввода-вывода, а второй, в скобках, адрес данных.
Регистры специального назначения ЦП, за исключением ПК, доступны как регистры ввода-вывода. Некоторые регистры (RAMPX, RAMPY) могут отсутствовать на машинах с адресуемой памятью менее 64 Кбайт .
регистр | Адрес ввода / вывода | Адрес данных |
---|---|---|
SREG | 0x3F | 0x5F |
SP | 0x3E: 0x3D | 0x5E: 0x5D |
EIND | 0x3C | 0x5C |
РАМПЗ | 0x3B | 0x5B |
RAMPY | 0x3A | 0x5A |
RAMPX | 0x39 | 0x59 |
RAMPD | 0x38 | 0x58 |
Типичная карта памяти ATmega может выглядеть так:
Адрес данных | Адрес ввода / вывода | |
---|---|---|
0x0000 — 0x001F | Регистры R0 — R31 | |
0x0020 — 0x003F | 0x00 — 0x1F | Регистры ввода / вывода (с битовой адресацией) |
0x0040 — 0x005F | 0x20 — 0x3F | Регистры ввода / вывода (без битовой адресации) |
0x0060 — 0x00FF | Расширенные регистры ввода-вывода (только ввод-вывод с отображением в память) | |
0x0100 — RAMEND | Внутренняя SRAM |
где RAMEND — последний адрес RAM. В частях, в которых отсутствует расширенный ввод-вывод, ОЗУ будет начинаться с 0x0060.