AVR на C – просто?
Материалы приведенные далее рассчитаны на пользователей знакомых с программированием в целом и языком C (не обязательно) в частности.
В основном излагаемый материал описывает использование микроконтроллеров AVR, особое внимание на ATmega328. Для изучения материалов понадобится Arduino Uno или Arduino Nano 3.
Да простят меня ардуино-ненавистники, но в данном случае Arduino будет использоваться в качестве макетных плат по доступной цене и с возможность использования без программатора.
1. Подготовка к изучению
Для изучения нам понадобятся:
- Среда разработки;
- Стандартные библиотеки C для микроконтроллеров AVR;
- Программа для загрузки микропрограмм в микроконтроллер;
- Микроконтроллер.
1.1. Среда разработки
При выборе среды разработки можно натолкнутся на «не пробиваемую стену» множества программных оболочек для программирования на разных языках программирования. Но учитывая направление на микроконтроллеры круг поиска сужается до сред разработки адаптированных под конкретный вид микроконтроллеров семейства AVR фирмы Atmel. Кроме того среда разработки язык программирования C.
Из множества вариантов рассмотрим среду разработки СodeBlocks. Будем использовать оригинальную версию СodeBlocks с сайта разработчиков www.codeblocks.org последней версии, на момент написания это версия 16.01. Данная среда разработки интересна наличием версий под популярные операционные системы Linux, Windows и Mac OS.
Вкратце рассмотрим установку под Windows. Скачав файл codeblocks-16.01-setup.exe запускаем его.
Ознакомимся с лицензией и принимаем ее.
Устанавливаем все компоненты без изменений
Путь установки оставляем без изменений.
Пробегают строки установки и появляется предложение запустить программу, соглашаемся. И конечно нажимаем Next в установщике и завершаем установку.
Получаем установленную среду разработки Code::Blocks.
1.2. Стандартные библиотеки C/C++ для микроконтроллеров AVR
Среда разработки установлена, но для работы необходимо подключить библиотеки для компиляции программ для микроконтроллера. Один из способов это поставить WinAVR. Только зачем, если среда разработки уже выбрана. Возьмем все необходимое с сайта производителя микроконтроллеров семейства AVR.
Скачиваем необходимое после простой регистрации по адресу: http://www.atmel.com/tools/ATMELAVRTOOLCHAINFORWINDOWS.aspx
Понадобится Atmel AVR 8-bit Toolchain так как использовать собираемся ATmega328 а он 8-bit. После скачивания запускаем полученный само распаковываемый архив и получаем папку (вида avr8-gnu-toolchain) со всем необходимым. Куда ее положить?
Запускаем ранее установленный Code::Blocks идем в меню Settings >> Compiler переходим во вкладку Toolchain executables выбираем интересующий нас компилятор из списка Selected compiler это будет GNU GCC Compiler for AVR. Далее смотрим путь по умолчанию для размещения ранее скачанной и распакованной папки.
Переименовываем нашу папку как в настройках Code::Blocks и перемещаем по указанному пути.
1.3. Программа для загрузки микропрограмм в микроконтроллер
Теперь все готово для программирования, но не хватает программы для облегчения прошивки микроконтроллера. Для изучения микроконтроллера ATmega328 будем использовать платформу Arduino UNO или Arduino Nano v3. Это дает возможность изучать микроконтроллер без паяльника и программатора.
Для Arduino есть хорошая программа ArduinoBuilder и оболочка из проекта CodeBlocks Arduino IDE (среда разработки Code::Blocks с добавлением библиотек ардуино). Использовать микроконтроллер без ардуино гораздо интересней поэтому скачиваем только ArduinoBuilder. Его будем использовать для экспериментов с микроконтроллером на плате Arduino.
Распаковываем архив, например в корень диска c: в папку ну скажем ArduinoBuilder, из нее делаем ссылку на рабочий стол и получаем два ярлыка:
Все программное обеспечение готово. Приступим к «железным» вопросам
1.4. Микроконтроллер
В своих изысканиях будем рассматривать микроконтроллер ATmega328 программы будем писать именно для него. «Знатоки» сразу нас пошлют к DataSheet но это не для нас. Мы пойдем своим путем и будем изучать его анатомию практически — методом «Тыка» :).
Первое что необходимо, это приобрести минимальное оборудование. Ограничимся для начала покупкой ардуины или аналога. Главное, чтобы на ней был установлен микроконтроллер ATmega328.
Нас интересуют:
Любой из перечисленных вариантов подойдет с теми или иными ограничениями или изменениями.
Рассмотрим подробнее вариант Arduino Nano v3. Здесь установлен микроконтроллер ATmega328P, есть возможность подключать через USB, а также существует несколько клонов по приемлемой цене. Описания в интернете можно найти массу, поэтому рассмотрим только схематичное описание найденное на просторах интернет.
На схеме темно-серым выделены соответствия физическим выводам микроконтроллера, на них и будем опираться при программировании.
Часть 2
Источник: http://cxem.net/mc/mc410.php
AVR. Учебный Курс. Программирование на Си. Часть 1
Я не раз и не два говорил, что изучение МК надо начинать с ассемблера. Этому был посвящен целый курс на сайте (правда он не очень последовательный, но постепенно я его причесываю до адекватного вида) .
Да, это сложно, результат будет не в первый день, но зато ты научишься понимать что происходит у тебя в контроллере. Будешь знать как это работает, а не по обезьяньий копировать чужие исходники и пытаться понять почему оно вдруг перестало работать.
Кроме того, Си намного проще натворить быдлокода, который вылезет вилами в самый неподходящий момент.
К сожалению все хотят результат немедленно. Поэтому я решил пойти с другой стороны — сделать обучалку по Си, но с показом его нижнего белья. Хороший программист-эмбеддер всегда крепко держит свою железку за шкварник, не давая ей ни шагу ступить без разрешения. Так что будет вначале Си код, потом то что родил компилятор и как все это работает на самом деле 🙂
С другой стороны у Си сильная сторона это переносимость кода. Если, конечно, писать все правильно. Разделяя алгоритмы работы и их железные реализации в разные части проекта.
Тогда для переноса алгоритма в другой МК достаточно будет переписать только интерфейсный слой, где прописано все обращение к железу, а весь рабочий код оставить как есть. И, конечно же, читаемость. Сишный исходник проще понять с первого взгляда (хотя..
мне, например, уже пофигу на что фтыкать — хоть си, хоть асм 🙂 ), но, опять же, если правильно все написать. Этим моментам я тоже буду уделять внимание.
В качестве подопытной железки на которой будет ставиться львинная доля всех примеров будет моя отладочная плата PinBoard.
Дальше все будет разжевано буквально по шагам для старта с полного нуля.<\p>
Выбор компилятора и установка среды Для AVR существует множество разных компиляторов Си:
В первую очередь это IAR AVR C — почти однозначно признается лучшим компилятором для AVR, т.к. сам контроллер создавался тесном сотрудничистве Atmel и спецов из IAR. Но за все приходится платить.
И этот компилятор мало того, что является дорогущим коммерческим софтом, так еще обладает такой прорвой настроек, что просто взять и скомпилить в нем это надо постраться.
У меня с ним правда не срослось дружбы, проект загнивал на странных ошибках на этапе линковки (позже выяснил, что это был кривой кряк).
Вторым идет WinAVR GCC — мощный оптимизирующий компилятор. Полный опенсорц, кроссплатформенный, в общем, все радости жизни. Еще он отлично интегрируется в AVR Studio позволяя вести отладку прямо там, что адски удобно. В общем, я выбрал его.
Также есть CodeVision AVR C — очень популярный компилятор. Стал популярен в связи со своей простотой.
Рабочую программу в нем получить можно уже через несколько минут — мастер стартового кода этом сильно способствует, штампуя стандартыне инициализации всяких уартов.
Честно говоря, я как то с подозрением к нему отношусь — как то раз приходилось дизасмить прогу написаную этим компилером, каша какая то а не код получалась.
Жуткое количество ненужных телодвижений и операций, что выливалось в неслабый обьем кода и медленное быстродействие. Впрочем, возможно тут была ошибка в ДНК писавшего исходную прошивку. Плюс он хочет денег. Не так много как IAR, но ощутимо. А в деморежиме дает писать не более чем 2кб кода.
Кряк конечно есть, но если уж воровать, так миллион, в смысле IAR 🙂
Еще есть Image Craft AVR C и MicroC от микроэлектроники. Ни тем ни другим пользоваться не приходилось, но вот SWG очень уж нахваливает MicroPascal, мол жутко удобная среда программирования и библиотеки. Думаю MicroC не хуже будет, но тоже платный.
Как я уже сказал, я выбра WinAVR по трем причинам: халявный, интегрируется в AVR Studio и под него написана просто прорва готового кода на все случаи жизни.
Так что качай себе инсталяху WinAVR с и AVR Studio. Далее вначале ставится студия, потом, сверху, накатывается WinAVR и цепляется к студии в виде плагина. Настоятельно рекомендую ставить WinAVR по короткому пути, что то вроде C:WinAVR тем самым ты избежишь кучи проблем с путями.
Cоздание проекта
Итак, студия поставлена, Си прикручен, пора бы и попробовать что нибудь запрограммировать. Начнем с простого, самого простого. Запускай студию, выбирай там новый проект, в качестве компилятора AVR GCC и вписывай название проекта.
Также не забудь поставить галочу Create Folder, чтобы у тебя все сложилось в одной директории. Ну и укажи место Location, где будет лежать проект. Указывай по короткому пути, что то вроде C:AVR Как показывает практика, чем короче путь тем лучше — меньше проблем при компиляции и линковке проектов.
Проц у меня в Pinboard по дефолту ATmega16, поэтому выбираю его. Те же у кого в PinBoard стоит Mega32 (по спец заказу ставил некторым 🙂 ) выбирают, соответственно ее.
Открывается рабочее поле с пустым *.c файлом.
Теперь не помешает настроить отображение путей в закладках студии. Для этого слазь по адресу:
Меню Tools — Options — General — FileTabs и выбираем в выпадающем списке «Filename Only». Иначе работать будет невозможно — на вкладке будет полный путь файла и на экране будет не более двух трех вкладок.
Настройка проекта
Вообще, классическим считается создание make файла в котором бы были описаны все зависимости. И это, наверное, правильно. Но мне, выросшему на полностью интегрированных IDE вроде uVision или AVR Studio этот подход является глубоко чуждым. Поэтому буду делать по своему, все средствами студии.
Тыкай в кнопку с шестеренкой.
Это настройки твоего проекта, а точнее настройки автоматической генерации make файла. На первой странице надо всего лишь вписать частоту на которой будет работать твой МК.
Это зависит от фьюз битов, так что считаем что частота у нас 8000000Гц.
Также обрати внимание на строку оптимизации. Сейчас там стоит -Os это оптимизация по размеру.
Пока оставь как есть, потом можешь попробовать поиграться с этим параметром. -O0 это отстутсвие оптимизации вообще.
Следующим шагом будет настройка путей. Первым делом добавь туда директорию твоего проекта — будешь туда подкладывать сторонние библиотеки. В списке появится путь «.»
Make файл сгенерирован, его ты можешь поглядеть в папке default в своем проекте, просто пробегись глазами, посмотри что там есть.
На этом пока все. Жми везде ОК и переходи в исходник.
Постановка задачи
Чистый лист так и подмывает воплотить какую нибудь хитрую задумку, так как банальное мигание диодом уже не вставляет. Давай уж сразу брать быка за рога и реализуем связь с компом — это первым делом что я делаю.
Работать будет так:
При приходе по COM порту единички (код 0х31) будем зажигать диодик, а при приходе нуля (код 0х30) гасить. Причем сделано будет все на прерываниях, а фоновой задачей будет мигание другого диода. Простенько и со смыслом.
Собираем схему
Нам надо соединить модуль USB-USART конвертера с выводами USART микроконтроллера. Для этого берем перемычку из двух проводков и накидывам на штырьки крест накрест. То есть Rx контроллера соединяем с Tx конвертера, а Tx конвертера с Rx контроллера.
Кроме того, через USART мы теперь сможем достучаться до загрузчика (Pinboard идет с уже прошитым загрузчиком) и прошить наш контроллер не используя программатор.
Также накинем джамперы, соединяющие LED1 и LED2. Тем самым мы подключим светодиоды LED1 и LED2 к выводам PD4 и PD5 соотверственно.
Получится, в итоге вот такая схема:
Подключение остальных выводов, питания, сброса не рассматриваю, оно стандартное
Сразу оговорюсь, что я не буду углубляться конкретно в описание самого языка Си. Для этого существует просто колоссальное количество материала, начиная от классики «Язык программирования Си» от K&R и заканчивая разными методичками.
Одна такая метода нашлась у меня в загашнике, я когда то именно по ней изучал этот язык. Там все кратко, понятно и по делу. Я ее постепенно верстаю и перестаскиваю на свой сайт.
Посмотреть оглавление.
Там правда еще не все главы перенесены, но, думаю, это ненадолго.
Вряд ли я опишу лучше, поэтому из учебного курса, вместо подробного разьяснения сишных тонкостей, я буду просто давать прямые линки на отдельные страницы этой методички.
Добавляем библиотеки.
Первым делом мы добавляем нужные библиотеки и заголовки с определениями. Ведь Си это универсальный язык и ему надо обьяснить что мы работаем именно с AVR, так что вписывай в исходник строку:
#include<\p>
Этот файл находится в папке WinAVR и в нем содержится описание всех регистров и портов контроллера.
Причем там все хитро, с привязкой к конкретному контроллеру, который передается компилятором через make файл в параметре MCU и на основании этой переменной в твой проект подключается заголовочный файл с описанием адресов всех портов и регистров именно на этот контроллер.
Во как! Без него тоже можно, но тогда ты не сможешь использовать символические имена регистров вроде SREG или UDR и придется помнить адрес каждого вроде «0xC1», а это голову сломать.
Сама же команда #include позволяет добавить в твой проект содержимое любого текстового файла, например, файл с описанием функций или кусок другого кода. А чтобы директива могла этот файл найти мы и указывали пути к нашему проекту (директория WinAVR там уже по дефолту прописана).
Главная функция.
Программа на языке Си вся состоит из функций. Они могут быть вложенными и вызываться друг из друга в любом порядке и разными способами. Каждая функция имеет три обязательных параметра:
- Возвращаемое значение, например, sin(x) возвращает значение синуса икс. Как в математике, короче.
- Передаваемые параметры, тот самый икс.
- Тело функции.
Все значения передаваемые и возвращаемые обязаны быть какого либо типа, в зависимости от данных.
Любая программа на Си должна содержать функцию main как точку входа в главную прогрмму, иначе это нифига не Си :). По наличию main в чужом исходнике из миллиона файлов можно понять, что это и есть головная часть программы откуда начинается все. Вот и зададим:
1 2 3 4 5 |
int main(void) { return 0; } |
int main(void) { return 0; }
Все, первая простейшая программа написана, не беда что она ничего не делает, мы же только начали.
Разберем что же мы сделали.
int это тип данных которая функция main возвращает. Узнать подробней о типах данных
Конечно, в микроконтроллере main ничего вернуть в принципе не может и по идее должна быть void main(void), но GCC изначально заточен на PC и там программа может вернуть значение операционной системе по завершении. Поэтому GCC на void main(void) ругается Warning’ом.
Это не ошибка, работать будет, но я не люблю варнинги.
void это тип данных которые мы передаем в функцию, в данном случае main также не может ничего принять извне, поэтом void — пустышка. Заглушка, применяется тогда когда не надо ничего передавать или возвращать.
Вот такие вот { } фигурные скобочки это программный блок, в данном случае тело функции main, там будет распологаться код.
return — это возвращаемое значение, которое функция main отдаст при завершении, поскольку у нас int, то есть число то вернуть мы должны число. Хотя это все равно не имеет смысла, т.к. на микроконтроллере из main нам выходить разве что в никуда. Я возвращаю нуль. Ибо нефиг. А компилятор обычно умный и на этот случай код не генерит.
Хотя, если извратиться, то из main на МК выйти можно — например вывалиться в секцию бутлоадера и исполнить ее, но тут уже потребуется низкоуровневое ковыряние прошивки, чтобы подправить адреса перехода. Ниже ты сам увидишь и поймешь как это сделать. Зачем? Вот это уже другой вопрос, в 99.
999% случаев это нафиг не надо 🙂
Сделали, поехали дальше. Добавим переменную, она нам не особо нужна и без нужны вводить переменные не стоит, но мы же учимся.
Если переменные добавляются внутри тела функции — то они локальные и существуют только в этой функции. Когда из функции выходишь эти переменные удаляются, а память ОЗУ отдается под более важные нужды.
Подробней о локальных и глобальных переменных, а также времени жизни оных.
1 2 3 4 5 6 |
int main(void) { unsigned char i; return 0; } |
int main(void) { unsigned char i; return 0; }
unsigned значит беззнаковый. Дело в том, что в двоичном представлении у нас старший бит отводится под знак, а значит в один байт (char) влазит число +127/-128, но если знак отбросить то влезет уже от 0 до 255. Обычно знак не нужен. Так что unsigned.
i — это всего лишь имя переменной. Не более того.
Теперь надо проинициализировать порты и UART. Конечно, можно взять и подключить библиотеку и вызвать какой нибудь UartInit(9600); но тогда ты не узнаешь что же произошло на самом деле.
Делаем так:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
int main(void) { unsigned char i; #define XTAL 8000000L #define baudrate 9600L #define bauddivider (XTAL/(16*baudrate)-1) #define HI(x) ((x)>>8) #define LO(x) ((x)& 0xFF) UBRRL = LO(bauddivider); UBRRH = HI(bauddivider); UCSRA = 0; UCSRB = 1 |
Источник: http://easyelectronics.ru/avr-uchebnyj-kurs-programmirovanie-na-si-chast-1.html
Программирование микроконтроллеров AVR на языке C / C++ (Си) в Atmel Studio
Программирование на Си для микроконтроллеров немного отличается от обычного программирования тем, что приходится работать с битами и оперировать ими, я тут я приведу примеры часто используемых приемов программирования на языке C++ в Atmel Studio.
Представление чисел:
Например десятичное число 15 можно представить так:
0b00001111 – двоичное
017 – восьмеричное
0x0f – шестнадцатеричное
Математические оператры:
Сложение: +
Вычитание: –
Деление: /
Умножение: *
Остаток: %
Логические операции:
Логическое “И” (AND) | && | Пример: && – возвращает истина(единица) в том случае, когда истинны оба условия 1 и 2, в противном случае возвращает ложь(ноль) |
Логическое “ИЛИ” (OR) | || | Пример: || – возвращает ложь(ноль) в том случае, когда ложны оба условия 1 и 2, в противном случае возвращает истина(единица) |
Логическое “НЕТ” (NOT) | ! | Пример: int k=5; if (!k) {…} Оператор NOT инвертирует условие наоборот, вместо истины(единица) возвратит ложь(ноль) и наоборот. В примере есть переменная которой присвоено число 5, условие if будет выполнятся если переменная k будет равна чему угодно, но только не 5 |
Побитовые операции:
Отрицание | – |
Побитовое “И” (AND) | & |
Побитовое “ИЛИ” (OR) | | |
Побитовое “XOR” | ^ |
Сдвиг битов вправо(эквивалентно делению на 2) | >> |
Сдвиг битов влево(эквивалентно умножению на 2) | 1, не затрагивая другие битыПример: PORTB = 0b00000010, необходимо на 2 контакт PORTB установить низкий уровень, а потом высокий и т.д.:PORTB ^= 0b00000010; //Результат: PORTB = 0b00000000, т.к. PORTB был равен 0b00000010PORTB ^= 0b00000010; //Результат: PORTB = 0b00000010, т.к. PORTB был равен 0b00000000PORTB ^= 0b00000010; //Результат: PORTB = 0b00000000, т.к. PORTB был равен 0b00000010PORTB ^= 0b00000010; //Результат: PORTB = 0b00000010, т.к. PORTB был равен 0b00000000и т.д., т.е. при каждом выполнении этой команды “PORTB ^= 0b00000010”, изменяется только второй бит на противоположное значение, так можно сделать например мигание светодиодом.Другие манипуляции с битами, каждое выражение не зависит от предыдущего, просто как примеры и результат этого выраженияPORTB = 0; //Результат: PORTB = 0b00000000, обнуляемPORTB = 255; //Результат: PORTB = 0b11111111, установим все биты в единицуPORTB = 0xff; //Результат: PORTB = 0b11111111, установим все биты в единицуPORTB = 1; //Результат: PORTB = 0b00000001, просто присваиваем единицуPORTB = 128; //Результат: PORTB = 0b10000000, просто присваиваем 128 в десятичной, а в двоичной будет такой результатPORTB = 17; //Результат: PORTB = 0b00000001, сдвигаем десятичное число 128 на 7 позиций вправоИсточник: https://www.iprg.ruОбсудить на форумеС точки зрения программирования, ПЛК Wecon серии LX3V является клоном ПЛК Mitsubishi Melsec FX2N. Поэтому программировать LX3V можно как в родной среде программирования Wecon PLC Editor, так и в среде GX Works2 для Перед использованием контроллер необходимо запрограммировать, т.е. создать пользовательскую программу. После создания пользовательская программа может быть сохранена в энергонезависимой Flash-памяти контроллера и запускаться на выполнение H – безгалогеновый ПВХ изоляция жилы/внешняя оболочка SL – кабель контрольный Li – многожильный проводник по VDE Уходящая в прошлое линейка контроллеров Step5, продолжает все-таки кое где встречаться. Приведенные здесь материалы от автора ставшим классиком в написании мануалов по Сименсу – Ганса Бергера, помогут, при необходимости, разобраться с этим вопросом. Работа с даными блоками управления осуществляется вкладкой MIKAS 11/M73A или J72+/M73I. MIKAS 11/M73A – только блоки управления M73 производства АВТЕЛ с ПО А308ХХХХ, А317ХХХХ, А373ХХХХ(далее ЭБУ M73A). Для загрузки программ в программируемое реле Lovato LRD20RD024 используется кабель программирования LRXC00 для COM-порта: |
Источник: https://ingeneryi.info/radio-kom/rd-kom/ms-kom/779-programmirovanie-mikrokontrollerov-avr-na-yazyke-c-c-si-v-atmel-studio.html
Доступ к портам I/O AVR на языке C (GCC, WinAVR) | avr | programming
Adblockdetector