2. Первая программа или порты ввода-вывода.
2.1. Порты и выводы.
Чтобы общаться с внешним миром у микроконтроллера есть порты ввода-вывода, в каждом из которых есть несколько отдельных битов (считай выводов), на которых можно установить ноль (0) или единицу (1).
У ATmega328 таких портов 3 это порты B,C и D. На каждом порту по 8 битов(за исключением порта C он 7 - разрядный) которыми можно (нужно) управлять. Но управлять с некоторыми ограничениями.
Ограничения:
-
D0 и D1 используются для прошивки микроконтроллерах на плате Arduino через USB;
-
C6 – используется для перезагрузки (reset);
-
B6 и B7 - на этих выводах микроконтроллера подключается внешний кварцевый резонатор.
Остальные биты можно использовать если они не задействованы. Для наших изысканий будем использовать:
-
порт B – B0, B1, B2, B3, B4, B5 (соответственно выводы микроконтроллера с 14 по 19);
-
порт C – С0, С1, С2, С3, С4, С5 (выводы — с 23 по 28);
-
порт D – D2, D3, D4, D5, D6, D7 (выводы — 4, 5, 6, 11, 12, 13).
Необходимо учитывать что ATmega328 производится в разных корпусах и нумерация выводов может отличатся
2.2. Регистры управления портами.
Управление портами достаточно простое. Используется три восьми битных регистра -
DDRx, PORTx и PINx, где x имя порта (в нашем случае B,C и D).
-
DDRx – Настройка разрядов порта x на вход или выход.
-
PORTx – Управление состоянием выходов порта x (если соответствующий разряд настроен как выход), или подключением внутреннего подтягивающего резистора (резистор подтягивает разряд к 1 если соответствующий разряд настроен как вход).
-
PINx –Чтение логических уровней разрядов порта x.
Настройка и работа портов сводится к трем операциям в зависимости от настройки входа или выхода.
Ввод:
-
В регистре DDRx на нужный разряд устанавливаем 0 обозначая его как ввод;
-
При необходимости на указанном разряде устанавливаем 1 для подключения подтягивающего резистора (резистор подтягивает указанный вывод к 1), подтягивающий резистор включают для уменьшения внешних помех и его можно не подключать;
-
Считываем из регистра PINx с того-же разряда состояние 0 или 1.
Вывод:
-
В регистре DDRx на нужный разряд устанавливаем 1 обозначая его как вывод;
-
В регистр PORTx на этот разряд устанавливаем его состояние 0 или 1;
-
В регистре PINx можно считать текущее состояние каждого разряда порта.
Пример: На выводе 5 порта B установить 1 (вывод 17 микроконтроллера переключить на логическую 1)
регистр DDRB
DDRB7 |
DDRB6 |
DDRB5 |
DDRB4 |
DDRB3 |
DDRB2 |
DDRB1 |
DDRB0 |
0 |
0 |
1 |
0 |
0 |
0 |
0 |
0 |
Установили разряд DDRB5 в 1 настроив вывод как вывод
регистр PORTB
PORTB7 |
PORTB6 |
PORTB5 |
PORTB4 |
PORTB3 |
PORTB2 |
PORTB1 |
PORTB0 |
0 |
0 |
1 |
0 |
0 |
0 |
0 |
0 |
Установили разряд PORTB5 переключив вывод микроконтроллера в 1. Дальнейшее переключение этого вывода производится без изменения регистра DDRx если не понадобится переключить разряд порта на ввод.
Регистр PINB можно не использовать, если только для проверки состояния выводов порта.
Рекомендация: биты регистров желательно переключать по отдельности, чтобы не вносить путаницу в программу микроконтроллера, если нет необходимости использовать все выводы порта как ввод или вывод.
2.3. Программа
Разберем программу на C по строкам.
#include <avr/io.h> // Подключение библиотеки // ввода/вывода AVR #include <util/delay.h> // Подключение библиотеки создания задержек #define V_V 5 // Указываем макроопределение регистра 5 порта B int main() { DDRB |= 1 << V_V; // Устанавливаем 5 бит регистра DDRB в // (назначаем как вывод) while(1) { // Безконечный цикл основной программы PORTB |= 1 << V_V; // Устанавливаем вывод микроконтроллера в 1 _delay_ms(100); // Ждем 100 мс PORTB &= ~(1 << V_V); // Устанавливаем вывод микроконтроллера в 0 _delay_ms(100); // Ждем 100 мс } return 0; }
В программе вставлен бесконечный цикл while(1), чтобы микроконтроллер не выполнил ничего лишнего. Все действия с портами в программе выполнены с использованием поразрядных операций в языке C. Что дало возможность управлять только одним разрядом (одним выводом микроконтроллера) порта B.
На использованном нами выводе микроконтроллера ATmega328 в Arduino UNO и Arduino Nano v3 подключен светодиод, поэтому в первой программе не придется даже собирать схему, достаточно подключить Arduino к компьютеру.
2.4. Проект на C и компиляция
Программное обеспечение готово, программа написана, микроконтроллер тоже есть в виде Arduino. Начнем.
Запускаем CodeBlocks, в меню File >> New >> Project начинаем создавать проект.
Выбираем AVR Project и Go.
Next
В поле Project title указываем название проекта, ниже в Folder to create project in указываем путь к папке куда создаем проект и жмем Next.
В следующем окне оставляем галку только Create “Release” configuration и опять Next.
Выбираем наш микроконтроллер (у меня atmega328p) устанавливаем частоту (для Arduino Nano v3 - 16МГц) и оставляем создание только hex файла и Finish.
И наконец в созданном проекте находим файл main.c и открываем его. Внутри видим:
/* */ #include <avr/io.h> int main(void) { // Insert code while(1); return 0; }
Заменяем эту заготовку нашей программой и жмем
Происходит компиляция проекта и внизу видим
2.5. Прошиваем микроконтроллер
Все прошивка готова, она находится в папке проекта (выбранной при создании проекта). У меня C:\avr\Program1\bin\Release\Program1.hex этот файл и является нашей прошивкой.
Начнем прошивать. Запустим программу ArduinoBuilder
В окне выбираем файл hex (находится в папке проекта CodeBlocks >> bin/Release/project1.hex) нашего проекта, выбираем Arduino и частоту микроконтроллера и жмем кнопку чем программировать (у меня COM9) обычно это com порт отличный от 1. После сего проделанного смотрим мигающий диод.
На этом задача минимум выполнена. Рассмотрен подборка программного обеспечения, изучены порты ввода/вывода и регистры их управления, написана программа на C скомпилирована и прошита в микроконтроллер. И все это можно применить для микроконтроллеров AVR за исключением программы ArduinoBuilder которая в основном создана под Arduino, но и ее можно заменить при использовании например программатора USBASP и программы AVRDUDE_PROG, основная часть материала полностью применима.
Список радиоэлементов
Обозначение | Тип | Номинал | Количество | Примечание | Магазин | Мой блокнот |
---|---|---|---|---|---|---|
Плата Arduino | Arduino Nano 3.0 | 1 | Поиск в магазине Отрон | |||
Плата Arduino | Arduino Uno | 1 | Поиск в магазине Отрон | |||
Скачать список элементов (PDF)
Прикрепленные файлы:
- project1.zip (6 Кб)
Комментарии (14) | Я собрал (0) | Подписаться
Для добавления Вашей сборки необходима регистрация
Что такое макроопределение, и зачем оно нужно?
2."DDRB[b] |= 1
[Автор]
2.
[Автор]
К тому же, если макроопределение встречается в тексте много раз, то изменив его значение один раз в начале, Вы измените разом весь код. И не придётся разыскивать и править по всему коду.
И макроопределение — это не переменная, которая занимает место в памяти. Его значения поставляются на этапе компиляции.
[Автор]
[Автор]
[Автор]
[Автор]
Есть версия codeblocks для ардуино. Но поддержка ее закончилась в 14 году. Есть что то свежее?
[Автор]