Часть 1
Итак, мы закупились всем необходимым. Настало время развернуть эксперементальную лабораторию!
Ставим софт, который идет в комплекте с программатором: PICKit2 Utility и MPLAB IDE. Первое — утилита для работы с программатором, второе — среда разработки. PICKit2 Utility нам в принципе не понадобится, но есть один момент, который я упомяну позже. А пока перенесем свое внимание на MPLAB IDE.
MPLAB IDE
Открваем среду разработки и создаем новый проект. Один из минусов этой IDE — отсутствие прилипающих панелек, вместо этого мы имеем нагромождение окон. Чтобы можно было жить дальше, я упорядочил все привычным образом (окно уменьшено, чтобы картинка влезла):
upd: все прекрасно прилипает! Кликаем по иконке в левом верхнем углу окна, в меню выбираем Dockable, после чего тащим его к границе. Спасибо lunatik42 за информацию!
File > New; File > Save as..., выбираем тип Assembly, ставим галку Add to project. Таки да, кодить будем на ассемблере.
Также нужно указать IDE, что мы используем ассемблер.
Лезем в Project > Select Language Toolsuite... и выбираем Microchip MPASM Toolsuite:
Теперь идем в Project > Build options… > Project, там у нас настройки компиляции. На вкладке «MPASM/C17/C18 Suite» выбираем генерацию абсолютного кода:
При написании абсолютного кода мы можем сами указывать, по каким адресам располагать наш код и данные. При написании переносимого кода компилятор сам рулит памятью, но для этого придется париться с секциями, нам это пока не надо.
На вкладке MPLAB Assembler можно отключить чувствительность к регистру переменных. Я решил не отключать.
Ну и чтобы жилось легче, слазаем в Edit > Properties... Там ставим отображение номеров строк и меняем шрифт по вкусу. Я поставил Lucida Console 8 кегля, чтобы в окно влезало больше кода.
Снова матчасть
Наша текущая задача — написать минимальный объем кода, который скомпилируется, чтобы попробовать прошить контроллер. В результате мы получим несколько строчек кода, но для их написания придется много читать документацию. Нам понадобятся два источника: даташит и встроенные в IDE мануалы (Help > Topics… > MPLAB Assembler), которые открываются в отдельном окне и не мешают процессу. Там есть таблица с набором команд и описание всех директив; если вы встретите в коде непонятное слово, то за толкованием нужно лезть именно туда.
В разделе «8.0 Instruction Set Summary» даташита приведено подробное описание системы команд, рекомендую вдумчиво прочитать этот раздел.
Минимальный код
Окей, можно наконец немножко покодить — это мы умеем!
Начнем с конца и напишем единственную строчку:
end
Компилируем по F10, получаем успешный билд и ошибку, мол невозможно что-то там загрузить. Еще получаем ворнинг от компилятора, которому не нравятся директивы в начале строки — это не проблема, сдвигаем наш end на один таб. Что же касается ошибки, ее причина в отсутствии конфигурации камня. Конфиг по сути представляет собой 12-битное слово, которое прописывается в камень при прошивке, у камней AVR это называется fuse-битами. Значение каждого бита описано в даташите, раздел «7.1 Configuration Bits».
А теперь квест на внимательность! Что мы забыли сделать? Мы забыли указать, под какой камень нужно собирать наш код. Чтобы сделать это, идем в Configure > Select Device... и выбираем наш камень — PIC12F509. IDE похвастается перед нами кучей возможностей, которые она предоставляет для этого камня:
Но что делать, если мы вдруг захотим использовать другую среду разработки? Для этого мы можем указать тип камня прямо в коде, делается это при помощи директивы list. После прочтения мануалов по этой директиве становится понятно, что нужно написать следующее (не забываем про таб в начале):
list p=12f509
Тип камня, указанный в настройках, передается компилятору через командную строку, и он имеет больший приоритет по отношению к директиве list. Поэтому, если задать в настройках один камень, а в директиве написать другой, то код скомпилируется под камень, указанный в настройках, при этом компилятор выдаст ворнинг «Processor superseded by command line. Verify processor symbol».
Камень мы указали. Теперь вспоминаем, что в разделе даташита «4.3 Data Memory Organization» написано, что регистры нашего камня лежат в адресном пространстве памяти данных. Чтобы обращаться к ним по именам, а не адресам, подключаем заголовочный файл:
#include p12f509.inc
Кроме адресов регистров, там прописаны номера конфигурационных битов — то, что нам сейчас понадобится. Также этот файл можно добавить в проект, чтобы видеть все определенные им константы в списке символов.
Вот теперь мы можем задать конфигурацию. Ее можно указать в Configure > Configuration bits..., но для лучшей переносимости и более удобного доступа лучше сделать это прямо в коде, для чего нам поможет директива __config. Открываем наш инклуд и смотрим секцию «Configuration bits». Биты названы в соответствии с даташитом.
Нам нужна следующая конфигурация: MCLR отключен (работает как обычный пин), защита кода отключена, сторожевой таймер отключен, для тактирования используется внутренний генератор. Таким образом, наш конфиг примет следующий вид:
__config _IntRC_OSC & _CP_OFF & _WDT_OFF & _MCLRE_OFF
Обратите внимание, значения объединяются при помощи «И». Я сначала по привычке написал все через «ИЛИ», и потом долго гадал, почему ничего не работает.
Итак, вот что у нас в итоге получилось:
list p=12f509 #include p12f509.inc __config _IntRC_OSC & _CP_OFF & _WDT_OFF & _MCLRE_OFF end
Компилируем… успешно! Как я и обещал, несколько строчек и много документации.
Беремся за железо
Вот и настал момент, которого вы так долго ждали! Если вы скроллили страницу в поисках того места, где повествование наконец дойдет до железа, то самое время остановиться и начать читать :)
Итак, у нас есть программатор, микроконтроллер, программа и нездоровый энтузиазм все это совместить. И теперь нас мучает только один вопрос: что с чем соединять?
Лезем в даташит, раздел 7.12 «In-Circuit Serial Programming» и видим вот такую картинку:
Normal Connections у нас пока отсутствуют, так что смотрим только на соединение ног программатора с ногами камня. Окей, что с чем соединять мы поняли, теперь нужно найти, откуда эти самые пины растут на камне и на программаторе.
Из мануалов к программатору узнаем назначение его выводов:
В даташите (раздел «Pin Diagrams») видим выводы микроконтроллера:
Теперь смотрим на камень.
Недоумеваем. Ну и на каком углу у него первый вывод? Где верх а где низ? Чтобы понять это, лезем в википедию и читаем про DIP-корпус. Оттуда узнаем, что выводы нумеруются против часовой стрелки от полукруглой засечки:
Оказывается, заботливые парни из Microchip даже поставили для нас точечку около первого вывода.
Достаем, наконец, макетную плату! Я соединил все следующим образом:
То же самое в дополненной реальности, как весьма точно выразился rule:
Прошиваем
Мы всего в нескольких кликах от долгожданного результата! Итак, подключаем наш программатор, если он еще не подключен, затем в MPLAB лезем в меню Programmer и выбираем там наш программатор — PICKit2. В окне вывода откроется вкладка сообщений программатора, где он бодро доложит о своей готовности. А еще у нас появится вот такая панелька для управления программатором:
Нам нужна самая левая кнопка — «Program the target device». Нажимаем!
Если мы все сделали верно, то внизу пробежит прогрессбар, а в окне вывода появятся сообщения о затирании и записи программной памяти. Мои поздравления, камень прошит! :)
В следующей части мы напишем HelloWorld, а так же я расскажу, зачем же нам все-таки может понадобиться PICKit2 Utility. До встречи!
Конец второй части.
Часть 1