AVR. Учебный Курс. Программирование на Си. Часть 1

Я не раз и не два говорил, что изучение МК надо начинать с ассемблера. Этому был посвящен целый курс на сайте (правда он не очень последовательный, но постепенно я его причесываю до адекватного вида) . Да, это сложно, результат будет не в первый день, но зато ты научишься понимать что происходит у тебя в контроллере. Будешь знать как это работает, а не по обезьяньий копировать чужие исходники и пытаться понять почему оно вдруг перестало работать. Кроме того, Си намного проще натворить быдлокода, который вылезет вилами в самый неподходящий момент.

К сожалению все хотят результат немедленно. Поэтому я решил пойти с другой стороны — сделать обучалку по Си, но с показом его нижнего белья. Хороший программист-эмбеддер всегда крепко держит свою железку за шкварник, не давая ей ни шагу ступить без разрешения. Так что будет вначале Си код, потом то что родил компилятор и как все это работает на самом деле :)

С другой стороны у Си сильная сторона это переносимость кода. Если, конечно, писать все правильно. Разделяя алгоритмы работы и их железные реализации в разные части проекта. Тогда для переноса алгоритма в другой МК достаточно будет переписать только интерфейсный слой, где прописано все обращение к железу, а весь рабочий код оставить как есть. И, конечно же, читаемость. Сишный исходник проще понять с первого взгляда (хотя.. мне, например, уже пофигу на что фтыкать — хоть си, хоть асм :) ), но, опять же, если правильно все написать. Этим моментам я тоже буду уделять внимание.

В качестве подопытной железки на которой будет ставиться львинная доля всех примеров будет моя отладочная плата PinBoard.

Дальше все будет разжевано буквально по шагам для старта с полного нуля.

Первая программа на Си для AVR

Выбор компилятора и установка среды
Для 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, так что вписывай в исходник строку:

1
#include <avr/io.h>

Этот файл находится в папке WinAVR и в нем содержится описание всех регистров и портов контроллера. Причем там все хитро, с привязкой к конкретному контроллеру, который передается компилятором через make файл в параметре MCU и на основании этой переменной в твой проект подключается заголовочный файл с описанием адресов всех портов и регистров именно на этот контроллер. Во как! Без него тоже можно, но тогда ты не сможешь использовать символические имена регистров вроде SREG или UDR и придется помнить адрес каждого вроде «0xC1», а это голову сломать.

Сама же команда #include <имя файла> позволяет добавить в твой проект содержимое любого текстового файла, например, файл с описанием функций или кусок другого кода. А чтобы директива могла этот файл найти мы и указывали пути к нашему проекту (директория WinAVR там уже по дефолту прописана).

Главная функция.
Программа на языке Си вся состоит из функций. Они могут быть вложенными и вызываться друг из друга в любом порядке и разными способами. Каждая функция имеет три обязательных параметра:

  • Возвращаемое значение, например, sin(x) возвращает значение синуса икс. Как в мате