В предыдущей моей статье про программатор spi flash и i2c eeprom из arduino после её публикации самый первый вопрос-комментарий был "программирует ли он PIC-и?". Вопрос, конечно, от невнимательного читателя, но он лишний раз подтвердил, что, хоть микроконтроллеры PIC довольно старые, но до сих пор ещё пользуются большим интересом у радиолюбителей, так как за долгое время было разработано огромное количество устройств на их базе. Но вот прошивать эти микроконтроллеры - то ещё приключение. Как известно для PIC-ов есть множество различных программаторов: простейшие, типа несколько проводков для LPT или COM портов (типа JDM и других), USB программаторы (PICKIT1,2,3 и их самодельные клоны). У обоих видов есть свои плюсы и минусы: первые - очень просты в сборке, но требуют наличия соответствующих портов, которые не всегда есть в современных ПК, а тем более в ноутбуках. Вторые - очень удобно использовать, так как они подключаются по USB, их можно подключать к любому современному и не очень ПК/ноутбуку, но! у них тоже есть весомый недостаток - они не очень дешёвые (даже на известном китайском маркетплейсе PICKIT2 стоит порядка 15-20$, а микроконтроллер PIC18F2550 для сборки самодельного PICKIT2 порядка 10$ и то не факт, что не нарвётесь на подделку/перемаркировку/горелку). Не каждый начинающий и даже более опытный радиолюбитель захочет покупать такой программатор, если ему он может пригодиться раз-два в год.
Так вот, после того самого комментария у меня возник спортивный интерес, смогу ли я сделать свой программатор для PIC-ов? Тем более, ранее я уже пытался "бороться" с этими микроконтроллерами. И скажу честно, у меня в первый раз не получилось ничего, от слова "совсем". Даже ID PIC16F73 не смог прочитать. Но уже тогда я понял, что эта задача - крайне сложная. Даже не из-за моего неудачного опыта. Просто я почитал несколько "Programming datasheet" на разные линейки PIC-ов и был просто в ужасе: оказалось что у этих "камней" куча подсемейств, состоящих от 1-2 представителей до нескольких десятков. И таких подсемейств - просто огромное количество. А самое интересное, что все они программируются по разному: у некоторых всего 6-8 команд, а в некоторые вообще нужно пихать ассемблерные коды через программатор! Единственное, что их объединяет - это название пинов для подключения программатора (PGC, PGD, PGM и MCLR). На этом сходства заканчиваются. Даже, например, PIC16F84 и PIC16F84A или PIC16F628 и PIC16F628A в плане программирования - это совсем разные "камни"! Но и это ещё не всё!!! Вторая, не менее важная проблема - это HEX-файлы для PIC-ов. У них тоже нет никакого стандарта! В одном единственном файле располагается CODE сегмент (т.е. основная программа), DATA сегмент (т.е. EEPROM) и слова конфигурации. А самое смешное, что у каждого подсемейства все эти сегменты располагаются по разным адресам смещения и количество конфигурационных слов - тоже у всех разное. Наверное, после этого до меня дошло, почему PICKIT такой дорогой? Это ж у программиста может съехать крыша в попытках хоть как-то стандартизовать алгоритмы программирования такого "приятного разнообразия". Представляю, как инженеры Microchip в своё время вели разработку: "А давайте, следующая линейка будет программироваться не командами, а ассемблерными кодами ядра и желательно развёрнутыми задом-наперёд... А что? Нечего программистам расслабляться".
Но вот, прошло некоторое время, у меня появились свои наработки в плане программного обеспечения и схемотехники, и я решил попробовать снова побороть PIC-и. Накидал в голове приблизительный алгоритм, как можно более-менее унифицировать софт. А также продумал "железную" часть программатора. С описания которой я, пожалуй, и начну.
За основу программатора я решил взять пятивольтовый микроконтроллер, так как логические уровни большинства PIC-ов именно 0 - 5 вольт (не считая PIC24, dsPIC, но о них я даже и думать не хотел). Я мог взять что-то очень дешёвое, типа STC8, но решил, что они не очень популярны и сделал свой выбор в пользу AVR. Тем более, что они используются в известнейших платах arduino, которые найдутся в загашниках почти любого радиолюбителя, да и стоят не очень дорого (относительно). Но одной лишь платы arduino или микроконтроллер AVR для программирования PIC-ов будет недостаточно. Наверное, многие знают, что микроконтроллеры PIC (большинство PIC16, PIC18) используют высоковольтное программирование, т.е. для входа в режим программирования необходимо подавать на определённый пин (MCLR) повышенное напряжение 12-13 вольт. Нужен дополнительный источник повышенного напряжения и схема управления подачей этого самого напряжения. Так вот, в первом варианте схемы я решил использовать повышающий преобразователь напряжения на микросхеме MC34063A, чтобы питать программатор исключительно от USB. И он заработал!!! Но радость "победы" длилась недолго. Программатор читал прошивку, читал ID, конфигурационные биты, но упорно отказывался стирать/записывать. В Programming datasheet я увидел, что операции записи/стирания требуют напряжения питания VDD 4,5-5,5 вольт. Я решил померять напряжение VDD во время процесса чтения и получил огромную просадку до 3,8 вольта. Естественно, при такой просадке о записи/стирании и речи идти не могло. Поэтому, я решил отказаться от идеи с преобразователем напряжения в пользу дополнительного источника питания 12 вольт. И это дало результаты - с внешним источником 12 вольт процессы стирания и записи пошли! В итоге уже второй вариант схемы - стал окончательным. Схема получилась очень простая. Я не стал использовать буферных элементов на дискретной логике, а сделал ключи управления напряжениями VPP и VDD (12в и 5в) на транзисторных ключах (2 каскада каждый). Также в схеме используется линейный стабилизатор на 5 вольт (7805). Стабилизацию по 12 вольтам я решил не ставить, так как боялся, что некоторые PIC-и могут потребовать более высокое напряжение (12,5-13,5 вольт) и с установленным стабилизатором типа 7812 поменять напряжение VPP уже не получится. В итоге, получилось не очень сложная схема. Под силу даже новичку с советским паяльником толщиной с палец:
Выглядит как-то так (все детали в SMD исполнении, расположены на нижней стороне платы):
На фото - первый вариант платы, я его показываю исключительно для наглядности, как можно скомпоновать плату-шилд для arduino nano.
Окончательный вариант своего программатора я сделал в виде отдельной платки с ATmega328P. Схема её следующая:
Я не рисовал ключи управления напряжениями на этой схеме, иначе бы она заняла пол экрана. Здесь изображена схема подключения атмеги к USB-UART конвертеру и ключам управления напряжениями. Моя окончательная плата программатора выглядит следующим образом (сразу извиняюсь за остатки флюса и ваты, которой я пытался отмыть флюс):
Платка получилась достаточно компактная, всего 44х47 мм, это всё благодаря миниатюрной микросхеме USB-UART преобразователя CH340E, которая к тому же не требует подключения кварцевого резонатора и атмеге в корпусе TQFP32, которая тоже занимает места не очень много. Линейный стабилизатор и вся мелочёвка также в SMD исполнении. Кстати, транзисторы я использовал Q1,Q2 - MMBT3904 (маркировка корпуса 1AM), Q3,Q4 - BC856 (маркировка корпуса 3B). Рисунок своей печатной платы я выложу в конце статьи. Хотя, плату каждый может сделать под имеющиеся компоненты. Кстати, при наличии у USB-UART преобразователя сигнала DTR, его необходимо повесить на пин RESET атмеги через конденсатор 0,1uF, чтобы работал автоматический сброс при программировании атмеги через UART bootloader. Как раз у CH340E этого сигнала нет и приходится сбрасывать атмегу вручную кнопкой.
Теперь поговорим о софте. Программу для ПК я традиционно написал в среде MS Visual Studio на C#. Внешний вид первой версии программы такой:
Интерфейс программы, думаю, не окончательный, потому что я не в силах предугадать, какие ещё параметры могут быть у каких либо семейств PIC и что надо добавить/убавить. Будет видно потом, в ходе добавления новых МК.
Как видите, есть два больших текстовых поля с данными CODE (верхнее) и DATA (нижнее) сегментов прошивки. Семь текстовых полей для слов конфигурации (брал за максимум PIC18F4550). Поле выбора модели PIC. Куча кнопок с интуитивно понятными по названиям функциями. В нижнем правом углу - текстовое поле для вывода информации. Три поля "Oscal" делал про запас, они пока никак не задействованы, но знаю что в 8-ногих пиках есть байты калибровки RC-генератора, которые можно случайно затереть, поэтому - могут пригодиться.
Работать с программой очень просто: подключаем программатор к USB. Должен появиться COM порт. В верхнем правом углу программы выбираем COM, на котором висит наш программатор (если программатор был подключен после запуска программы, то надо нажать кнопку "Scan" для получения списка доступных портов) и нажимаем кнопку "Open", если всё правильно, она должна стать зелёной и появится соответствующее сообщение в консоли внизу справа. Чтобы проверить, отзывается ли программатор, нажимаем кнопку "Check", в консоли должно появиться сообщение "Программатор подключен". Дальше надо выбрать модель PIC в окошке "Device". И только после этого можно читать, писать, стирать. Есть некоторые особенности работы с конфигурационными словами: при загрузке HEX-a они автоматически вставляются в соответствующие окошки (Config1 - Config7), при нажатии кнопки "Write" они будут записаны автоматом после CODE и DATA сегментов, либо при нажатии кнопки "WR Cfg" они запишутся отдельно. Но значение Config-ов пишутся не напрямую из HEX-а, а именно из этих окошек, то есть если после открытия HEX-файла переписать свои корректные значения в эти окошки, то будут записаны именно они.
Так как программа очень сырая, многие исключения в ней не обрабатываются, то есть, если сделать что-то неверно, программа вылетит с ошибкой. Например, если выбрать модель PIC и открыть HEX для совершенно другой модели. Или вписать некорректные значения в окошки Config (кириллицу или не 16-ричные знаки не "0-9,A-F").
Что касается скорости работы программатора, то она - вполне достойная. Конечно, скорость чтения/записи зависит от модели PIC. Но если взять PIC18F4550 как наиболее "жирный" из уже поддерживаемых, то скорость чтения около 2 Килобайт в секунду, запись, естественно, чуть медленнее. При 32 Килобайтах CODE сегмента время чтения\записи не напрягает.
Программу я старался написать таким образом, чтобы она была универсальна для любого семейства PIC, и не требовала никаких изменений при добавлении поддержки новых моделей. Для добавления новых устройств используется файл настроек ("pic.xml"), который находится в папке с программой. В нём содержатся однотипные структуры с необходимыми параметрами микроконтроллера, которые программа использует в первую очередь для разбора HEX-файла. Таким образом работа по добавлению новых моделей PIC ведётся в файле настроек и в большей степени в прошивке атмеги. Вид файла настройки следующий:
<name model="PIC16F628A">
<id>0x1060</id>
<type>2</type>
<f_size>4096</f_size>
<f_psize>1</f_psize>
<ee_size>128</ee_size>
<f_start>0</f_start>
<ee_start>002100</ee_start>
<ee_type>0</ee_type>
<conf1>002007</conf1>
<conf2>none</conf2>
<conf3>none</conf3>
<conf4>none</conf4>
<conf5>none</conf5>
<conf6>none</conf6>
<conf7>none</conf7>
<oscal1>none</oscal1>
<oscal2>none</oscal2>
<oscal3>none</oscal3>
<delay>4</delay>
<word>3FFF</word>
</name>
Как видите, параметров много, хотя если сравнить с подобным файлом настроек программатора K150, то и не особо.
На данный момент в программе не реализованы функция сохранения считанного в HEX-файл, работа с oscal байтами калибровки. По поводу сохранения HEX-а я уже приблизительно себе представляю как это сделать. Oscal пока даже не в ближайшей перспективе.
Что касается прошивки атмеги. Никаких скетчей для arduino вы не увидите, вопреки названию статьи. Код написан на Си. Для написания кода я использовал среду Eclipse с плагином для AVR (использует AVR-GCC, точно такой же как и Atmel studio). Поэтому все *.h и *.c файлы проекта могут быть спокойно перенесены в Atmel studio без изменений. Также можно с минимальными изменениями перенести код на другие модели AVR с бОльшим объёмом флеш памяти (например, ATMEGA64, ATMEGA128 и др.). Из специфических функций там только USART (настроен на скорость 57600, передача и приём плюс прерывание по приёму байта). И то модуль USART у большинства атмег почти одинаковый, достаточно подправить названия регистров (например UDR на UDR0, UCSR0A на UCSRA и т.д.). Все остальные функции - реализованы с помощью "ногодрыга". Настройка пинов PGD,PGC,PGM,VPP и VDD реализована с помощью макросов:
#define PGD_PIN 1 //D9
#define PGD_PORT PORTB
#define PGD_DDR DDRB
#define PGD_IDR PINB
#define PGC_PIN 2 //D10
#define PGC_PORT PORTB
#define PGC_DDR DDRB
#define PGM_PIN 0 //A0
#define PGM_PORT PORTC
#define PGM_DDR DDRC
#define VDD_PIN 7 //D7
#define VDD_PORT PORTD
#define VDD_DDR DDRD
#define VPP_PIN 6 //D6
#define VPP_PORT PORTD
#define VPP_DDR DDRD
#define PGD_HIGH PGD_PORT |= (1 << PGD_PIN);
#define PGC_HIGH PGC_PORT |= (1 << PGC_PIN);
#define PGM_HIGH PGM_PORT |= (1 << PGM_PIN);
#define VDD_HIGH VDD_PORT |= (1 << VDD_PIN);
#define VPP_HIGH VPP_PORT |= (1 << VPP_PIN);
#define PGD_LOW PGD_PORT &= ~(1 << PGD_PIN);
#define PGC_LOW PGC_PORT &= ~(1 << PGC_PIN);
#define PGM_LOW PGM_PORT &= ~(1 << PGM_PIN);
#define VDD_LOW VDD_PORT &= ~(1 << VDD_PIN);
#define VPP_LOW VPP_PORT &= ~(1 << VPP_PIN);
Поэтому переназначить ножки микроконтроллера на любые другие не представляет особого труда. Достаточно переписать номер пина и букву порта.
Прошить сам программатор HEX-файлом можно двумя способами: любым программатором для AVR, если это чистая атмега или с помощью программ для загрузки HEX-а в arduino, таких как XLoader, ArduinoUploader и других (можно найти, например, тут. Это не реклама стороннего сайта!).
На данный момент прошивка занимает 5 Килобайт с небольшим из 30 доступных в ATMEGA328Р (2 Кб занимает bootloader arduino). Так что места ещё навалом, можно добавить поддержку многих семейств.
Теперь - самое главное. Поддержку каких камней удалось добавить? Скажу сразу, пока - не густо. Так как пока что от начала разработки до момента написания статьи прошло около недели, и то я вёл разработку в свободное время, на данный момент добавлена поддержка и проверена работа (с реальным устройством на данном МК) PIC16F628A (в его подсемействе есть ещё два камня 627A и 648A). PIC16F73 (проверена работа методом сравнения прочитанного и записанного с референсным JDM программатором), у этого "камня" есть ещё три одногрупника (F74, F76, F77). Также добавлена поддержка и проверена работа с PIC18F4550, добавлен PIC18F2550 (так как это в плане программирования одно и то же). Единственное, не смог победить чтение ID у этого семейства, возможно, мой экземпляр работает некорректно. У последних двух "камней" в одногрупниках - несколько десятков МК, поддержку которых легко сделать всего лишь правкой конфигурационного файла без изменения прошивки атмеги. Должны работать, но мне пока не на чем проверить.
В ближайших планах добавить поддержку таких старичков как PIC16F84A и его одногрупников (так как он у меня есть для тестов), PIC16F87X. Дальнейшая поддержка будет зависеть от интереса к устройству и, возможно, помощи в тестировании программатора. Так как мне одному не под силу и не по карману сделать это самому (покупать разнообразные PIC-и только для тестов).
На этом пока всё. Спасибо за внимание. Адекватная критика в комментариях приветствуется.
Скачать список элементов (PDF)
Прикрепленные файлы:
- BRD.rar (38 Кб)
- PIC_PROG_FW.rar (69 Кб)
- PIC_PROG_SW.rar (13 Кб)
- SCH.rar (127 Кб)
Автор: AndrejChoo