Программирование микроконтроллеров PIC. Часть 1. Необходимые инструменты и программы. Основы MPLAB
Итак, вы решили научиться программировать pic-контроллеры. Для начала поговорим о том, что вам для работы с этими контроллерами понадобится.
Контроллер работает по определённой программе, которая должна как-то в него попасть. Обычно программу в машинных кодах, готовую для записи в контроллер, называют прошивкой. Следовательно нужно какое-то устройство, которое будет записывать (на сленге обычно говорят заливать или прошивать) программу в контроллер. Такое устройство называется программатор. Подробнее о программаторах и заливке программы мы поговорим позднее, в последней части нашей эпопеи (когда уже будет что заливать), а пока давайте по-порядку — как нам эту программу написать.
Программа для контроллера — это, как я уже сказал, набор машинных кодов, записанный в файле с расширением «hex» (здесь можно почитать про формат *.hex), который и нужно заливать в контроллер с помощью программатора. Никакого другого языка контроллер не понимает. Следовательно, нужна специальная программа, которая будет переводить текст программы, написанный на каком-либо языке программирования, в машинные коды. Наиболее удобными в этом плане являются интегрированные среды разработки (IDE — integrated development environment), поскольку они могут не только осуществлять перевод текста программы в машинный код, но и производить симуляцию её работы. Причём симуляцию можно проводить пошагово, при этом можно наблюдать состояние регистров или даже менять их состояние по своему желанию. Короче, интегрированные среды помимо, собственно, компиляции (перевода в машинные коды) предоставляют отличные возможности для отладки программы.
IDE, как и программаторов, существует много. Лично я пользуюсь MPLAB и вам рекомендую, по той простой причине, что MPLAB — это IDE от самого производителя PIC-контроллеров — фирмы Microchip, поэтому имеет отличную поддержку (в том числе на русском языке, что особенно приятно). С официального сайта Microchip можно скачать и сам этот пакет, и подробное описание по работе с ним. Если не нашли или ломает искать — ссылки для скачивания здесь, правда это уже не самая свежая версия.
В описании на русском языке про всё рассказано: от установки и настройки до удаления. В большинстве случаев вся установка заключается в том, чтобы запустить setup и ответить на пару вопросов, типа куда ставить драйверы и тому подобное, от себя лишь добавлю, что во избежание глюков ставить пакет надо в такую папку, чтобы в пути были только английские буквы (а не в какую-нибудь, типа C:\Программы\PIC\MPLAB). Вообще, кириллицу в путях к файлам или в названиях файлов лучше не использовать, иначе возможны глюки.
MPLAB позволяет писать программы на двух языках: СИ и Ассемблер. Интернет просто ломится от разборок СИ-шников и ассемблерщиков, которые с пеной у рта доказывают друг другу, какой язык лучше. Я отношу себя к ассемблерщикам, поэтому, естественно, расскажу почему лучше именно Ассемблер.
Ассемблер представляет собой набор элементарных команд, выполняемых контроллером. Каждая команда трактуется в машинный код совершенно однозначно, а результат её выполнения и время выполнения всегда одинаковы. То есть, если вы имеете листинг на ассемблере, то вы можете совершенно точно сказать, что делает контроллер в каждый момент времени и каким именно образом достигается нужный результат.
Программа на языке СИ (да и вообще на любом языке высокого уровня) — это уже набор команд не контроллера, а соответствующего языка. При компиляции каждая такая команда заменяется набором команд для контроллера, но каким именно набором команд она заменяется, — этого вы уже не знаете, это знает только разработчик языка программирования. Соответственно, невозможно понять, каким именно образом контроллер выполняет желаемое действие.
Короче говоря, в случае с языком высокого уровня вы изучаете как какой-то дядя обозвал свои способы реализации необходимых вам функций и по каким правилам их надо записывать. В данном случае можно провести следующую аналогию: вы хотите поговорить с китайцем, но вам говорят: “Китайский слишком сложный язык, но есть один дядя в Болгарии, который 20 лет жил в Китае и отлично его выучил. А болгарский язык с русским очень похожи и русскому человеку он интуитивно понятен, так что выучите болгарский, а уж дядя переведёт.”
В случае с ассемблером, вы изучаете сам контроллер и правила, по которым надо разговаривать с контроллером. При этом контроллер имеет всего-то несколько десятков команд, которые умещаются на одном листке и их легко можно окинуть одним взглядом.
Надеюсь, к этому моменту вы уже сделали выбор языка программирования, так что пойдём дальше.
Что нужно сделать в MPLAB, чтобы получить желанную прошивку? Как я уже сказал — подробности читайте в руководстве к IDE MPLAB, оно на русском и там всё понятно (если не понятно — идём на форум), я же только кратко перечислю самое основное и дам некоторые рекомендации.
Итак, мы установили MPLAB, хотим написать в нём программу для контроллера и получить готовую прошивку.
Сначала нужно создать проект. Для каждого проекта рекомендую заводить отдельную папку, потому что, во-первых, в проект может входить несколько файлов, а, во-вторых, сам MPLAB создаст ещё несколько вспомогательных файлов (*.lst, *.err, *.cod, *.bkx). Если несколько проектов будут в одной папке, то легко можно запутаться какие файлы к какому проекту относятся. Короче, создаём для проекта новую папку, потом запускаем MPLAB и выбираем меню Project -> New Project…
В появившемся окошке, в проводнике справа, выбираем нашу папку, в левой части (в поле под надписью File Name) пишем название будущего проекта, например my1.pjt (не забываем указать расширение), и жмём ОК.
Появляется окно с названием Edit Project. Это менеджер проекта, в котором указываются параметры проекта (какие файлы и библиотеки нужно подключить к проекту, какой будет использоваться камень, будет ли использоваться симуляция и многое другое). Находим поле ввода с названием Development Mode. Справа от этого поля есть кнопочка Change… Нажимаем.
Открывается окошко с названием Development Mode, в котором мы видим кучу вкладок. На вкладке Tools ставим галочку рядом с MPLAB SIM Simulator (грех для отладки симулятором не пользоваться), в поле ввода Processor выбираем контроллер, с которым мы будем работать. На вкладке Clock указываем какая у нас будет частота генератора. Жмём ОК. На ошибку и предупреждение не обращаем внимания, это просто нам говорят, что пока не могут создать .hex (ну правильно, у нас пока и программы нет) и что при изменении настроек надо заново перекомпилировать проект (так мы ещё вообще ни разу не компилировали).
В поле ввода Language Tool Suite выбираем Microchip.
Нажимаем кнопку с названием Add Node… В появившемся окне, в проводнике справа выбираем папку проекта, в поле ввода слева пишем как будет называться файл с текстом программы на ассемблере, например my1.asm (не забываем указывать расширение), и жмём ОК. Всё, теперь мы подключили к проекту файл my1.asm (указали, что текст программы будет в этом файле).
На этом с Edit project заканчиваем, — нажимаем ОК.
Теперь нужно, собственно, создать файл с текстом программы (в менеджере проекта мы просто указали, что текст будет в таком-то файле, но фактически этот файл ещё не создан). Для этого идём в меню File и выбираем пункт New. Откроется окошко редактора с названием Untitled1. Выбираем меню File -> Save As…, в проводнике справа указываем папку проекта, в поле ввода File Name пишем название файла, которое мы указали в менеджере проекта, то есть в нашем примере это будет my1.asm. Если всё сделано правильно, то название окошка редактора поменяется с Untitled1 на \путь\my1.asm.
Вот и всё! Теперь осталось только набрать в окошке редактора текст программы, скомпилировать проект (меню Project->Build All) и, если в программе нет ошибок (что с первого раза бывает очень редко), то в папке проекта появится готовая прошивка (файл с расширением hex), которую можно заливать в контроллер.
- Часть 1. Необходимые инструменты и программы. Основы MPLAB
- Часть 2. Что такое микроконтроллер и как с ним работать
- Часть 3. Структура программы на ассемблере
- Часть 4. Разработка рабочей части программы. Алгоритмы
- Часть 5. Ассемблер. Организация циклов и ветвлений
- Часть 6. Как перевести контроллер в режим программирования и залить в него прошивку
radiohlam.ru
Самоучитель по программированию PIC контроллеров для начинающих (Е.А. Корабельников,2008)
1. Готовим инструменты
Микроконтроллеры (и вообще все процессоры) изначально понимают только машинные коды, то есть некую совокупность нулей и единиц.
Те, кто представляет себе работу счетчиков, регистров, триггеров и т.д., сразу же поймет природу машинного кода.
Так как, среди электронщиков, таких людей большинство, то на мой взгляд, все они согласятся с такой аксиомой: машинные коды полезны в “малых дозах”.
Авот когда начинаются “большие дозы” (сложные устройства с десятками корпусов м/схем), то “мозги начинают дымиться” даже у классных электронщиков, имеющих недюжинные способности.
В этом случае, самое неприятное заключается в том, что по мере роста схемотехнической сложности устройства, эффективность работы электронщика резко “падает”.
И в самом деле, сил и средств вкладывается “море”, а получается нечто не очень надежное, габаритное, сложное в изготовлении, энергоемкое и дорогое.
Чтобы “одним махом прихлопнуть” все эти проблемы, “яйцеголовые” и придумали сначала “большие” процессоры (то, что применяется в компьютерах), а затем и “маленькие”, назвав их микроконтроллерами.
Внутри м/контроллера находится “набор” модулей, каждый из которых многофункционален. Манипулируя весьма не слабыми возможностями этого “набора”, можно реализовать миллионы разновидностей устройств.
Естественно, всем этим “хозяйством” нужно как-то “рулить”. Эта “рулежка” и есть то, что называется программированием.
Если речь идет о больших “массивах” машинных кодов, то программирования напрямую (в машинных кодах) и врагу не пожелаешь: удовольствия никакого, да, чего доброго, и в “психушку” попасть можно (есть исключения – люди с выдающимися способностями и гении). Для того, чтобы обычные люди могли, без особого “напряга”, заниматься составлением программ, придуманы различные языки программирования.
Смысл всех их заключается в замене машинных кодов словами, сокращениями слов, абревеатурами и т. д., то есть тем, что человеком легко и осмысленно воспринимается и чем он может комфортно оперировать при составлении текста программы.
Все эти “удобоваримые приятности”, по окончании составления текста программы, переводятся в машинные коды одним “легким движением руки” (мозги программиста не задействуются).
Чтобы это “легкое движение руки” имело место быть, “яйцеголовые” придумали так называемую “интегрированную среду разработки”.
Это есть набор программ, в котором программист работает с максимальной степенью комфорта, причем, по всему “массиву” решаемых им задач (включая и составление текста программы, и т.д. и т.п.).
Что, первым делом, нужно сделать, например, русскому, который попал в Англию и собирается там жить?
Выучить английский язык.
При “въезде” в программирование, нужно сделать то же самое (задача даже существенно проще).
“Проматерь” всех языков программирования – ассемблер.
Хотя он и считается самым простым, но слово “простой” относится прежде всего к набору его команд: количество их – минимально необходимое, и тем не менее, вполне достаточное для решения самых сложных задач, но не к комфортному восприятию их человеком.
Команды ассемблера являются либо сокращениями английских слов, либо набором первых букв английских словосочетаний, либо и тем, и другим.
Минимальный “джентльменский” набор ассемблера для ПИКов составляет 35 команд. Реально же, наиболее часто, используются от 10 до 20 команд.
В дальнейшем, настройте себя просто на тупое заучивание (на первых порах) всей этой английской “абракадабры”, типа зубрежки (я вообще не имею никакой склонности к иностранным языкам, но ничего, освоил), не такая уж это и сложная задача, заверяю Вас. В дальнейшем, Ваше образное мышление и зрительная память Вам помогут.
Авыучить ассемблер очень даже стоит по причине того, что он, может быть, и не очень
“удобоварим”, но именно на этом языке пишутся самые компактные по объему, быстрые и надежные программы, и по этой причине, серьезные программисты, работают
studfile.net
Идеальная среда разработки для PIC — личный опыт / Habr
В связи с нововведениями на сайте, решил наконец-то вылезти из подполья и написать что-нибудь полезное. Ну а поскольку я программирую разные микроконтроллеры (МК) и являюсь фанатом Eclipse, то решил про это и написать. Начну со своей истории знакомства с программированием PIC, а закончу советами тем, кто по долгу службы или в силу увлечения программирует на МК семейства PIC, хотя, впрочем, эти же советы сгодятся и для других архитектур МК.В среду железячников я попал в 2006 году на 4-м курсе учёбы в университете, когда пошёл на производственную практику в научно-технический центр, где, собственно, и работаю по сей день. В то время в нашей компании мейнстримом было использование Keil uVision2 для МК на базе C51 и ARM. Однако мне подсовывали простые задачи под PIC, вроде контроля и управления одним сигналом (кнопка вкл-выкл), и моей первой средой разработки были блокноты — бумажный и компьютерный, плюс книжки бумажные по PIC. Выглядела моя среда разработки примерно так:
Для компиляции файлов мне выдали экзешник компилятора и bat-файл, который использовался мной совершенно бездумно — даже не знаю, что за компилятор там был. В общем, суровые были времена…
Потом был MPASM, но он убогий и мне про него почти нечего вспоминать. По-моему, под него я также писал в блокноте программки.
MPLAB IDE
По мере совершенствования своих навыков я узнал, что вместо блокнота можно использовать наикрутейшую, как мне тогда казалось, MPLAB IDE:
В её состав входят:
- CC18 и ещё какой-то компилятор, которые можно выбирать в настройках проекта;
- хороший набор библиотечных функций;
- подключаемые inc-файлы описания МК семейства PIC, заточенные под использование в ассемблере;
- встроенный отладчик и программатор;
- Но главное — поддержка языка Си — это был для меня глоток свежего воздуха!
Хотя, если присмотреться к этой среде разработки, её убогость и отсталость могут отпугнуть любого мало-мальски привыкшего к хорошим условиям программиста, но я тогда об этом не знал. Справку по встроенным библиотечным функциям надо открывать отдельно и искать, что, где и как называется. Для новичков — непосильная задача. Тем не менее, на тематических форумах люди до сих пор спрашивают, какой компилятор лучше использовать; кто-то так и продолжает использовать MPLAB IDE.
MikroC
Задачи для PIC мне подкидывали всё реже и реже, начали набирать обороты разработки с МК серии C51, ARM7 (не путать с ARMv7!), Cortex-M. Но иногда ко мне снова обращались за помощью в написании программ под PIC, а я в силу любопытства пробовал новые средства разработки.
К тому времени уже давно и активно программировал в Keil uVision3 — возвращаться к допотопному MBLAB IDE совершенно не хотелось. Так я познакомился с MikroC, который поставляется вместе с программаторами PICKit:
Набор плюшек почти такой же как в MBLAB IDE, но всё же побогаче:
- свой собственный компилятор
- встроенные библиотеки функций с удобным поиском и доступным описанием;
- подключаемые h-файлы описания МК семейства PIC;
- набор дополнительных внешних утилит
- широкий спектр примеров с исходниками
- встроенный отладчик и программатор;
- встроенные вкладки открытых файлов;
- навигация по функциям в файле
Честно, для маленьких простых проектов, которые и составляют основную нишу программ под PIC, этого вполне достаточно. Даже новички нормально разбираются с помощью справки и быстро делают рабочий код. Большинство наших разработчиков, имеющих дело с PIC, используют эту среду при разработке.
Так или иначе, сделав очередной проект в MikroC, я благополучно забыл про PIC’и и думал, что уже никогда к ним не вернусь.
Однако история любит повторяться!
Через 3 года, в 2013 году, появилась задача разработать ПО по готовой КД, в которой был заложен PIC18F4680. Честно, я даже не знал, что среди PIC’ов бывают такие монстры, всегда имел дело только с мелочью!
Задачи были нетривиальные — реализация загрузчика для внутрисхемного обновления ПО, работа в режиме жёсткого реального времени, работа с АЦП, внешними ЦАП, линиями управления, несколькими таймерами-компараторами.
Кстати, немного отвлекаясь от темы: только на этом проекте я в полной мере понял, что такое банки памяти в PIC, как они работают и какие ограничения накладывают на разработку ПО. К примеру, все банки у МК по 256 байт. И хоть убейся, но для PIC нельзя создать структуру, превыщающую по объёму эти 256 байт — ограничение всплыло наружу при реализации протокола обмена, ну да ладно, проехали…
К этому времени Keil uVision3 мне уже изрядно поднадоел, поскольку сложность проектов росла и мне не хватало имевшегося в Keil функционала. Где-то с 2011 года я освоил Eclipse, GCC, синтаксис makefile — и все свои проекты начал вести с использованием этих инструментов. К тому же, у меня уже был опыт применения связки Eclipse + SDCC для реализации проекта под C51 МК. После появления Keil uVision4 я его установил, протестировал пол-часика и снёс, ибо по удобству программирования он всё равно сильно отстаёт от Eclipse.
Eclipse + SDCC
В настоящее время Eclipse де-факто является стандартом в области разработки ПО для встраиваемых систем. Вот список IDE, основанных на Eclipse, от популярных брендов:
- NXP LPCXpresso IDE
- Freescale CodeWarrior
- Xilinx Platform Studio
- Texas Instruments CCS
- Android Development Tools
Автоподстановка, всплывающие подсказки по автодополнению, макросы, затемнение неактивных участков кода, удобная навигация по коду и многое-многое другое, — я не буду всё перечислять, — многие разработчики встраиваемых систем совершенно не привыкли и не знают всех этих плюшек, значительно облегчающих жизнь:
Главной проблемой чистого Eclipse для разработки на C/C++ под МК является сложность вхождения в него железячных программистов, замена привычных инструментов, работающих после установки в 1-2 клика, на какие-то плагины, требующие настройки, или, что ещё хуже, на вручную написанные makefile — всё это требует значительных первоначальных усилий по чтению и изучению документации, поиску помощи и пособий для начинающих в интернете. Говорю как человек, имеющий опыт по переводу команды программистов-железячников на Eclipse.
Коли прочитали эту статью — дайте знать, я хоть узнаю, как у нас читают профильные хабы на Хабрахабре
Однако, за месяц полностью освоив синтаксис и один раз написав качественный makefile, все остальные проекты создаются по накатанному шаблону и требуют лишь минимальной индивидуальной настройки.
Также пришлось сделать ряд дополнительных телодвижений по настройке проектов под PIC — по умолчанию Eclipse понимает синтаксис GCC. Различные макросы и директивы, встроенные в другие компиляторы (будь то СС18 или SDCC), приходится разделять на этапе компиляции и на этапе индексации проекта. Чтобы при навигации в коде редактор не выдавал ложных ошибок на неизвестные директивы, к исходникам проекта подключается файл eclipse-syntax.h:
#ifndef ECLIPSE_SYNTAX_H_
#define ECLIPSE_SYNTAX_H_
// keyword SDCC defined when compiling with SDCC compiler
#ifndef SDCC
#ifdef __SDCC_PIC18F4680
#error "SDCC not found, project compile will be with errors!"
#endif
// file not parsed through makefile - just for proper eclipse syntax
#ifndef __CC18__
#error "__CC18__ not found, use `-D__CC18__` in makefile for proper CC18 compilation!"
#define near
#define far
#define rom
#define ram
#define _asm
#define _endasm
#define Nop()
#define ClrWdt()
#define Sleep()
#define Reset()
#define clrwdt
#define nop
#define __code
#define __data
#define __xdata
#define __sfr
#define __sbit
#define __naked
#define __wparam
#define __bit char
#define __at(num)
#else // __CC18__ defined - compile stage!
#endif // __CC18__
#define __inline
#define __asm
#define __endasm
#define __interrupt(x)
#define INTERRUPT(x)
#define USING(x)
#define CRITICAL
#define CRITICAL_START
#define CRITICAL_END
#define _REENTRANT
#else // if SDCC defined
#define INTERRUPT(x) __shadowregs __interrupt (x)
//#define USING(x) __using (x)
#define USING(x)
#define CRITICAL __critical
#define CRITICAL_START __critical {
#define CRITICAL_END }
#endif // SDCC defined
#endif /* ECLIPSE_SYNTAX_H_ */
Кроме того, в SDCC у меня не получилось слинковать большой проект в готовый бинарник — потребовалось также настроить GPUtils, в состав которого входят gpasm, gpdasm, gplink и скрипты .lkr карт памяти МК PIC. Правда, из-за одного найденного мной бага в SDCC на этапе отладки кода я в итоге вернулся на CC18 компилятор и линковщик. Тем не менее, SDCC и GPUtils были полностью настроены — для страждущих привожу часть makefile, касающуюся опций запускаемых компиляторов и линковщиков CC18, SDCC, GPUtils:
Кусочки makefile
###########################################################
# project-specific compile options
###########################################################
# Project definitions
CHIP = 18F4680
DEFINES := -DPIC$(CHIP)
#DEFINES += -D__SDCC_PIC$(CHIP) # use SDCC compiler
DEFINES += -D__CC18__ # use MPLAB CC18 compiler
#DEFINES += -DOPTIMIZE_BITFIELD_POINTER_GET # SDCC memory optimize for bitfield structures
###########################################################
# common part for all sdcc-based projects
###########################################################
SDCC_BASE = c:/DevTools/SDCC
CC = "$(SDCC_BASE)/bin/sdcc.exe"
LD = "$(SDCC_BASE)/bin/sdcc.exe"
ELF2HEX = "$(SDCC_BASE)/bin/packihx.exe"
HEX2BIN = "$(SDCC_BASE)/bin/makebin.exe"
###########################################################
# common part for all MPLAB MCC18-based projects
###########################################################
MPLAB_BASE = c:/DevTools/CC18
CC_MPLAB = "$(MPLAB_BASE)/bin/mcc18.exe"
AS_MPLAB = $(MPLAB_BASE)/mpasm/mpasmwin.exe
LD_MPLAB = $(MPLAB_BASE)/bin/mplink.exe
###########################################################
# GPUtils used with SDCC for linking project
###########################################################
GPUTILS_BASE = c:/DevTools/GNUPICutils
GPASM = "$(GPUTILS_BASE)/bin/gpasm.exe"
GPDASM = "$(GPUTILS_BASE)/bin/gpdasm.exe"
GPLINK = "$(GPUTILS_BASE)/bin/gplink.exe"
###########################################################
# C preprocessor flags for MPLAB MCC18 compiler
###########################################################
#optimization parameters (default = full optimization)
OPT_ENABLE_ALL := -O+ # Enable all optimizations (default)
OPT_DEBUG :=-Ou- -Ot- -Ob- -Op- -Or- -Od- -Opa-
OPT :=$(OPT_ENABLE_ALL)
#OPT :=$(OPT_DEBUG)
CFLAGS_MPLAB := -p $(CHIP)
CFLAGS_MPLAB += -I $(MPLAB_INC_DIR)
CFLAGS_MPLAB += -nw=2066 # suppress Warning [2066] type qualifier mismatch in assignment
CFLAGS_MPLAB += -ml # Large memory model
CFLAGS_MPLAB += -ls # large stack (can span multiple banks)
#CFLAGS_MPLAB += -scs # Enable default static locals
#CFLAGS_MPLAB += -sco # Enable default overlay locals (statically allocate activation records). Ignored if set --extended
CFLAGS_MPLAB += --extended # generate extended mode code
COMPILE_MPLAB_STRING=$(CC_MPLAB) $(CFLAGS_MPLAB) $< -fo=$@ $(DEFINES) $(OPT)
AFLAGS_MPLAB := /y
AFLAGS_MPLAB += /rDEC # set default radix HEX/DEC/OCT
AFLAGS_MPLAB += /l- # disable listing file
#AFLAGS_MPLAB += /l$(OBJDIR_MPLAB) # enable listing file
AFLAGS_MPLAB += /o # specify path for object files
#AFLAGS_MPLAB += /o$(OBJDIR_MPLAB) # specify path for object files
#AFLAGS_MPLAB += /q # enable quiet mode
AFLAGS_MPLAB += /d__LARGE__ # define symbol
AFLAGS_MPLAB += /p$(CHIP) # set processor type
#ASSEMBLE_MPLAB_STRING=$(AS_MPLAB) $(AFLAGS_MPLAB) %<
# used linker script
LDFLAGS_MPLAB := $(CHIP)_g.lkr
# objects to compile
LDFLAGS_MPLAB += $(OBJS_MPLAB)
LDFLAGS_MPLAB += $(MPLAB_LIBS)
# specify chip for proper linking
LDFLAGS_MPLAB += /p$(CHIP)
# verbose mode operation
#LDFLAGS_MPLAB += /v
# generate report file for stack analysis
LDFLAGS_MPLAB += /g
# generate .LST file and no .COD file
LDFLAGS_MPLAB += /i
# do not invoke MP2COD (no .COD or .LST file)
LDFLAGS_MPLAB += /w
# link MPLAB libs
LDFLAGS_MPLAB += /l $(MPLAB_LIB_DIR)
# generate MAP file
LDFLAGS_MPLAB += /m $(EXEDIR)/$(PROJECT_NAME)_mplab.map
# set output file
LDFLAGS_MPLAB += /o $(EXEDIR)/$(PROJECT_NAME)_mplab.hex
###########################################################
# C preprocessor flags for SDCC v.3.3.0 compiler
###########################################################
# ----- processor selection -----
CFLAGS := -m$(ARCH)
CFLAGS += -p$(CHIP)
# ----- preprocessor options -----
CFLAGS += $(INCS)
CFLAGS += $(DEFINES)
# ----- verbose & dependancy generate -----
# CFLAGS += -M # generate dependencies
# CFLAGS += -E #
# CFLAGS += -C # dont discard comments
CFLAGS += -c # dont link file (i.e. have multiple source files)
CFLAGS += $(DEBUG)
# ----- common settings -----
#CFLAGS += --nostdinc # This will prevent the compiler from passing on the
# default include path to the preprocessor.
#CFLAGS += --nostdlib # This will prevent the compiler from passing on the
# default library path to the linker.
#CFLAGS += --less-pedantic # Disable some of the more pedantic warnings.
CFLAGS += --stack-auto # All functions in the source file will be compiled as reentrant.
# It automatically implies --int-long-reent and --float-reent.
CFLAGS += --int-long-reent # Integer (16 bit) and long (32 bit) libraries have been compiled as reentrant.
CFLAGS += --float-reent # Floating point library is compiled as reentrant.
#CFLAGS += --no-peep
#CFLAGS += --funsigned-char # The default signedness for every type will be unsigned.
#CFLAGS += --cyclomatic # This option will cause the compiler to generate an information
# message for each function in the source file. The message contains
# the number of edges and nodes the compiler detected in the
# control flow graph of the function, and most importantly
# the cyclomatic complexity.
# ----- optimization options -----
#CFLAGS += --nogcse # Will not do global subexpression elimination, this option may be used
# when the compiler creates undesirably large stack/data spaces to store
# compiler temporaries.
#CFLAGS += --noinvariant # Will not do loop invariant optimizations.
#CFLAGS += --noinduction # Will not do loop induction optimizations.
#CFLAGS += --nojtbound # Will not generate boundary condition check when switch statements
# are implemented using jumptables.
#CFLAGS += --noloopreverse # Will not do loop reversal optimization.
#CFLAGS += --nolabelopt # Will not optimize labels (makes the dumpfiles more readable).
CFLAGS += --nooverlay # The compiler will not overlay parameters and local variables of any function.
CFLAGS += --peep-asm # Pass the inline assembler code through the peep hole optimizer.
#CFLAGS += --opt-code-speed # Optimize for code speed rather than size
#CFLAGS += --opt-code-size # Optimize for code size rather than speed
CFLAGS += --fomit-frame-pointer # Frame pointer will be omitted when the function uses
# no local variables.
CFLAGS += --use-non-free # Search / include non-free licensed libraries and header files
# ----- special options for pic16 port of SDCC -----
CFLAGS += --pstack-model=large # use stack model 'small' (default) or 'large'
# don't use extended instruction set - SDCCman, $4.6.20.1 Known Bugs
#CFLAGS += -y --extended # enable Extended Instruction Set/Literal Offset Addressing mode
#CFLAGS += --pno-banksel # do not generate BANKSEL assembler directives
CFLAGS += --obanksel=2 # set banksel optimization level (default=0 no)
CFLAGS += --denable-peeps # explicit enable of peepholes
CFLAGS += --no-optimize-goto # do NOT use (conditional) BRA instead of GOTO
CFLAGS += --optimize-cmp # try to optimize some compares
CFLAGS += --optimize-df # thoroughly analyze data flow (memory and time intensive!)
#CFLAGS += --preplace-udata-with=udata_shr # Place udata variables at another section: udata_acs, udata_ovr, udata_shr
#CFLAGS += --ivt-loc= # Set address of interrupt vector table.
#CFLAGS += --nodefaultlibs # do not link default libraries when linking
#CFLAGS += --use-crt= # use <crt-o> run-time initialization module
#CFLAGS += --no-crt # do not link any default run-time initialization module
#CFLAGS += --mplab-comp # enable compatibility mode for MPLAB utilities (MPASM/MPLINK)
#CFLAGS += --asm= # Use alternative assembler
#CFLAGS += --link= # Use alternative linker
CFLAGS += --debug-xtra # show more debug info in assembly output
CFLAGS += --debug-ralloc # dump register allocator debug file *.d
CFLAGS += --pcode-verbose # dump pcode related info
CFLAGS += --calltree # dump call tree in .calltree file
#CFLAGS += --gstack # trace stack pointer push/pop to overflow
###########################################################
# linker flags
###########################################################
#gputils (GNU PIC Utils) used to link objects and libs.
GPLINK_FLAGS = -c -m -w -r -I $(LIBDIR) -s $(GPUTILS_BASE)/lkr/$(CHIP)_g.lkr
#SDCC linker not used
#LDFLAGS := -m$(ARCH)
#LDFLAGS += $(DEBUG)
#LDFLAGS += --profile
#LDFLAGS += --code-size $(FLASH_SIZE) # Code Segment size
#LDFLAGS += --code-loc $(FLASH_LOC) # The start location of the code location, default value is 0
#LDFLAGS += --iram-size $(IRAM_SIZE) # Internal Ram size
#LDFLAGS += --xram-loc $(XRAM_LOC) # The start location of the external ram, default value is 0
#LDFLAGS += --xram-size $(XRAM_SIZE) # External Ram size
#LDFLAGS += --stack-loc $(STACK_LOC) # By default the stack is placed after the data segment.
# Using this option the stack can be placed anywhere in the
# internal memory space of the 8051.
##############################################################################
# MPLAB CC18 compiler - linker
$(HEX_MPLAB): $(OBJS_MPLAB) Makefile
@echo "--- CC18 Linking objects to $(HEX_MPLAB) ..."
@$(LD_MPLAB) $(LDFLAGS_MPLAB)
##############################################################################
# SDCC compiler - linker
$(HEX): $(OBJS) Makefile
@echo "--- SDCC Linking objects to $(HEX) ..."
$(GPLINK) $(GPLINK_FLAGS) -o $(HEX) $(OBJS) $(LIBS)
$(GPDASM) -p$(CHIP) $(HEX) > $(DASM)
Эпилог
Как видно, в итоге я пришёл к использованию связки Eclipse с внешними компиляторами. Изучение опций компиляции — дело нужное и не столь сложное, чтобы просто так от него отказываться — любой программист сможет их изучить и применить при необходимости. Думаю, в итоге у меня получилась идеальная связка, доступная на сегодняшний день для создания проектов под PIC.
Собирая воедино все средства разработки, вот список компиляторов, которыми я пользуюсь в связке с Eclipse и получаю от этого истинное удовольствие при программировании:
- CC18 для PIC
- SDCC для C51
- gnu-arm-embedded для ARM7 и Cortex-M
- MinGW для x86
Очевидно, при необходимости список может легко дополняться.
Надеюсь, прочитав мою историю, кто-то решится наконец для себя сойти со старых IDE и освоить новые.
Дерзайте!
habr.com
Программирование микроконтроллеров семейства PIC начинающим
Главная страница » Программирование микроконтроллеров семейства PIC начинающим
Первые микроконтроллеры появились в 60-х годах. Автоматизированные системы до этого времени обычно строились на основе реле. В принципе, релейные системы исполняли требуемую функцию вполне успешно. Однако главным недостатком релейных схем являлись сложности модернизации на случай изменения функциональности. Для инженеров проще было собрать новую релейную систему, нежели модифицировать уже существующую. В этом смысле программируемый логический контроллер оказался куда более предпочтительным устройством. Теперь программируемые логические контроллеры распространены повсеместно. Однако тонкости программирования таких систем остаются малопонятными для многих радиолюбителей. Рассмотрим этот важный момент – как программировать контроллер на примере широко известной серии ПЛК (PLC — Peripheral Interface Controller): продукта компании Microchip Technology Inc.
СОДЕРЖИМОЕ ПУБЛИКАЦИИ :
Общий взгляд на устройства ПЛК
Системы на базе микропроцессора (микроконтроллеры) выступают в качестве программируемых электронных устройств, для которых специально разработаны языки программирования. Благодаря таким языкам программирования, существенно облегчается процесс программирования контроллеров. Язык высокого уровня, созданный для ПЛК, обеспечивает простоту, эффективность и дружелюбную среду для пользователя.
Микропроцессор фактически можно рассматривать электронной схемой, поддерживающей обработку команд, хранящихся в системной памяти. Эта же схема работает с инструкциями — арифметическими и логическими, использует внешние устройства:
- память,
- входные порты,
- выходные порты.
В свою очередь, микроконтроллер представляет собой интегральную схему, в составе которой присутствуют:
- микропроцессор,
- память программ и данных,
- генератор тактовых импульсов,
- интерфейсы ввода и вывода,
- таймеры,
- аналого-цифровые преобразователи,
- внешние коммуникационные порты и другие схемы.
Макрос языка высокого уровня — это инструкция, которая является сокращённой строкой, содержащей несколько инструкций. Запись программы с повторяющимися действиями (схожестью инструкций) при использовании макросов значительно сокращается.
Программируемые микроконтроллеры используются в составе современной электроники повсеместно. Умение работать с этим функциональным инструментом открывает широкие горизонтыЭффективность программы на основе макросов столь же эффективна, как и запись программы на языке «C». Компилятор отвечает за создание соответствующих подстановок для генерации кода, который передаётся в память программы микропроцессора или микроконтроллера.
Программирование широко распространённых микроконтроллеров PIC12 / PIC16
Микроконтроллеры PIC программируются с использованием проприетарного последовательного протокола. Поэтому конечному пользователю недостаточно просто взять и подключить микросхему контроллера PIC напрямую к любому «стандартному» интерфейсу.
Однако технические требования относительно программирования по времени достаточно слабы. Этот фактор даёт возможность использовать некоторые выводы параллельного или последовательного порта компьютера для генерации программной последовательности с помощью программного обеспечения.
Помимо рабочего напряжения, микроконтроллерам требуется ещё три сигнала:
- Программируемое напряжение (около 13В).
- Таймер программирования (ICSPCLK).
- Данные (ICSPDAT).
Поскольку большинство выпускаемых экземпляров PIC допускают программируемое напряжение несколько ниже значения, указанного спецификацией, открывается возможность использования уровней сигналов ± 12В, присутствующих на интерфейсе последовательного порта настольного ПК. Таким образом, «записать» PIC вполне допустимо без необходимости подключения дополнительного источника питания.
Преобразование уровней допускается выполнять при помощи нескольких компонентов. Однако представленная ниже упрощённая схема, обладает некоторыми ограничениями. В частности, позволяет считывать и программировать непосредственно PIC устройства. Нет никакой гарантии, что эта схема способна обеспечить программирование всех контроллеров, поскольку не соответствует полной спецификации программирования.
Схема принципиальная упрощённого программатора микроконтроллеров серии PIC и обозначенные линии подключения интерфейсов RS232 / ISSPВнутрисхемное программирование микроконтроллера PIC
Разъём внутрисхемного программирования (ICSP) предоставляет возможность запрограммировать микроконтроллер непосредственно в рамках прикладной схемы. Этот вариант видится особенно полезным в домашних условиях или в другой не специальной среде, где по каким-либо причинам требуется повторное изменение программированием PIC и тестирование схемы.
Применение разъёма ICSP позволяет избежать рисков при перемещении микроконтроллера PIC между различными гнездами (например, в случае изгиба контактов или воздействия на микроконтроллер электростатических разрядов). Также работа с разъёмом ICSP обеспечивает экономию времени.
Вот такой вариант ICSP соединителя вполне подойдёт для подключения линий связи на случай выполнения программирования микроконтроллера серии PIC12/PIC16Следует внимательно использовать интерфейс и кабель ICSP, принимая во внимание, что схема не должна нарушать ход сигналов программирования. Другими словами – точное соответствие месту назначения сигналов необходимо выполнять безукоризненно.
Основные условия программирования:
- время переключения напряжения программирования «0 – 13В» составляет несколько микросекунд;
- полный размах напряжения сигналов таймера и данных достигается в течение одной микросекунды;
- вывод сигнала PGM остаётся низким всё время программирования.
Некоторые микроконтроллеры PIC требуют применения напряжения программирования до подачи рабочего напряжения. В этом случае напряжением программирования управляют через модуль программатора. Самый простой способ выполнить первые два условия — не использовать корреспондирующие выводы в цепях схемы. Если необходимо, следует использовать отладчик.
Рекомендации относительно процедуры программирования
Не рекомендуется подключать активные цепи к линии внешнего (основного) сброса (MCLR – Microcontroller Line Reset). Если сигнал MCLR используется для сброса PIC, следует устанавливать резистор номинальным сопротивлением более 56 кОм между выводами MCLR и подачи напряжения питания. Рекомендуется в цепь резистора включать конденсатор небольшой ёмкости — менее 100 пФ со смещением на землю (вывод GND).
Сигнальные выводы программирования должны исключать наличие индуктивной или ёмкостной нагрузки. Когда рабочее напряжение питания берётся от модуля программатора, требуется изолировать вывод питания PIC от остальной части прикладной схемы в процессе программирования.
Схемные доработки программатора микроконтроллера, рекомендуемые с целью обеспечения более качественного процесса программирования устройстваЭтот вариант может иметь место, если схема содержит собственный стабилизатор напряжения питания и оснащается развязывающим конденсатором большой ёмкости. Модуль программатора, предназначенный под напряжение питания 3,3В, не в состоянии заряжать конденсатор достаточно быстро, а для программирования PIC требуется не менее 4,5В.
Между тем вариант изолирования можно исключить, если в схеме используется диод Шоттки. Чтобы удерживать вывод перевода микроконтроллера в режим программирования (PGM) на низком уровне, рекомендуется подключать этот вывод к земле через резистор номиналом от 2,2 кОм до 10 кОм.
Всегда рекомендуется таймер включения питания вносить в «слово» конфигурации. Задержка таймера более 40 мс даёт достаточно времени для стабилизации напряжения питания перед началом любой операции. Такой шаг позволяет избежать непреднамеренного выполнения программы до входа в режим программирования.
Во время программирования остальные контакты порта остаются в режиме ввода — имеют высокий импеданс. Используемой схемой необходимо обрабатывать такое состояние по возможности неактивным способом. Чтобы избежать нежелательных «побочных эффектов», следует рассмотреть возможность дополнения подтягивающими резисторами.
Для обеспечения повторного программирования микроконтроллера PIC в условиях напряжения питания ниже 4,5В, область памяти необходимо отключить от защиты. Это обусловлено применением «Chip Erase», единственного способа удаления кода или защиты данных, которого требуют практически все микроконтроллеры PIC с напряжением питания выше 4,5В.
Сигналы ICSP соответствующие контактам PIC 12Fxxx / 16Fxxx
Число ниже аббревиатуры сигнала соответствует выходу разъема ICSP модуля программатора. Для использования модуля с тестовыми платами сторонних производителей требуется адаптер.
Следует обратить внимание: разъём ICSP этого модуля программатора имеет различный порядок сигналов по сравнению с другими программаторами микроконтроллеров PICСледующие схемы показывают, как подключать сигналы программирования к микроконтроллерам PIC 12Fxxx / 16Fxxx:
Схемы, определяющие порядок подключения сигнальных проводников, участвующих в процедуре чтения/записи данных микроконтроллеров разной конфигурацииФирменные средства программирования
Существует солидная группа фирменных программаторов для микроконтроллеров семейства PIC. Наиболее известные аппаратные средства:
- REAL ICE
- Pickit 1-2-3
- IC PROG
- ICD 2-3
Характерные отличия отмеченных программаторов – устройства обладают не просто классическими функциями чтения/записи. Фирменным программаторам присущ целый ряд расширенных функций, включая полный контроль содержимого памяти и стёка.
На основе информации: Uolsinectis
zetsila.ru
Программирование PIC16F876A. Собираем схему с плавно мигающим светодиодом / Habr
Эта статья направлена на новичков в программировании микроконтроллеров семейства PIC16 от Microchip. В нашем случае, я выбрал немного превосходящий микроконтроллер для таких задач, а именно — PIC16F876A. Программирование микроконтроллера будем производить в MPLAB IDE.Цель работы: собрать схему, которая будет мигать светодиодом, внимание, с применением ШИМ.
И так, цель задачи обозначили. Теперь перейдем к реализации наших планов.
Часть 1. Железо.
В первую очередь нам понадобятся компоненты, из которых мы будем собирать схему. А именно:
- Микроконтроллер PIC16F876A
- Рассыпуха к нему
- Светодиод
- Макетная плата
Макетную плату желательно иметь в наличии.
В понятие «рассыпухи» входят такие детали как: пара конденсаторов для кварца и конденсатор на выход модуля CPP (Для того что бы сгладить пульсации).
Собранная схема выглядит следующим образом:
Это типовое включение микроконтроллера, ничего нового я тут не придумывал.
Так же, для программирования микроконтроллера я пользуюсь программатором-отладчиком ICD2. Он подключается к компьютеру по USB и прекрасно работает как на системе Windows, так и на GNU/Linux. В нашем случае будем использовать родной MPLAB IDE в Windows.
Скрин в процессе разработки:
Часть 2. Программная.
Светодиод подключаем на 1й модуль CPP (ШИМ). За настройку модуля в микроконтроллере отвечает регистр CPP1CON. Чтобы модуль у нас заработал, предварительно необходимо инициализировать таймер. Для режима ШИМ используется таймер TMR2. За его конфигурацию отвечает регистр T2CON. Инициализация:
movlw .0
bcf STATUS, 5movwf T2CON ; Помещаем в регистр T2CON - 0
bsf T2CON, 0 ; Устанавливаем бит T2CKPS0 (Предделитель)
bsf T2CON, 2 ; Включаем таймер TMR2 битом TMR2ON
bsf T2CON, 3 ; Устанавливаем бит TOUTPS0 (Постделение)
На этом инициализация таймера закончена. Теперь при включении контроллера от будет служить источником для нашего ШИМ модуля.
Инициализация ШИМ модуля происходит следующим образом:
movlw 00101111b ; Подготавливаем конфигурацию
movwf CPPCON ; Конфигурируем ШИМ
bsf CPPCON, 2 ; Включаем модуль ШИМ
Все, на этом инициализация закончена. Теперь мы можем помещать в регистр CPP1L число от 0 до 255, тем самым меняя скважность выходных импульсов.Полный исходник программы для прошивки нашего микроконтроллера:
STATUS equ 03h
TRISC equ 07h
CPPCON equ 17h
CPP1L equ 15h
T2CON equ 12h
counter equ 23h
tmp equ 25h
org 0
goto start
start
bsf STATUS, 5
movlw .0
movwf TRISC
bcf STATUS, 5
movwf T2CON
bsf T2CON, 0
bsf T2CON, 2
bsf T2CON, 3
movlw 00101111b
movwf CPPCON
bsf CPPCON, 2
movlw .0
movwf CPP1L
movlw .255
movwf tmp
decfsz tmp, 1
goto $+2
goto $+4
call delay10mS
incf CPP1L, 1
goto $-5
movlw .255
movwf tmp
decfsz tmp, 1
goto $+2
goto $+4
call delay10mS
decf CPP1L, 1
goto $-5
goto $-16
delay10mS
movlw .50
movwf counter
loop
call delay200uS
decfsz counter
goto loop
return
delay200uS
movlw .100
addlw -1
btfss STATUS,2
goto $-2
return
end
Краткая заметка по командам, использованных в программе.equ — Присвоение имени на определенный адрес.
goto — Переход программы на метку, либо определенную строку
call — Вызов подпрограммы
movlw — Поместить в регистр W, число
movwf — Переместить из регистра W число
bsf — Установить бит в регистре, в состояние 1
bcf — Установить бит в регистре, в состояние 0
addlw — Прибавить в регистр W число
btfss — Проверить бит в регистре на 1
incf — Инкриминировать регистр (прибавить 1)
decf — Декриминировать регистр (вычесть 1)
decfsz — Вычесть 1 из регистра + проверка на 0
Задержки в программе откалиброваны на частоту кварцевого резонатора в 8мгц.
Принцип работы программы.
В начале, происходит инициализация регистров, затем настройка внутренних модулей микроконтроллера.
В переменной tmp мы можем задавать скважность, тем самым меняя максимальную яркость светодиода.
Далее реализована часть программы, которая отвечает за само мигание светодиода, с учетом использования ШИМ. Сначала, инкриминируя CPP1L до значения tmp мы заставляем светодиод медленно начать светиться, а затем делаем обратную операцию.
Часть 3. Финальная
Перед тем как прошивать Ваш контроллер, Вам необходимо установит биты конфигурации микроконтроллера. Без них, ничего работать не будет.
И так:
1) WDT — выключаем. Это сторожевой таймер. Предназначен для аппаратного сброса микроконтроллера в момент непредвиденного зависания.
2) LWP — выключаем. Это низковольтное программирование. Мы используем нормальный программатор, который подает на MCLR 13В.
3) Осцилятор: В данном случае мы имеем 8мгц. Значит ставим значение XT.
Часть 4. Бонусная.
Видео для тех, кто еще не программировал/не собирал схемы, но очень хочет увидеть результат:
Часть 5. Информация.
Официальный сайт microchip — www.microchip.com
Цитируемые источники — www.wikipedia.org
Русская документация для микроконтроллеров PIC — www.microchip.ru/lit/?mid=1×0
habr.com
РадиоКот :: Начинающим программистам микроконтроллеров PIC
РадиоКот >Обучалка >Микроконтроллеры и ПЛИС >Несколько слов о PIC-контроллерах >Начинающим программистам микроконтроллеров PIC
Автор: Владимир Д.
[email protected]
Исходя из собственного опыта начала изучения программирования микроконтроллеров постараюсь дать несколько практических советов по составлению программ на ассемблере. Все, приведенные ниже, примеры программирования даны применительно к Pic контроллерам среднего семейства Microchip,как наиболее приемлемых для начала освоения, ввиду относи- тельно простой их архитектуры и несложной системы команд ассемблера.
Предлагаемые программы вполне можно применять в виде готовых макросов (законченных подпрограмм).Они не привязаны к конкретному контроллеру, поэтому при применении следует учитывать данные из datasheet -ов.
Примем тактовую частоту – Fтакт. = 4,096 МГц (стандартный кварц). Тогда время цикла составит t c = 1 / Fтакт. * 4 = 0,97656 мкс
INI_TMR ; инициализация режима прерываний от RTCC bsf STATUS,RP0 ; выбираем банк 1 movlw b"00000100" movwf OPTION ; предделитель для RTCC 1 : 32 bcf STATUS,RP0 ; банк 0 movlw b"10100000" movwf INTCON ; разрешено прерывание от RTCC movlw .96 ; загружаем в RTCC предварительное число 96 movwf TMR0
Получим время прерываний:
t i = t c * 32 * (256 – 96 = 160)
t i = 0,97656 * 32 * 160 = 5 000 мкс = 5 мс
Теперь, если в Вашу любую программу ввести бесконечный цикл (так называемый цикл ожи- дания прерывания), и окончание программы переводить на этот цикл, получим временную привязку к 5 мс.И после прерывания программа вернётся по адресу, указанном вектором прерываний (чаще это 04h).Для чего это можно использовать – смотри дальше.
Итак:
; org 0 START ; начало выполнения программы после ; включения питания org 04h ; а это адрес вектора прерывания, по которому main ; будет выполняться основная программа ; START ; здесь обычно происходит обязательная ини- INI_TMR ; циализация портов, режимов, регистров и т.п. INI_PORTS loop goto loop ; а это и есть бесконечный цикл ;-------------------------------------------------- main ; далее идёт тело основной программы, ; в которой обязательно надо создать программу обслуживания прерываний от RTCC, ; вызываемой командой CALL: ServTMR btfsc INTCON,RTIF ; проверяем флаг срабатывания прерываний от RTCC и call SET_TMR ; если "да",то снова инициализируем TMR0 return ; если "нет" - возврат в место вызова ServTMR в ; основной программе main ; SET_TMR movlw .96 movwf TMR0 ; снова загружаем число 96 bcf INTCON,RTIF ; сбрасываем флаг срабатывания retfie ; возврат с разрешением прерываний в ServTMR, а ; затем в основную программу main
Пример использования прерывания от RTCC для получения секундного импульса на одном из выходов , скажем, порта В – RB0 : Используем регистр Rsec, который должен быть ранее объявлен в в адресном поле рабочих регистров.
FORM_1S ; в каждом цикле, а он по прерыванию RTCC длится incf Rsec,w ; 5 Мс, увеличиваем регистр Rsec на 1 до числа 200 xorlw .200 ; (5 мс * 200 = 1 сек) btfsc STATUS,z goto OUT_PORT ; при Rsec = 200 флаг z = "1" и переход на управление ; выводом RB0 порта В return ; возврат в основную программу main ; OUT_PORT btfss PORTB,0 ; проверяем состояние вывода RB0 goto OUT_ON ; если RB0 ="0", то устанавливаем в "1" bcf PORTB,0 ; в противном случае - устанавливаем в "0" goto main ; возврат в основную программу ; OUT_ON bsf PORTB,0 ; устанавливаем RB0 = "1" goto main
Таким образом на выходе RB0 порта В каждую секунду уровень сигнала будет изменяться то “0” то “1”.
В регистрах контроллера информация находится обычно в двоичном виде, ( в бинарном коде). Но часто необходимо получить информацию в двоично – десятичном виде (BCD – код), скажем, для управления поразрядно семисегментным индикатором.
Рассмотрим примеры преобразований двоичного кода b2 в двоично – десятичный BCD и наоборот.
В 8 – bit регистре можно записать в двоичном коде число от 0 до 255 ( от b”00000000″ до b”11111111″ ). Преобразуем двоичное число в три разряда двоично – десятичного кода - “сотни”, “десятки” и “единицы”. Для этого будем использовать следующие регистры, которые должны быть заранее объявлены в адресном поле рабочих регистров :
Rbin – регистр хранения числа в двоичном коде b2
Rhan – регистр “сотни” кода BCD
Rdec – регистр “десятки” кода BCD
Rsim – регистр “единицы” кода BCD
Преобразования проводим используя операции вычитания чисел 100, а затем 10 с подсчётом количества положительных вычитаний.
CON_100 movlw .100 ; вычитаем 100 из Rbin c проверкой, что subwf Rbin,w ; результат не отрицательный. Флаг "c" = 1 при btfss STATUS,c ; результате > или = 0, и "c" = 0 приОбратное преобразование BCD - кода в b2. Используем те же регистры Rhan, Rdec, Rsim где находится число в BCD - коде, регистры RbinH - старший разряд и RbinL - младший разряд для чисел ( > 255) в коде b2 и вспомогательные регистры RM1 - "множимое" , RM2- "множитель".Для преобразования BCD в b2 нужно умножить "сотни" на 100, "десятки" на 10 и сложить всё вместе с "единицами" и с учётом переноса в старший разряд при необ- ходимости.Для умножения используем операцию сложения.
B2X_100 movlw .99 ; преобразование "сотен" movwf RM2 ; множитель = кол - во сложений (100) минус один movf Rhan,w movwf RM1 ; множимое = "сотни" loopX100 addwf RM1,w btfsc STASTUS,c ; проверяем перенос в старший разряд incf RbinH,f ; если есть перенос decfsz RM2,f ; контролируем количество сложений goto loopX100 movwf RbinL ; результат сложения заносим в регистр мл. разряда ; B2X_10 movlw .9 ; преобразование "десятков" movwf RM2 ; множитель = кол - во сложений (10) минус один movf Rdec,w movwf RM1 ; множимое = "десятки" loopX10 addwf RM1,w ; здесь перенос можно не проверять, т.к. результат decfsz RM2,f ; всегдаКонец преобразованиям и дальнейшее выполнение программы. В регистрах RbinL и RbinH получили 16 - bit число в коде b2.
Для выполнения арифметической операции деления по аналогии с умножением, рассмот- ренном выше, применяется операция вычитания. Допустим нам нужно произвести деление числа, находящегося в регистрах RHsum (старшие разряды) и RLsum (младшие разряды) - на делитель ( примем делитель не > 255) находящийся в регистре Rdel.
Результат будем заносить в регистры RHrez и RLrez (старшие и младшие разряды соот- ветственно) :
OP_DEL movf Rdel,w subwf Rlsum,w btfss STATUS,c ; проверяем не отрицательный ли результат? goto DEF_carry ; если "да", то проводим заём из ст. разряда incf RLrez,f ; подсчитываем кол-во вычитаний с учётом btfsc STATUS,c ; возможного переноса в старший разряд incf RHrez,f movwf RLsum ; восстанавливаем остаток, что бы не потерять goto OP_DEL ; при отрицательном результате вычитания ; DEF_carry movlw 0h xorwf RHsum,w ; всё ли заняли из старшего разряда в младший? btfsc STATUS,z ; если "да", т.е. RHdel = 0 и в OP_DEL отри- goto OUT_ DEL ; цат. результат - конец делению и выход decf RHsum,f ; если "нет" - заём из старшего разряда и про- incf RLrez,f ; должаем дальше btfsc STATUS,c ; проверка необходимости переноса в ст.разряд incf RHrez,f goto OP_DEL
Как вам эта статья? | Заработало ли это устройство у вас? |
www.radiokot.ru
Программирование микроконтроллеров PIC. Часть 2. Что такое контроллер и как с ним работать
Итак, вы прочитали предыдущую статью и установили MPLAB. Что дальше? Дальше давайте немного поговорим о том, что вообще представляет собой pic-контроллер, как он устроен и как с ним работать. Принципы построения у всех pic-контроллеров одинаковые и принципы работы со всеми контроллерами тоже одинаковы, но в этой статье в качестве конкретных примеров будут использоваться примеры для PIC16F628A.
Контроллер можно представить как совокупность некоторого количества различных устройств, заключённых в одном корпусе, работой которых управляет одно главное устройство. Кроме этого, контроллер имеет память программ и память данных.
Главное устройство называется ядром (оно тоже состоит из разных частей: АЛУ, детектор инструкций, стек и т.д., но нам для программирования это пока не важно). Главным оно является потому, что только оно может читать зашитые в память программ элементарные команды и, в зависимости от этих команд, раздавать указания остальным устройствам, что нужно делать.
Одним из важнейших компонентов ядра является АЛУ — арифметико-логическое устройство. В микроконтроллерах PIC оно имеет один рабочий регистр W и может выполнять математические и логические операции с любым регистром памяти данных. То, что АЛУ может работать с любым регистром памяти данных — очень важно, в дальнейшем будет рассказано почему.
Все остальные устройства — это периферийные модули. Непосредственно друг с другом они не взаимодействуют и предназначены для выполнения каких-либо конкретных задач. Например, контроллер PIC16F628A имеет такой набор периферийных модулей: 2 порта ввода-вывода (по 8 независимых цифровых каналов), модуль аналоговых компараторов (2 компаратора), 3 таймера, модуль сравнения/захвата/ШИМ и модуль USART.
Разные контроллеры могут отличаться набором периферийных модулей (соответственно, могут решать разные задачи), но все контроллеры одной серии имеют одно и тоже ядро.
Память контроллера делится на память программ и память данных.
Память программ в контроллерах с буквой F — флешовая, соответственно, она может быть достаточно большое количество раз перезаписана. Здесь основным интересным фактом является то, что размер этой памяти не кратен 8-ми битам, как обычно, а имеет разрядность 14 бит. Такой размер в данном случае называется словом. Все команды контроллера 14-ти разрядные, то есть занимают одно слово памяти программ. Доступ к памяти программ осуществляется по отдельной 14-ти разрядной шине.
Те, кто писал программы для компьютера могут запутаться, т.к. в компьютере слово — это 16 бит, так что будьте внимательны. Когда говорят, что объём памяти программ, например, PIC16F628A равен 1 Килобайту, то это не означает, что он равен 1024 байта по 8 бит. На самом деле он равен 1024-м словам по 14 бит.
Память данных, в свою очередь, делится на EEPROM и ОЗУ.
EEPROM — это энергонезависимая память, которая может использоваться для хранения любой пользовательской информации. Ячейки этой памяти имеют стандартный размер — 8 бит. Тут всё понятно.
ОЗУ — это оперативная память, которая используется только во время выполнения программы. При отключении питания, информация, хранившаяся в этой памяти, пропадает. Эта память, так же как и EEPROM, 8-ми битная. На этом типе памяти давайте остановимся поподробнее:
ОЗУ представляет собой набор регистров, разделённый на блоки по 128 байт, называемые банками. В разных контроллерах может быть разное количество банков (например, в PIC12 их 2, а в PIC16 — 4).
В каждом банке по первым 32-м адресам (с 0000h по 0020h) расположены служебные регистры. Их называют регистрами специального назначения (SFR — special function register). Через эти регистры, собственно, и осуществляется управление работой всех составных частей контроллера (управление различными функциями как самого ядра, так и периферийных модулей).
Каждому устройству выделен один или несколько регистров специального назначения. Увидев то или иное сочетание битов, выставленное в соответствующем регистре ядром (помните, АЛУ может оперировать с любым регистром), устройство понимает, что ему нужно делать. Таким же образом, изменяя специальные биты в другом своём регистре, устройство докладывает о результатах своей работы.
То есть, то, какие биты и в каком регистре специального назначения нужно установить для получения желаемого результата (включение прерываний, установка высокого или низкого уровня на одном из входов и т.д.), определяет программист — пишет в программе команды, которые устанавливают или сбрасывают нужные биты в соответствующем регистре специального назначения. А непосредственно выполняет эти команды (непосредственно устанавливает нужные биты в нужных регистрах) — ядро контроллера с помощью АЛУ.
При обращении к регистрам используется не абсолютный адрес ячейки памяти, а смещение относительно начального адреса того банка, в котором этот регистр находится. Если регистр находится в нулевом банке, то это смещение будет совпадать с абсолютным адресом, но если регистр находится в любом другом банке, то такого совпадения не будет. Для того, чтобы определить смещение относительно начала банка — нужно от абсолютного адреса регистра отнять адрес начала банка.
Например, регистр TRISA расположен по адресу 85h. Этот адрес находится в первом банке — адрес начала банка 80h. То есть, для обращения к этому регистру в программе нужно сначала выбрать первый банк, а потом обращаться к регистру по адресу 85h-80h=05h.
Выбор банка, так же, как и любое другое управление, заключается в установке в специальном регистре нужных битов. В контроллере PIC16F628A текущий выбранный банк определяется сочетанием битов RP1, RP2 в регистре STATUS.
Некоторые регистры имеют сквозную адресацию и доступны из всех банков (например, регистр STATUS доступен по смещению 03h в любом банке).
Кроме регистров специального назначения, существуют ещё регистры общего назначения — это просто пустые ячейки памяти, которые могут использоваться программистом для хранения в оперативной памяти какой-то пользовательской информации (например, в них можно хранить значения каких-то переменных).
Полный список всех регистров (с адресами и банками, в которых они расположены) называется картой памяти.
Карта памяти, описание всех регистров специального назначения и порядок работы с ними, а также описание всех поддерживаемых ядром инструкций приводятся в документации на контроллер.
- Часть 1. Необходимые инструменты и программы. Основы MPLAB
- Часть 2. Что такое микроконтроллер и как с ним работать
- Часть 3. Структура программы на ассемблере
- Часть 4. Разработка рабочей части программы. Алгоритмы
- Часть 5. Ассемблер. Организация циклов и ветвлений
- Часть 6. Как перевести контроллер в режим программирования и залить в него прошивку
radiohlam.ru