На этом уроке мы начнём осваивать работу с микроконтроллером ATmega8.
Первым делом подадим питание на МК, подключим его к программатору, Добьемся, чтобы программатор «увидел» МК. Разберёмся с фьюзами. Установим среду программирования. Напишем первую программу, скомпилируем и прошьём МК. В окончании убедимся в работоспособности МК.
Заглянем в даташит, раздел 25.8 Serial Downloading. Будем подключать МК к программатору согласно этому рисунку…
Назначения выводов Вашего программатора вы можете узнать из документации к нему. В моём случае распиновка USBASP следующая:
Подпаиваем провода к панельке для проверки. Получается как-то так…
Теперь необходимо установить драйвера к программатору USBasp Driver 0.1.12.1.
Программа SinaProg 2.1 установки не требует.
Ну а теперь эти страшные фьюзы… устанавливаем как на screenshoot-ах…
Программирование битов защиты: нам нечего скрывать, всё разблокировано – No lock…
- BOOTSZ0..1 – задает размер сектора загрузчика
- RSTDISBL – отключает вывод reset, делая его обычной ножкой ввода-вывода
- WDTON – включает Watch Dog Timer
- SPIEN – разрешает последовательное програм- мирование
- EESAVE – защита EEPROM от стирания
- BOOTRST – заставляет микроконтроллер запускаться с области бутлоадера
- CKOPT – задает размах тактового сигнала, т.е. амплитуду колебаний на выходе с кварца. Когда CKOPT = 1 то размах минимальный, за счет этого достигается пониженное энергопотребление, но снижается устойчивость к помехам. Если CKOPT = 0, то размах сигнала увеличится. Это повышает энергопотребление и помехоустойчивость.
ВНИМАНИЕ! Не вЫключайте бит SPIEN. Выключение этого бита, запретит последовательный режим программирования, и микроконтроллер не будет отвечать.
ВНИМАНИЕ! Не вКлючайте бит RSTDISBL. В последовательном режиме программирования необходим вывод RESET. Включение этого бита, выключит вывод RESET, и микроконтроллер не будет отвечать.
- BODLEVEL и BODEN – определяет момент срабатывания детектора уровня питающего напряжения, при снижении напряжения питания ниже установленного уровня, произойдет «перезагрузка» контроллера
- CKSEL – выбор источника тактового сигнала для микроконтроллера
Программу для нашего МК мы будем писать в Atmel Studio 6.2.
Какая среда лучше? CodeVisionAVR, WinAVR, Bascom-AVR? В какой писать удобнее, а в какой понятнее вопрос субъективный.
Я решил для себя, что писать лучше в среде разработки предоставленной ATMEL. На том и порешили…
Первая программа. Что ж, запускаем Atmel Studio. Создаём новый проект File->New->Project…
Выбираем тип процессора, жмём далее. В результате мастер создания проектов, выдаёт шаблон кода, который мы приведем к благообразному виду…
/*
* test.c
*
* Created: 16.02.2015 0:41:52
* Author: Сергей Владимирович
*/
#include < avr/io.h > //Файл определения имён регистров, портов, констант…
Int main(void) //Основной цикл
{
while(1) //Бесконечный цикл
{
//TODO:: Please write your application code
}
}
Для обмена данными с внешним миром в МК предусмотрены порты ввода-вывода. Именуются они PORTA, PORTB, PORTC… и так далее. У каждого порта может быть несколько линий, выводов, обычно их 8-мь. В нашем случае, из раздела Pin Configurations, мы узнаём, что наш МК имеет три порта:
- PORTB имеет 8-ь выводов с названиями PB0 — PB7;
- PORTC имеет 7-ь выводов с названиями PC0- PC6;
- PORTD имеет 8-ь выводов с названиями PD0 — PD7.
Каждому порту можно задать направление передачи данных:
- порт настроен на ввод, МК получает данные из вне;
- порт настроен на вывод, МК выводит обработанные данные во внешнюю среду, включает, управляет и т.п.
В процессе работы вывод порта может принимать два состояния:
- «высокое» — логическая единица – напряжение +5В;
- «низкое» — логический ноль, напряжение 0В.
Для проверки работоспособности МК напишем программу, которая будет изменять состояние линии порта каждые две секунды.
Во первых подключаем внешнюю библиотеку для работы с функциями задержки…
#include < util/delay.h > //Функции ожидания
Далее, для корректного функционирования нам необходимо указать программе, с какой частотой работает тактовый генератор…
#define F_CPU 8000000UL //Указываем тактовую частоту процессора
Выбираем порт, например PORTC. Порт содержит семь линий, используем линию PC5 которая соединена с 28-ым выводом микросхемы.
Первым делом настроим эту линию на вывод. Для настройки направления данных используется регистр DDRx, где х – это имя порта. В нашем случае регистр будет называться DDRC.
Каждой линии порта PORTC соответствует бит регистра DDRC. Этот бит определяет направление линии ввода-вывода. Если бит регистра DDRC равен 1, то линия PC5 настроена на выход, если равен 0, то на вход.
DDRC |= (1<<5); //Настраиваем линию PC5 на выход
Как же понять эту строчку??
Выражение 1<<5 осуществляет сдвиг единички влево на 5 бит, то есть справа добавляются четыре нулевых бита и получается 10000, а знак «|», стоящий перед знаком присваивания «=», осуществляет операцию побитного логического сложения.
При логическом сложении 0+0=0, 0+1=1, 1+1=1. Операцию логического сложения по-другому называют операцией ИЛИ (английское название OR).
Таким образом, к битам, хранящимся в регистре DDRС = 0b00000000, прибавляется двоичное 10000, представленное как 0b00010000, и результат сложения 0b00010000 записывается в регистр DDRС.
Собираем всё вместе…
#define F_CPU 8000000UL
#include < avr/io.h > //Файл определения имён регистров, портов, констант…
#include < util/delay.h > //Функции ожидания
int main(void) //Основной цикл
{
DDRC |= (1 << 5); //Настраиваем линию порта PC5 на вывод!
while(1) //Бесконечный цикл
{
PORTC |= (1 << PC5); //Устанавливаем линию порта в высокое состояние
_delay_ms(2000); //Ждём 2-е секунды
PORTC &= ~(1 << PC5); //Устанавливаем линию порта в низкое состояние
_delay_ms(2000); //Ждём 2-е секунды
}
}
Как записать единицу в регистр Вы уже знаете, а как быть с нулем?
Чтобы установить вывод порта PС5 в низкое состояние, нам необходимо в бит PC5 порта PORTC записать ноль. Для этого применяют следующую конструкцию:
PORTC &= ~(1<< PC5); // Устанавливаем линию порта в низкое состояние
Выражение 1<< PC5 осуществляет сдвиг единички влево на 5 бит, то есть справа добавляются четыре нулевых бита и получается 10000, далее инвертируется с помощью операции побитного инвертирования, обозначаемой значком «~». После инверсии мы получаем вместо нулей единички, а вместо единичек – нули. Эта логическая операция иначе называется операцией НЕ (английское название NOT).
Таким образом, при побитном инвертировании 0b00010000 мы получаем 0b11101111.
Получившееся число с помощью операции побитного логического умножения & умножается на число, хранящееся в регистре порта PORTC, и результат записывается в регистр порта PORTC.
При логическом умножении 0*0=0, 0*1=0, 1*1=1. Операцию логического умножения иначе называют операцией И (английское название AND).
То есть сдвинутая нами влево на пять позиций единичка превращается при инвертировании в ноль и умножается на соответствующий бит, хранящийся в регистре порта PORTC. При умножении на ноль мы получаем ноль. Таким образом, бит PC5 становится равным нулю.
Остаётся скомпилировать проект Build->Build Solution (F7) и прошить контроллер файлом с расширением .hex, который лежит по адресу диск:<имя проекта>Debug.
Работоспособность программы проверяется вольтметром, подключённым к линии PC5 порта PORTC. Наблюдают изменение потенциала линии PC5 раз в две секунды.
Ну, вот и всё! Поздравляю Вас с написанием первой программы!!!
PS: Для лучшего усвоения материала советую Вам выбрать порт и его линию самостоятельно!
См. также видеокурс по AVR-микроконтроллерам для начинающих
Кто хочет идти «в ногу» с автором курса — создавайте свои дневники на форуме и выкладывайте что у вас получается и какие вопросы возникают при этом.