Pull to refresh

Дайте мне железа! Часть 2

Programming microcontrollers *
Дайте мне железа!

Часть 1

Итак, мы закупились всем необходимым. Настало время развернуть эксперементальную лабораторию!

Ставим софт, который идет в комплекте с программатором: PICKit2 Utility и MPLAB IDE. Первое — утилита для работы с программатором, второе — среда разработки. PICKit2 Utility нам в принципе не понадобится, но есть один момент, который я упомяну позже. А пока перенесем свое внимание на MPLAB IDE.

MPLAB IDE


Открваем среду разработки и создаем новый проект. Один из минусов этой IDE — отсутствие прилипающих панелек, вместо этого мы имеем нагромождение окон. Чтобы можно было жить дальше, я упорядочил все привычным образом (окно уменьшено, чтобы картинка влезла):

MPLAB IDE

upd: все прекрасно прилипает! Кликаем по иконке в левом верхнем углу окна, в меню выбираем Dockable, после чего тащим его к границе. Спасибо lunatik42 за информацию!

File > New; File &gt Save as..., выбираем тип Assembly, ставим галку Add to project. Таки да, кодить будем на ассемблере.

Также нужно указать IDE, что мы используем ассемблер.

Лезем в Project > Select Language Toolsuite... и выбираем Microchip MPASM Toolsuite:

Microchip MPASM Toolsuite

Теперь идем в Project > Build options… > Project, там у нас настройки компиляции. На вкладке «MPASM/C17/C18 Suite» выбираем генерацию абсолютного кода:

Absolute code

При написании абсолютного кода мы можем сами указывать, по каким адресам располагать наш код и данные. При написании переносимого кода компилятор сам рулит памятью, но для этого придется париться с секциями, нам это пока не надо.

На вкладке 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 у нас пока отсутствуют, так что смотрим только на соединение ног программатора с ногами камня. Окей, что с чем соединять мы поняли, теперь нужно найти, откуда эти самые пины растут на камне и на программаторе.

Из мануалов к программатору узнаем назначение его выводов:

Выводы PICKit2

В даташите (раздел «Pin Diagrams») видим выводы микроконтроллера:

Выводы PIC12F509

Теперь смотрим на камень.

PIC12F509

Недоумеваем. Ну и на каком углу у него первый вывод? Где верх а где низ? Чтобы понять это, лезем в википедию и читаем про DIP-корпус. Оттуда узнаем, что выводы нумеруются против часовой стрелки от полукруглой засечки:

Нумерация выводов DIP-микросхем

Оказывается, заботливые парни из Microchip даже поставили для нас точечку около первого вывода.

Достаем, наконец, макетную плату! Я соединил все следующим образом:

Схема соединения камня с программатором

То же самое в дополненной реальности, как весьма точно выразился rule:

Схема с пояснениями

Прошиваем


Мы всего в нескольких кликах от долгожданного результата! Итак, подключаем наш программатор, если он еще не подключен, затем в MPLAB лезем в меню Programmer и выбираем там наш программатор — PICKit2. В окне вывода откроется вкладка сообщений программатора, где он бодро доложит о своей готовности. А еще у нас появится вот такая панелька для управления программатором:

Панель управления PICKit2

Нам нужна самая левая кнопка — «Program the target device». Нажимаем!

Если мы все сделали верно, то внизу пробежит прогрессбар, а в окне вывода появятся сообщения о затирании и записи программной памяти. Мои поздравления, камень прошит! :)

В следующей части мы напишем HelloWorld, а так же я расскажу, зачем же нам все-таки может понадобиться PICKit2 Utility. До встречи!

Конец второй части.

Часть 1
Tags:
Hubs:
Total votes 65: ↑62 and ↓3 +59
Views 8.1K
Comments Comments 19