Эта заметка посвещена прошивке микроконтроллеров (МК) марки PIC. Тем радиолюбителям, которые с этим ранее не сталкивались, может показаться, что это очень сложная задача. На самом деле здесь всё просто. Нам понадобится программатор PicKit3, программа для его управления, микроконтроллер и, собственно, сама прошивка — программа в формате hex.
Программатор лучше приобретать с универсальной панелькой (Адаптером), как показано на первых двух фото. Эта связка будет Вам служить долго и может прошивать практически любые PIC-контроллеры и даже внешнюю память. Для этого программатор и адаптер необходимо соединить так, как показано на Фото 1 и Фото 2. Сам контроллер устанавливается в адаптер так, показано на Фото 3. На этом же фото показана установка перемычек J1, J2 и J3 для 14-ти выводных PIC. Установку же перемычек для МК с другим числом выводов можно посмотреть в работе [1]. Эту конструкцию необходимо подключить к компьютеру через USB-разъём, который идёт в комплекте с PicKit3.
![]() |
![]() |
![]() |
Фото 1 | Фото 2 | Фото 3 |
Программу для управления PicKit3 лучше всего брать с официального сайта Microchip — она легко скачивается и устанавливается на компьютер. Её внешний вид изображен на следующем фото:
4. Как написать программу для включения светодиодов, подключенных к PIC16F84A (Урок 4. Теория)
Все вышеописанные действия нужно выполнить один раз, после чего в Ваших руках появится довольно мощный комплекс для прошивки МК. Дальнейшие действия нужно выполнять при каждой новой прошивке.
Сначала нужно установить контроллер в адаптер и дать программе самостоятельно определить тип МК. Для этого достаточно выбрать в меню Tools — Check Communication. Впрочем, эту проверку можо каждый раз и не делать — только при включении. Далее, необходимо убедиться, что напряжение прошивки установлено 5В. Этот параметр контролируется в окошке VDD PICkit3 (Target Power) и, как правило, устанавливается автоматически.
Для начала процедуры нужно выбрать файл прошивки: File — Import Hex, после чего нажать кнопку Write на панели программы. Эта команда начнёт запись в наш МК, а после её окончания засветит зелёным цветом окошко над этой кнопкой. Обычно это занимает несколько секунд. Всё — контроллер прошит и готов к работе!
Не стоит бояться неправильно установить МК в адаптер. В PICkit3 реализованы все возможные защиты и спалить контроллер не получится 🙂
-
Универсальный Адаптер для Программирования PIC-контроллеров
Источник: gorchilin.com
Учимся писать прошивки.
Как написать программу для пик контроллера
Напишем простенькую программу для самого распространенного микроконтроллера фирмы Microchip PIC16F877A. Почему именно PIC16F877A, а не какой нибудь другой? Объясняю. По своему внутреннему устройству этот контроллер сочетает в себе все предыдущие модели, у него «на борту» есть все модули, которые встариваются в другие контроллеры 8-ми битного семейства начиная от PIC10 и заканчивая PIC16.
Кроме этого, названия регистров у него такие же как и у других, и на него можно найти руссифицированное описание. Для начинающих это довольно хорошая помощь в освоении программирования микроконтроллеров. Плюс, мне он нравится большим количеством выводов, можно одключить много всяких компонентов и модулей.
Русскую версию даташита вы всегда можете скачать на русском сайте www.microhip.ru, английскую соответственно на анлийском — www.microhip.com. Скачали? Держите его всегда под рукой. Даташит — это описание работы и внутреннего устройства микроконтроллера и если его внимательно читать, то можно избежать ошибок, и неясностей в работе программы. Откроем созданный ранее проект и напечатаем следующий код:
#include
// Подключение заголовочного файла
__CONFIG(0x03F72); // Установки контроллера
void main(void) // Главная функция
while(1) // Главный цикл
Вообще-то, я не очень люблю ставить комментарии, что конечно является дурным тоном в программировании, но это потому что при написании кода ты увлечен, весь в процессе, в голове куча мыслей и отвлекшись можно просто потерять основную нить. Для этой статьи я никуда не торопился, а потому все же сделал кое какие записи. Попробуем разобраться.
#include
// Подключение заголовочного файла
Те кто хорошо знаком с синтаксисом языка Си знают что #include это директива компилятора, говорящая ему о необходимости подключения библиотечного файла. Таким файлом у нас является pic.h, он расположен в директории куда был установлен Hi-tech в папке Include. Вообще там куча подобных файлов, но мы указываем главный из них, а дальше все делает программа. По указанному, при создании проекта, названию контроллера MPLAB определяет где и в каком дальше файле искать полное описания и названия его регистров.
__CONFIG(0x03F72); // Установки контроллера
Во второй строке записан так называемый макрос компилятора Hi-tech, в традиционном синтаксисе Си такой команды нет. С помощью нее мы настраиваем некоторые модули контроллера, сами настройки записываются в виде HEX-значения в круглых скобках. Что конкретно означает запись 0x03F72 и как ее получить можно посмотреть в строке «Configuration Bits. » меню «Configure».
Если у вас стоит галочка Configuration Bits set in code, то все необходимые настройки наш компилятор берет из макроса __CONFIG. Если эту галочку снять то будет доступно редактирование полей. При изменении значения поля будет меняться и конечная сумма в столбце Value, ее то мы как раз и запишем в параметр нашего макроса. Что же все таки написано в этой таблице.
FOSC — Oscillator Selection bits — Устанавливает тип тактового генератора нашего микроконтоллера, значение HS означает что в нашем случае будет использоваться высокочастотный кварцевый генератор;
WDTE — Watchdog Timer Enable bit — Запускает сторожевой таймер служащий, например, для предотвращения зависания микроконтроллера. Пока лучше его отключить, ставим значение Disabled;
PWRTE — Power-up Timer Enable bit — Активирует таймер удерживающий микроконтроллер в состоянии сброса, до тех пор пока напряжение питания не достигнет необходимого уровня. Для предотвращения ложных запусков ставим его в занчение Enabled;
BOREN — Brown-out Reset Enable bit — Активирует детектор пониженного напряжения. Если питающее напряжение снижается ниже определнного минимума то микроконтроллер перезагружается. Тоже полезная опция, так же ставим значение Enabled;
LVP — Low-Voltage (Single-Supply) In-Circuit Serial Programming Enable bit — Активирует возможность низковольтного внутрисхемного программирования. Нам пока это не надо так что ставим Disabled;
CPD — Data EEPROM Memory Code Protection bit — Установка защиты от считывания кода записанного в память контроллера. Ставим Off, нам эта опция пока не нужна;
WRT — Flash Program Memory Write Enable bits — Установка защиты от записи программы во Flash память. Устанавливаем защиту в Off;
CP — Flash Program Memory Code Protection bit — Установка защиты от считывания кода записанного во Flash память. Это нам тоже ни к чему, снова Off.
Более подробно работу этих модулей мы будем разбирать позже, а пока во избежание программных ошибок устанавливайте значение перечисленных пунктов как показано на рисунке. У вас должно получиться такое же значение как и в коде программы.
void main(void) // Главная функция
С настройкой покончено. В следующей строке у нас уже знакомая команда, это главная функция программы, так сказать тело программы. Запись void main(void) показывает что данная функция не имеет определенного типа и не возвращает никаких значений. Далее у нас идет открывающая скобка, после которой мы можем написать все что задумали. Я написал следующее:
while(1) // Главный цикл
В программировании, с помощью такой записи создают бесконечный цикл, который в данном случае ничего не выполняет, заставляя контроллер как бы топтаться на одном месте. В принципе условие цикла можно записать вот так (1=1), но это будет тоже самое.
Итак. Текст программы мы написали, сохранили на всякий случай, теперь компилируем. На панели инструментов нажимаем кнопку «Build All» и ждем результатов.
Если все прошло успешно то в окне «Output» должно появиться вот такое сообщение, заканчивающееся строкой BUILD SUCCEEDED, а в папке с проектом — несколько новых файлов. Из которых нас в первую очередь интересует файл с расширением «hex». Это и есть наш конечный результат, то ради чего все затевалось — прошивка, ее мы записываем в память микроконтроллера и получаем готовое hand made устройство.
Но программу, которая тупо крутится на одном месте ничего не делая врятли можно назвать громадным достижением, поэтому поехали дальше. Открываем даташит и ищем раздел «Порты ввода/вывода» (в русскоязычном варианте) или I/O Ports (в англоязычном). В первую очередь нас интересуют регистры PORTB и TRISB.
PORTB — 8-ми битный двунаправленный порт ввода/вывода. Порт это, по сути, совокупность выводов (ног), который является основным средством связи микроконтроллера с внешним миром. Вся информация, которую микроконтроллер передает или принимает проходит через порт.
TRISB — регистр управления портом, определяет направление каналов порта B. Если в биты регистра TRISB записать «1» то порт B будет настроен как вход. Запись в TRISB — «0» переведет порт B в режим выхода. В принципе все просто. Почему был взят PORTB, а не скажем PORTD или PORTA?
От остальных PORTB, если вы внимательно читали даташит, отличается наличием встроенных защитных диодов и подтягивающих резисторов, тоесть сжечь его по неосторожности достаточно сложно, если не сказать — невозможно. Я вообще все мощные элементы (светодиоды, транзисторы и т.д.) стараюсь в первую очередь разместить на этом порту, после него уже идет очередь порта D, порт C использую для связи с другими контроллерами или компьютером, а порт A для каких либо измерений. Продолжим. Немного модифицируем нашу программу, добавим следующие строки перед while(1):
TRISB = 0b00000000; // Перевод порта в режим выхода
PORTB = 0b00000000; // Присваивание начального значения
С помощью такой вот записи мы перевели все биты (ноги) порта B в режим вывода и принудительно обнулили, записав в PORTB значение по умолчанию. Если с первой операцией все понятно то зачем нужна вторая операция?! После сброса (перезагрузки) значение, которое принимает регистр PORTB может быть каким угодно, поэтому его необходимо обнулить во избежание ложных срабатываний или сразу вывести в начальное положение. Это не является прописной истиной, поэтому данную операцию можно пропустить, но я всегда так делаю и вам советую.
К тому что у нас получилось, в тело нашего бесконечного цикла, сразу добавим еще одну строчку:
PORTB++; // Увеличение текущего значения порта
Данная запись увеличивает значение записанное в PORTB на единицу и эквивалентна записи PORTB=PORTB+1. Снова нажимаем кнопку «Build All» и ждем успешного завершения.
Теперь хорошо было бы посмотреть как это все работает, поэтому запускаем PROTEUS (его мы устанавливали в прошлой статье).
И собираем схему как изображено на картинке.
1. Нажимаем кнопку библиотека элементов — и в открывшемся окне, в списке Category ищем строку Microprocessor ICs, в списке Sub-Category — PIC16 Family, в таблице Results — PIC16F877A.
Нажимаем «OK», после чего возвращаемся в главное окно и кликаем левой клавишей мыши на свободном рабочем поле, элемент вставлен.
2. Тоже самое проделываем для следующих элементов:
Конденсатор. Category — Capacitors, Sub-category — Ceramic Disc, Results — CERAMIC22P;
Кварцевый генератор. Category — Miscellaneous, Sub-category — All Sub-category, Results — CRISTAL;
Резистор.
Category — Resistors, Sub-category — 0.6W Metal Film, Results — MINRES100R;
Светодиод. Category — Optoelectronics, Sub-category — LEDs, Results — LED-RED (GREEN, BLUE, любого понравившегося цвета);
Кнопка. Category — Switches
Попутно все компоненты добавляются в панель списка элементов «DEVICES», поэтому повторно открывать библиотеку для одинаковых деталей нет необходимости, достаточно выделить нужный в списке и кликнуть на свободном рабочем поле.
3. На боковой панели нажимаем кнопку терминальные метки — . В списке «TERMINALS» нам потребуются элементы POWER и GROUND, выбираем каждый и кликаем на свободном рабочем поле.
4. На той же панели нажимаем виртуальные приборы — . В списке INSTRUMENTS выделяем OSCILLOSCOPE и вставляем его в проект.
5. Включаем кнопку стрелка — и расставляем все элементы как нам нужно, просто перетаскивая их мышью.
6. Редактируем параметры (номиналы) конденсаторов, резисторов и т.д. в соответствии со схемой. Щелкаем левой кнопкой мыши на нужном элементе несколько раз, в открывшемся окне редактирования ищем строки: Capacitance (для конденсаторов), Resistance (для резисторов), Frequency (для генераторов), String (для питания). Номиналы конденсаторов — 22p, резисторов — 100R и 10K, генераторов — 20MHz, питание — +5V.
7. Соединяем все элементы между собой, для этого достаточно подвести курсор к контакту детали, кликнуть по нему мышью, провести линию к контакту другой детали затем снова кликнуть мышью.
8. Открываем свойства микроконтроллера PIC16F877A. В строке Processor Clock Frequency пишем 20MHz, а в строке Programm File — путь к HEX-файлу нашей программы. Он находится в директории куда мы сохраняли проект MPLABа. После всех операций нажимаем «OK». Сохраняем схему, можно в той же папке что и исходник программы.
9. Нажимаем запуск симуляции «Play». У меня получилось следующее:
Теперь можно сходить и попить чайку, в следующей статье продолжим.
Источник: anubis-system.ucoz.com
Программирование pic микроконтроллеров. USB и CAN
Я плавно переделываю уроки на использование пакета MPLABX и компилятора XC8. Так как старые уже не поддерживается. Тем не менее, вы можете найти старую статью здесь. Так же точно можете скачать компилятор C18 и использовать его. XC8 несколько отличается
Итак, нам понадобится компилятор XC8. Его можно скачать с официального сайта. ссылка, либо же с зеркала зеркало
Итак, создаем проект в MPLABX
Это делается примерно так же как во втором уроке, только выбираем компилятор XC8
Сначала запускается функция main(). Идет настройка вывода сигнала через порт А (TRISA=0;) а потом обнуляется этот выход с порта А (PORTA=0); Далее идет бесконечный цикл, в котором мы мигаем лампочкой на порту RA2 и вызываем функцию задержки.
Пока что у вас не скомпилируется этот проект. Потому что в include стоит файл config.h, а мы пока его еще не создали. Там будут конфигурационные биты.
Необходимо их настроить. Для этого идем в Window->PIC memory views->configuration bits
откроется окно, и выставляем там FOSC=INTOSCIO, WDT=OFF, MCLRE=OFF
Щелкаем правой клавишей и Generate Source Code to Output. Эта опция создаст код, необходимый для задачи конфигурационных битов.
Копируем код, создаем файл заголовков config.h и вставляем сгенерированный код в конец файла.
Все обозначений навроде портов и встроенных устройств можно найти в файле p18f2550.h или p18f4550.h, так же всегда вы можете обратиться к ТО на контроллер.
директива #include
подключает заголовки для контроллера
#pragma config — Это опять же выбор конфигурационных битов для контроллера. См урок №2.
Эти настройки у нас хранятся теперь в файле config.h
Если вы будете использовать этот код с бутлоадером. А это намного удобнее, нам необходимо сдвинуть его в памяти программы на 0x1000.
Если в C18 компиляторе для этого была специальная директива, то теперь для этого служит настройка компилятора. Грубо говоря, теперь когда мы пишем код в XС8, компилятор сам знает где должны быть прерывания, как размечена память, и.т.д. Все, что мы можем сделать — это сделать сдвиг.
Итак, чтобы программа корректно работала с бутлоадером, нужно сделать следующее:
File->Project properties
Потом XC8 global options (не XC8 compiler options, специально на это обращаю внимание), и пишем в поле additional options
Это означает, что весь код компилируется со сдвигом в 0x1000
Если вы захотите вставить код ассемблера в файл Си, то вам нужно будет его заключить между директивами
Файлы проекта: ссылка
вторник, 23 декабря 2014 г.
Второй урок. Простой код на ассемблере и устройство вкратце.
В данном тексте приведены ссылки на книги. «название книги»:страница обозначает указатель на определенную страницу книги. «название книги»:Гглава — главу. При этом ТО — сокращение для тех. описания контроллера (Datasheet). Например ТО:15 — 15 страница технического описания. ТО:Г3 — третья глава технического описания |
Эта статья переработана. Существует так же старая версия с оболочкой MPLAB 8 .91 . Прочесть ее можно здесь.
Вот и ладушки, если вы читаете второй урок, то наверное, в первом вы смогли подготовить инструменты. Или и так без меня все умеете. Теперь небольшое отступление для начинающих. За более подробной
информацией, обращайтесь к серьезным книгам, особенно к техническому описанию контроллера.
Итак, что такое контроллер, и как он работает?
Конечно же, это просто черный жучек с ножками. За неимением никаких других членов, он общается с окружающим миром исключительно напряжением на ножках. Что в общем и демонстрировалось в программе в первом уроке. Просто с определенной переодичностью контроллер зажигал
светодиодик.
В расcматриваемых нами контроллерах память разделена. Программа записывается в отдельное пространство, именуемое памятью программы (PROGRAM MEMORY). Переменные и настройки хранятся в памяти данных (DATA MEMORY). Причем, ячейки памяти, выделенные для использования как переменные называются регистрами общего назначения (GENERAL PURPOSE REGISTERS или GPR) и настройки находятся в регистрах специального назначения (SPECIAL FUNCTIONS REGISTERS или SFR). Память данных поделена на 15 блоков и блоки меняются регистром BSR (BLOCK SELECT REGISTER).
Так же существует EEPROM memory — это флеш память, используемая для длительного хранения информации.
Подробнее о памяти контроллера смотри главу 1 ссылка.
Код программы
Для начала мы будем писать на ассемблере.
Если вы написали команду на ассемблере, то это будет ровно одна команда, записанная в контроллер.
Таким образом вы будете отлично знать, что ваш контроллер делает и как. А вот если вы пишете на C, то на каждую строчку, написанную вами могут приходиться сотни команд, выполненных контроллером. Знать-то нужно и то и другое, но ассемблер даст нам понимание того, что и как работает в контроллере.
Ладно, начнем.
Открываем MPLAB X IDE жмем File-> New Project . В открывшемся окне выбираем Microchip Embedded Standalone Project
выбираем семейство контроллер ов advanced 8 bit MRUs и наш контроллер, например pic18f2550
Next, Next.Теперь компилятор предлагает нам выбрать соответствующий набор для разработки. К этому моменту должно быть установлено все необходимое.
Первый урок на ассемблере, поэтому выбираем MPASM. Далее. Задаем имя и прочие свойства. Укажите кодировку с русским. Например. UTF-8.
Иначе ваши комментарии на кириллице не сохранятся.
И вот проект открыт. По началу в нем есть только makefile. Это файл для сборки проекта. Поэтому щелкаем на Source files->new->empty file
после компиляции у нас должен в папке проекта появиться HEX файл. Он находится в папке distdefaultproduction. Его можно и нужно прошить в контроллер. Это та же программа, что и в уроке 1.
На самом деле среда MPLABX умеет работать с программаторами, но у меня PICkit 2 и с ней она работает посредственно, поэтому я прошиваю HEX файл напрямую через PICKIT
Пояснения к коду программы
Начнем потихоньку разбирать что там написано
В самом верху указываем то, какой у нас будет контроллер
#include
Мы их рлдключаем для того. чтобы вместо того, чтобы всегда и везде мы записывали цифрами. мы могли использовать некоторые уже привычные нам обозначения.
напирмер, без подключения заголовков. команда записи в регистр выбора блока (BSR) -строка 16 нашей программы выглядела бы так
MOVWF 0FE0;
так. Еще директива.
list p=18f2550
Она просто говорит
компилятору, какой контроллер будем прошивать.
Дальше уже интереснее. Нам нужно задать управляющее слово. это — настройки контроллера.
Задает их директива CONFIG
По поводу всех настроек контроллера обращаемся так же к техническому описанию. ТО:288
Конфигурационные биты
CONFIG FOSC=INTOSCIO_EC
Эта настройка говорит о том, что мы будем использовать внутренний генератор импульсов. Он — внутри контроллера. Читаем в ТО:25
CONFIG MCLRE = OFF
Здесь мы отключаем сигнал сброса. То есть контроллер будет включаться сразу с подачей на него питания.
CONFIG WDT = OFF
Отключаем сторожевой таймер. Просто. чтобы не «запариваться». Он служит защитой от зависания контроллера. Читаем в ТО:299
Более подробно конфигурационные биты рассмотрены во 2-й главе к этому уроку. ссылка
Тело программы
DELAYCOUNTER EQU 0x00
Эта директива (EQU) ставит в соответствие к DELAYCOUNTER 0x00
То есть мы пишем DELAYCOUNTER, а программа думает «0x00»
Вообще мы будем использовать DELAYCOUNTER как переменную. а 0x00 — просто адрес, где она хранится в общих регистрах.
Кстати. Забыл сказать. 0x00 — это просто число. Так мы записываем числа в 16ричной системе счисления.
то есть 0x6B = 107