3д принтер выдает echo debug info errors
Последнее время я часто печатаю большие модели, время печати которых от суток и более. При этом начали проявляться проблемы с электроснаблежнием. Поскольку проблема повторяется уже во второй раз, хочу закрепить полученный опыт в этой статье на тему того, как можно продолжить печать с того же места после прерывания.
Я использую 3д-принтер Wanhao Duplicator i3 Plus на прошивке Marlin , однако статью постараюсь сделать универсальной, с изложением базовых принципов. Это должно быть применимо и для других FDM принтеров.
Краткая теория
Для начала нужно понимать, из чего состоит и как работает любой станок. В основном это несколько актуаторов по осям (движущих механизмов с электродвигателями) и некоторая электроника и механика для управления рабочим инструментом. Все эти части управляются соотвествующими драйверами, драйвера в свою очередь подключены к контроллеру.
На старых станках в качестве контроллера использовались десктопы с LPT портом, тоесть контроллер фактически был вынесен из станка. Однако сейчас роль контроллера может выполнять даже Arduino Uno с её atmega328 . Это решает ряд проблем при использовании компьютера в качестве контроллера.
Надо понимать что обычно, роль контроллера – всего лишь выполнять команды, такие как сделай перемещение по оси X на столько-то , включи подогрев стола , используй текущую позицию как начало координат и тд. Закономерно, это привело к созданию абстракции (общего протокола численного программного управления (ЧПУ)) – G-code . Программа-slicer (например Cura , Fusion 360 ) создает управляющую программу как раз в формате G-code , однако не стоит забывать, что у G-code есть диалекты, тоесть каждый производитель прошивки, может немного поменять значения тех или иных команд, добавить функционал и тд. Для того, чтобы понимать чтоже самом деле происходит при посылке той или иной команды в станок, нужно:
- Узнать что именно за прошивка у вас установлена.
- Найти описание G-code команд на сайте производителя прошивки или просмотреть исходный код из которого прошивка собрана.
Восстановление печати
В моей версии прошивки Marlin на данный момент не реализована функция сохранения последней команды (youtube) или координат инструмента в энергонезависимую flash-память. А также нет алгоритма который мог бы рассчитать текущую позицию проведя инструмент до концевика. Ввиду этого, после перезагрузки, принтер не знает где у него находиться инструмент и какая должна быть следующая команда. И для того, чтобы исполнить любую операцию (и понимать где она будет сделана), нам нужно взять какую-то точку за начало координат и дальше проводить относительно неё все перемещения.
Поиск системы координат
Нулевая точка отсчета на принтере обуславливается расположением концевиков и, в моём случае, находится на плоскости стола в ближнем левом углу. Если не производить механическую настройку принтера между печатями смещение модели относительно этой точки будет в пределах повторяемости вашего принтера, что вполне удовлетворительно для восстановления печати.
- Аккуратно снять мешающуюся модель, точно запомнив место её нахождения;
- Добавить в G-code операцию паузы (такие используются для смены пластика) или приостановить принтер из его меню после обнуления координат и поднятия инструмента на рабочую высоту;
- Установить вашу модель назад (например с помощью клея);
- Продолжить печать.
Редактирование G-code
Все манипуляции нужно произвести в файле G-code текущей модели вручную. Он представляет из себя текстовый файл, зачастую большого размера. При попытке открытия такого обычным блокнотом у вас могут возникнуть проблемы, тк алгоритм данного редактора не рассчитан на работу с большими файлами и то и дело, то пытается весь файл прочитать, то весь файл записать и тд. Мне очень нравится редактор Visual Studio Code , который советую и вам.
G-code файл (FDM принтера) можно разделить на две части:
Шапка, там где производиться подогрев стола и инструмента, обнуление системы координат. Также зачастую в ней содержатся комментарии.
Повторяющиеся по своему виду наборы комманд для печати слоёв. При использовании, в качестве slicer’a, программы Cura , в G-code все слои любезно прокоментированы.
У нас получается примерно следующий алгоритм:
Смотрим всё что находится в шапке и разбираем, что это означает.
Например, мб такая ситуация, использования датчика уровня стола BLTouch – команда G30 . Её нужно заменить на использование концевика.
В целом убираем всё лишнее кроме подогрева стола и инструмента, обнуления координат. Если вы не используете специальных настроек или датчика уровня стола, в принципе можете не изменять настройки, главное понимать их смысл и чтобы он не противоречил с тем, что вам требуется.
Затем нужно максимально точно измерить высоту напечанной модели.
В моём случае получилось 143.5 мм. Поделив данную высоту на толщину слоя можно получить номер слоя на котором прервалась печать: 143.5 мм / 0.15 мм = 956.[6].
Я всегда округляю величину в меньшую сторону, тк экструдер горячий и не сильно страшно, если он чуть прижмет деталь при печати, в отличии от того, если он начнет класть слой в воздухе.
Теперь следует удалить из файла G-code все операции печати слоёв влоть до 956 (не совсем так).
Имейте ввиду, что нумерация слоёв в Cura идёт с нуля, а не с единицы, поэтому в комментариях ищите 955 слой.
Найти нужный вам слой можно воспользовавшись поиском (ища по слову ;LAYER:955 ). В месте откуда вы хотите удалить код, установить курсор и не меняя его положении прокрутите до начала файла, зажав Shift и установив курсор в новом месте, у вас выделится весь кусок для удаления.
Печать каждого слоя начинается с команды перемещения инструмента на новую высоту, однако в случае, с Cura эта команда содержится в конце предыдущего слоя, соотвественно её нужно тоже сохранить.
Также за этой командой следует несколько других перемещений, я их тоже оставляю тк эта последовательность не мешает и с неё продолжается печать отсутствующего слоя.
Кстати проверить правильно ли вы определили слой можно как раз исходя из значения Z в этой команде.
Как было сказано выше: «Печать каждого слоя обычно начинается с команды перемещения в некоторую точку, с которой начинается печатать слоя». Однако не факт, что алгоритм реализованный в прошивке выполнит не быстрое перемещение (одновременное перемещение по всем осям), а сначала подъём по оси Z, а уже затем по осям XY. В случае быстрого перемещения есть вероятность того, что инструмент, двигаясь с нулевой точки в точку на которой находится продолжение печати, заденет модели.
Поэтому после операции обнуления координат (шапки G-code), я добавляю команду перемещения в точку над уже напечатанными моделями – G0 F0 X0 Y0 Z145 . Подробнее можно прочитать здесь.
PID (ПИД, Пропорционально-интегрально-дифференцирующий регулятор) - регулятор, использующий сумму трех значения входного сигнала (Kp, Ki, Kd) для задания и поддержки температуры стола\хотенда в установленных пределах. Данные значения будут разными в зависимости от используемого железа, наличия обдува, силиконового носка и множества других факторов, поэтому калибровку необходимо производить как после первого запуска принтера, так и после изменения конфигурации хотенда\стола. Так же данную процедуру необходимо проводить при скачкообразных изменениях температуры и большом разбросе при удержании заданного значения.
В прошивку Marlin встроены инструменты для автоматической калибровки PID как для хотенда, так и для стола. Для управления нагревом стола с помощью PID необходимо предварительно активировать в прошивке параметр "PIDTEMPBED" (подробнее в разделе Прошивка -> Стол, данную процедуру необходимо провести перед калибровкой стола и прошить принтер, по умолчанию параметр выключен). Процедуру калибровки желательно проводить на максимально приближенных к печатным условиям, если у вас закрытый корпус - необходимо закрыть дверцу и надеть кожух\колпак, при калибровке хотенда стол должен находиться в непосредственной близости к соплу и обдув должен быть включен на максимум (либо значение, которое вы используете чаще всего). Внимание, во время проведения калибровки вам может показаться, что принтер завис, но это не так - тест довольно длительный и время его проведения зависит от количества установленных повторений.
Полученные значения можно внести в прошивку или сохранить в EEPROM, данная процедура описана в разделе "Прошивка". Также для калибровки хотенда можно воспользоваться готовым GCod'ом который проведет калибровку за вас и сохранит значения в EEPROM. Для этого необходимо скопировать код, описанный ниже (установив в нем свои значения номера экструдера, температуры, а также количество повторений) в текстовый файл, сохранить его с расширением ".gcode" и запустить на исполнение на вашем принтере; результаты тестирования будут автоматически сохранены. После завершения в терминал будут выведены текущие значения EEPROM для проверки, значения PID для экструдера находятся в строке с командой "M301".;HotEnd_PID_calibration.gcode
G28 ;Вернуться в начало координат
G1 Y100.0 X100.0 Z5.00 F1500 ;Переместить хотэнд на координаты X100 Y100 Z5
M106 S255 ; включить обдув модели на 100%
;
M303 E0 S240 C7 U ;E0<номер экструдера> S<температура> C<циклы> U<применить полученные значения>
M106 S0 ; выключить обдув модели
M500 ;Сохранить полученные значения в EEPROM
;
M503 ;Вывести текущие значения EEPROM для проверки
(необходимо активировать параметр PIDTEMPBED в прошивке)
Процедура калибровки PID для стола практически не отличается от калибровки хотенда. При наличии корпуса закройте дверцу и установите крышку принтера, чтобы создать закрытый объем внутри принтера. Обратите внимание, что команды для калибровки стола и хотенда совпадают, отличается лишь параметр номера экструдера, для стола это всегда будет "-1"
Полученные значения также вносятся в прошивку или сохраняются в EEPROM. Для тестирования стола также можно использовать GCode, указанный ниже, сохранив его в файл с расширением ".gcode" и запустив на принтере; он проведет тестирование и автоматически сохранит значения в EEPROM. После завершения в терминал будут выведены текущие значения EEPROM для проверки, значения PID для стола находятся в строке с командой "M304".
;Bed_PID_calibration.gcode
G28 ;Вернуться в начало координат
G1 Y100.0 X100.0 Z5.00 F1500 ;Переместить хотэнд на координаты X100 Y100 Z5
M106 S255 ; включить обдув модели на 100%
;
M303 E-1 S80 C7 U ;E-1<стол> S<температура> C<циклы> U<применить полученные значения>
M106 S0 ; выключить обдув модели
M500 ;Сохранить полученные значения в EEPROM
;
M503 ;Вывести текущие значения EEPROM для проверки
Значения, полученные после PID калибровки, записываются в разделе "PID Settings" в файле "Configuration.h" по порядку (без кавычек):
Для управления нагревом стола через PID необходимо раскомментировать параметр "PIDTEMPBED" (убрать "//"), после чего можно по порядку ввести значения Kp, Ki, Kd в разделе "PID > Bed Temperature Control" в файле "Configuration.h":
После прошивки принтера необходимо стереть EEPROM и загрузить в него значения, установленные нами в прошивке, для этого в терминале принтера нужно ввести две команды по порядку (до точки с запятой):
Терминал принтера
M502 ; Загрузить значения указанные в прошивке
M500 ; Сохранить значения в EEPROM
Не стоит забывать, что значения PID хранятся в энергонезависимой памяти контроллера и после перепрошивки вам необходимо либо восстановить в EEPROM значения, указанные нами в прошивке, либо, если вы не хотите перепрошивать свой принтер, вы можете сохранить значения напрямую в EEPROM, но не забывайте, что при использовании команды "M502" (записать значения из прошивки в EEPROM) придется повторно записать PID значения в EEPROM, так как они будут заменены теми, что указаны в прошивке. Для хранения данных значений предпочтительнее указывать их в прошивке - это убережет вас от множества проблем.
Терминал принтера:
M301 P<Kp value> I<Ki value> D<Kd value> ;Установить значения PID для хотенда
M304 P<Kp bed value> I<Ki bed value> D<Kd bed value> ;Установить значения PID для стола
M500 ; Сохранить значения в EEPROM
Хотэнд (HotEnd) - блок из нагревателя, термодатчика, сопла и корпуса, который отвечает за нагрев пластика
Стол (Bed, HeatBed) - Рабочая поверхность принтера, на которой располагается модель
EEPROM (ПЗУ) - Память контроллера для хранения настроек, которые сохраняются после отключения электроэнерги
M500 - Cохранить текущие значения в EEPROM
M502 - Загрузить значения из прошивки
M503 - Вывести текущие значения EEPROM
M106 S<speed> - Включение обдува модели (0 - выключить)
M301 P<Kp value> I<Ki value> D<Kd value> - Установить значения PID для хотенда
M303 E<номер экструдера(стол -1)> S<температура> C<циклы> U<применить полученные значения> - Автокалибровка PID
M304 P<Kp bed value> I<Ki bed value> D<Kd bed value>- Установить значения PID для стола
Надеюсь данный гайд был полезен, так же прошу прощения за упрощения\упущения и тавтологию данный текст в основном направлен на новичков в 3D печати посему упрощенно по максимуму. Если мой вариант изложения информации будет доступным и понравиться людям продолжу публиковать минигайды относительно 3D печати.
Перед тем как приступить к калибровке необходимо подготовить и загрузить прошивку. От программы, по которой работает принтер, зависит качество и надежность печати.
Как я писал ранее, в качестве внутреннего ПО был выбран проект Marlin. Рассмотрим все необходимые действия для получения работоспособной прошивки для описанной выше конфигурации.
СРЕДА РАЗРАБОТКИ
ИСХОДНИК ПРОШИВКИ
Текущая версия Marlin для работы над прошивкой Marlin-1.1.0-RC8. Для скачивания прошивки в первоисточнике перейдите по ссылке.
ПОДКЛЮЧЕНИЕ КОНТРОЛЛЕРА
НАСТРОЙКА ПРОШИВКИ
ВКЛАДКА Configuration.h
Устанавливаем скорость обмена порта
Я установил достаточно большую скорость обмена. Здесь нужно осознавать, что работоспособность на выбранной скорости определяется не только платой контроллера, но и программой управления. Я использую Repetier Host. Она прекрасно справляется с такой скоростью :).
Выбираем плату контроллера
Этой строкой указываем, что будем использовать силовую плату RAMPS 1.4 с одним экструдером, вентилятором и обогреваемым столом. В комментариях тип платы описан следующим образом:
// RAMPS 1.4 (Power outputs: Hotend, Fan, Bed)
Описание плат управляющего контроллера, поддерживаемые прошивкой, находятся во вкладке Boards.h.
Определяем какой экструдер будем использовать:
В случае, если используется блок питания с программным отключением, прошивка поддерживают возможность управлять таким БП. Для этого необходимо описать тип БП. Поскольку в моем случае управление БП не поддерживается, то:
Так как корпус принтера является открытым, то различные внешние возбудители (сквозняки и пр.) могут сильно влиять на температуру нагревателей. Для более точного поддержания температуры нагревателей я рекомендую использовать PID регулировку. В этом случае потребуется калибровка нагревателей! Она проходит в автоматическом режиме и опишу этот процесс ниже по тексту статьи. На данном этапе достаточно только включить PID регуляторы хотэнда и стола с коэффициентами регулировки по умолчанию.
Более свежие прошивки имеют в своем составе большое количество настроек, повышающих безопасность работы принтера. В частности контроль скорости нарастания температуры, минимальное и максимальное значение температуры на нагревателях и даже длину непрерывной экструзии. Мне кажется, использование данных фишек совсем не повредит. Посему настраиваем минимальную и максимальную температуру нагревателей:
Запрещаем холодную экструзию проволоки. При температуре ниже 170 гр. С подача осуществляться не будет:
Запрещаем непрерывную подачу пластика более 200 мм:
Включаем температурную защиту нагревателей:
Далее переходим к настройке механики. Концевые датчики положения в моей конструкции предполагают начало отсчета координат из минимального значения по всем трем осям:
Для правильной работы оптических концевиков потребуются подтягивающие резисторы:
При использовании оптических концевиков инвертируем значение логического сигнала:
Поскольку выводы, снимающие сигналы с концевых датчиков, поддерживают прерывания включаем обработку событий от концевиков по прерыванию, что существенно сэкономит машинное время:
По концевикам осталось только обозначить направление движения к начальной точке:
Для повышения точности печати, с целью исключения люфта при начале движения и во время остановки двигателей лучше включить захват положения двигателей всех осей и экструдера даже без движения:
Следующие строки определяют направление вращения приводов для движение в нужном направлении. Напоминаю, что значения приведены для конфигурации Mendel Prusa I3.
При использовании экструдера, содержащего редуктор потребуется установить:
Использованные мной драйверы немного слабоваты. По этой причине на большой скорости движения в Z направлении заметны существенные глюки. Значит сразу лучше ограничить скорость при возврате каретки в начальное положение:
Для программного контроля перемещения в рабочем пространстве установим границы перемещения после установки принтером начальной точки:
Для точного перемещения по осям прошивка должна знать на сколько шагов требуется прокрутить двигатель при перемещении на 1мм:
В этой строке прописаны значения осей X, Y, Z, E (экструдера). Все значения, кроме E вполне совпадают с расчетными величинами (по крайней мере у меня). К значению Е вернемся позже. Теорию можно прочесть на форуме RepRap.
Далее ограничиваем ускорения для перемещений по всем осям. Я ограничил все значения, кроме ускорения вращения экструдера на половину от значений по умолчанию:
Для перехода на русский язык в меню управления принтером:
и SD карты памяти:
Основные параметры настроены, можно приступать к калибровке! Но, раз уж мы ковыряем прошивку, сразу доработаем все необходимое для реализации работы в меню контроллера без ПК.
Опишем температуру преднагрева для PLA и ABS пластика:
Если интересно знать статистику работы принтера. Для сохранения статистики в EEPROM включим:
Данная фишка позволит сохранять в энергонезависимой памяти контроллера следующую информацию:
Информацию можно получить из принтера по команде M78.
Также рекомендую включить настройки температурной безопасности:
Режимы требуется настраивать индивидуально для каждой модели принтеров. Описание параметров приведу в части статьи, описывающей вкладку Configuration_adv.h.
Если с настройками по умолчанию энкодера работать неудобно (слишком быстро перепрыгивает между разделами меню или не устраивает направление вращения), то следующие разделы помогут тонко отстроить работу энкодера:
// ЧИСЛО ИМПУЛЬСОВ ЭНКОДЕРА НА ОДИН ШАГ. ДЛЯ ЭКОДЕРОВ С ВЫСОКИМ РАЗРЕШЕНИЕМ
// ТРЕБУЕТСЯ УВЕЛИЧИТЬ ЗНАЧЕНИЕ
// ИЗМЕНЕНИЕ НАПРАВЛЕНИЯ ВРАЩЕНИЯ
ВКЛАДКА Configuration_adv.h
Прошивка поддерживает большое количество дополнительных настроек, очень помогающих в работе. Хотелось бы сразу описать те, которые я активно использую. Для перехода к расширенным настройкам открываем вкладку Configuration_adv.h.
Настройки режимов защиты по температуре:
После включения параметра THERMAL_PROTECTION_HOTENDS при нагреве хотэнда по командам M140 или M190 принтер будет отслеживать прирост температуры! Если за период времени WATCH_TEMP_PERIOD температура не увеличивается на WATCH_TEMP_INCREASE ГРАДУСОВ, то принтер остановится и потребуется полная перезагрузка.
Для нагревателя стола тот же алгоритм защиты и переменные при условии включения THERMAL_PROTECTION_BED:
Если для отвода тепла от платы контроллера используется вентилятор, то разумно использовать его включение программно и подключить через дополнительную недорогую плату. В прошивке при этом требуется:
1. Определить пин контроллера, задействованный для управления вентилятором охлаждения:
Очень интересная настройка:
позволяет запускать вентилятор обдува фактически на любой рабочей скорости. Для этого на установленное в настройке время в миллисекундах задается максимальная стартовая скорость. После запуска установится рабочая скорость.
Для более детального управления вентилятором обдува радиатора задаем пин, скорость вращения и температура включения:
В предыдущих статьях я упоминал, что драйвер шагового двигателя оси Z при параллельном подключении двух двигателей, существенно перегревается. Прошивка позволяет подключить второй двигатель на драйвер неиспользуемого двигателя экструдера:
Пожалуй, это все самые необходимые настройки вкладки.
ВКЛАДКА Language_RU.h
После перехода на русский язык мне не понравился перевод параметров. Я сделал перевод под себя. Для этого во вкладке Language_RU.h изменил константы:
ОТЛАЖЕННАЯ ПРОШИВКА
Тем, кто собрал таки свою Прушу, выкладываю свою версию прошивки. Прошивка полностью отлажена и позволит сразу запустить принтеры ZDV Prusa I3 и ZDV Prusa I3 v2.
УПРАВЛЯЮЩАЯ ПРОГРАММА
В данной статье собраны основные ошибки, которые возникают при работе с 32-разрядными микроконтроллерами.
Задание тактирования
Тактирование блока всегда должно задаваться ПЕРЕД настройкой его конфигурации!Очень часто возникают ошибки, когда настраивается какой-либо периферийный блок, при этом тактирование данного блока не разрешено в контроллере тактовых частот. Также возможна ситуация, когда тактирование сбрасывается в одном из подключенных файлов. Необходимо внимательно следить за последовательностью включения тактирования периферийного блока и его конфигурации. В фрагменте кода 1 приведена корректная настройка порта С.
Фрагмент кода 1 - Пример инициализации порта ввода-вывода
// 1 - Включаем тактирование порта С
RST_CLK_PCLKcmd (RST_CLK_PCLK_PORTC, ENABLE);
// 2 - Инициализируем порт в заданной конфигурации
PORT_StructInit(&GPIOInitStruct);
GPIOInitStruct.PORT_Pin = PORT_Pin_0;
GPIOInitStruct.PORT_OE = PORT_OE_OUT;
GPIOInitStruct.PORT_SPEED = PORT_SPEED_SLOW;
GPIOInitStruct.PORT_MODE = PORT_MODE_DIGITAL;
Программа работает с отладчиком, но не работает при подаче питания на МК
Если программа работает с отладчиком, но не работает после сброса по Reset или после включения питания, необходимо проверить очередность включения тактирования и инициализации!Это тот случай, когда тактирование в программе задано после настройки периферии. На примере настройки портов рассмотрим ход выполнения программы:
После сброса по Reset или после включения питания запускается пользовательская программа, тактирование периферийных контроллеров по сбросу выключено.Так как тактирование портов не было включено на момент их инициализации, то настройка портов не была произведена.
При запуске программы в режиме отладки происходит следующая последовательность действий:
Отладчик подключается и перезапускает МК, при этом если в настройках отладчика выбран сброс только ядра, то тактирование периферийных блоков остаётся включённым с прошлого запуска. В программе происходит инициализация портов, которая выполняется успешно, так как тактирование портов включено.В данном случае порты ввода-вывода функционируют корректно, поскольку их инициализация происходила при уже включенном тактировании.
Переменные и флаги в прерываниях
Нельзя изменять значение переменной в основном потоке и в обработчике прерывания без атомарного доступа!Например, простейшая операция " i++; " происходит в несколько этапов:
В регистр ядра Rx загружается значение i из ячейки памяти.В любой момент между этими шагами может возникнуть прерывание, в обработчике которого также возможно изменение переменной i. В этом случае при выходе из обработчика прерывания новое значение переменной i будет изменено в основной программе на шаге 3, при этом логика программы может быть нарушена.
В ядре Cortex M существуют операции для защищенного обращения к памяти LDREX и STREX. Информацию по их использованию можно найти, например, на официальном сайте Keil.
Вторым вариантом обращения к памяти может быть использование метода bit-band, который доступен для МК на базе Cortex M3/M4. Запись и стирание флагов в ячейках памяти происходит атомарными операциями типа чтение-модификация-запись.
Программирование Flash-памяти
Flash память МК может работать в двух режимах: в обычном режиме (доступ к памяти осуществляется через шины I Code и D Code) и в режиме программирования (доступ к памяти осуществляется через регистры контроллера Flash-памяти). В режиме программирования программный код должен выполняться из области системной шины (внешняя память) или ОЗУ. Выполнение программного кода из Flash-памяти в режиме программирования невозможно. При попытке доступа ядра к Flash-памяти, находящейся в режиме программирования, будет вызвано прерывание HardFault или BusFault в зависимости от настроек ядра (SCR регистры). Поэтому важно, чтобы при программировании Flash-памяти не возникало никаких прерываний, поскольку таблица векторов и обработчики прерываний по умолчанию расположены во Flash-памяти.
Чтобы запретить выбранное прерывание IRQn необходимо вызвать функцию NVIC_DisableIRQ(). При этом необходимо учитывать, что запрещение генерации запроса прерываний от системного таймера SysTick выполняется не в контроллере NVIC, а в регистре управления системным таймером.
Пример запрещения прерываний от системного таймера приведён в фрагменте кода 2.
Фрагмент кода 2 - Запрещение прерываний от системного таймера
Чтобы запретить сразу все прерывания, кроме HardFaut и NMI, необходимо выполнить специальную функцию, как показано в фрагменте кода 3.
Фрагмент кода 3 - Запрещение всех прерывания, кроме HardFaut и NMI
После работы с Flash-памятью необходимо вернуть разрешение прерываний.
Пример расположения программного кода в памяти ОЗУ приведён в статье Расположение функций в ОЗУ, программирование EEPROM.
Выводы, совмещенные с JTAG и SWD
Иногда возникает необходимость использовать выводы, совмещенные с интерфейсом JTAG и SWD (далее для краткости используется обозначение JTAG, но подразумевается JTAG и SWD). При использовании функций библиотеки SPL выводы, совмещенные с JTAG B, перенастроить не получится, так как для них по умолчанию установлена защита. Например, функция PORT_Init() проверяет конфигурируемые выводы на принадлежность к JTAG B и не даёт их переназначать. Разрешение данной проверки определено в файле MDR32F9Qx_config.h с помощью макроопределения USE_JTAG_B, строка 80, как показано в фрагменте кода 4.
Фрагмент кода 4 - Макроопределения защиты выводов, совмещённых с JTAG, в файле MDR32F9Qx_config.h
Библиотечный файл MDR32F9Qx_config.h защищен от записи, поэтому необходимо предварительно в свойствах файла снять атрибут "Только чтение" (Правая клавиша мыши -> Свойства -> Только чтение). Для снятия защиты с выводов, совмещённых с JTAG A или B необходимо закомментировать соответствующее макроопределение: USE_JTAG_A или USE_JTAG_B. После этого данными выводами можно управлять с помощью функций SPL.
Необходимо обратить внимание, что после переопределения выводов, совмещенных с JTAG, выбранный интерфейс JTAG работать не будет. Программа при запуске будет переопределять эти выводы, и подключиться к МК через данный интерфейс будет невозможно. Для связи с МК необходимо будет использовать либо другой интерфейс JTAG, либо интерфейс UART при старте МК в режиме "UART загрузчик". Чтобы сохранить работоспособность интерфейса JTAG при старте МК, необходимо в начале функции main() вставить пустой цикл на пару секунд. Этот цикл даст некоторую задержку перед переопределением выводов, совмещённых с JTAG. За это время отладчик успеет перехватить управление и остановить исполнение программы. Таким образом сохраняется возможность подключиться к МК, даже если выводы JTAG в программе используются по другому назначению.Запись в регистры порта, выводы которого совмещенные с JTAG и SWD
Если в программе не используются функции SPL, то необходимо учитывать, что при записи в регистры MDR_PORTx→RXTX и MDR_PORTx→OE биты выводов, совмещенных с JTAG, необходимо сбрасывать. Если этого не сделать, то работа интерфейса будет нарушена, а отладка невозможна.В качестве примера можно посмотреть реализацию функций PORT_SetBits() или PORT_ResetBits() библиотеки SPL.
Смена тактовой частоты
Для смены тактовой частоты на более высокую требуется совершить следующие операции:
Если требуется, переключить мультиплексор С3 на промежуточный источник тактирования, например, HSI. Настроить генератор HSE и/или умножитель частоты PLL и дождаться, пока он выйдет в рабочий режим. Настроить в контроллере Flash-памяти число тактов паузы Delay до переключения на более высокую частоту. Настроить поля SelectRI и LOW в регистре MDR_BKP→REG_0E. Переключить мультиплексор С3 на новый источник тактирования.При переходе на более низкую частоту, изменение значения Delay и SelectRI, LOW производят после смены частоты.
Таким образом, при смене тактовой частоты необходимо соблюдать следующие правила:
До перехода на новую частоту с помощью переключения мультиплексора C3 необходимо, чтобы новая частота была полностью сформирована, и МК был полностью готов к работе на ней. На момент смены частоты значения Delay и SelectRI, LOW должны соответствовать максимальной частоте из старого и нового значения.Пример инициализации тактирования в МК серии 1986ВЕ9х
В фрагменте кода 5 приведена функция CPU_Initialize(), инициализирующая тактирование в МК серии 1986ВЕ9х от умножителя частоты PLL с использованием генератора HSE, который работает на внешнем кварцевом резонаторе. Для работы функции CPU_Initialize() в проект необходимо подключить библиотечные файлы MDR32F9Qx_rst_clk.c, MDR32F9Qx_eeprom.c, MDR32F9Qx_power.c.
Фрагмент кода 5 - Инициализация тактирования в МК серии 1986ВЕ9х
// Инициализация системы тактирования микроконтроллера
void CPU_Initialize (void)
<
// Сброс настроек системы тактирования
RST_CLK_DeInit();
// Инициализация генератора на внешнем кварцевом резонаторе (HSE = 8 МГц)
RST_CLK_HSEconfig (RST_CLK_HSE_ON);
if(RST_CLK_HSEstatus() != SUCCESS) while (1);
>
// Инициализация блока PLL
// Настройка источника и коэффициента умножения PLL
// CPU_C1_SEL = HSE_CLK, PLLCPUo = HSE_CLK * 10 = 8 МГц * 10 = 80 МГц
RST_CLK_CPU_PLLconfig (RST_CLK_CPU_PLLsrcHSEdiv1, RST_CLK_CPU_PLLmul10);
// Включение PLL
RST_CLK_CPU_PLLcmd (ENABLE);
if(RST_CLK_CPU_PLLstatus() == ERROR) while (1);
>
// Подключение PLL к системе тактирования
// (CPU_C2_SEL = PLLCPUo = 80 МГц)
RST_CLK_CPU_PLLuse (ENABLE);
// Настройка коэффициента деления блока CPU_C3_SEL
// (CPU_C3_SEL = CPU_C2)
RST_CLK_CPUclkPrescaler (RST_CLK_CPUclkDIV1);
// Настройка числа тактов паузы Delay в контроллере Flash-памяти
// Тактовая частота до 100 МГц - Delay = 3
RST_CLK_PCLKcmd (RST_CLK_PCLK_EEPROM, ENABLE);
EEPROM_SetLatency(EEPROM_Latency_3);
RST_CLK_PCLKcmd (RST_CLK_PCLK_EEPROM, DISABLE);
// Настройка параметров регулятора напряжения SelectRI и LOW в контроллере BKP
// Тактовая частота 80 МГц
RST_CLK_PCLKcmd(RST_CLK_PCLK_BKP, ENABLE);
POWER_DUccMode(POWER_DUcc_upto_80MHz);
// Переключение тактовой частоты процессора на CPU_C3
// (HCLK = CPU_C3)
RST_CLK_CPUclkSelection (RST_CLK_CPUclkCPU_C3);
>
При использовании функции printf() отладка не доходит до main()
Это особенность компилятора Keil, заменяющего функционал printf() на инструкцию программной остановки BKPT для реализации механизма semihosting. При старте программы низкоуровневые библиотеки Си также выполняют инструкцию BKPT, что приводит к остановке исполнения программы. Чтобы Keil не реализовывал механизм semihosting необходимо выполнить один из указанных пунктов:
1) Исключить вызов printf() из проекта.
2) Описать функции, перенаправляющие стандартный поток ввода-вывода в требуемый интерфейс МК, например, как показано в статьях Printf через ITM и Printf через UART.
3) В настройках проекта "Options for Target -> Target" выбрать опцию "Use MicroLIB", которая позволяет использовать оптимизированную по размеру кода стандартную библиотеку Си, в которой исключен механизм semihosting. Подробнее про MicroLIB описано на официальном сайте Keil.
Переход по абсолютному адресу приводит к исключению HardFault
Иногда требуется перейти в функцию, расположенную по известному адресу в памяти. Если в коде это будет выражено так, как показано в фрагменте кода 6 или 7, то произойдёт вызов исключения HardFault:
Фрагмент кода 6 - Некорректный переход по заданному адресу на языке Си
// Указатель на функцию в памяти по известному адресу
typedef void (*funcptr)();
funcptr funcInRAM = (funcptr) (BASE_ADDR_FUNC_IN_RAM);
// Вызов функции
funcInRAM();
Фрагмент кода 7 - Некорректный переход по заданному адресу на языке ассемблер
LDR R0,=(0x20005000)
BX R0
Это происходит, потому что адрес перехода должен быть нечетным, чтобы указать ядру о переходе на инструкцию THUMB, а не ARM! Подробнее об этом описано на сайте ARM Info Center.
На самом деле при переходе в фрагментах кода 6 и 7 происходит исключение UsageFault, но данное исключение по сбросу запрещено, поэтому происходит вызов обработчика исключения HardFault. Разрешение исключений BusFault, MemManage fault и UsageFault выполняется в регистрах ядра SCB (System Control Block), как показано в фрагменте кода 8. О том, как работать с исключениями в Cortex-M3/M4 приведено в Application Note 209 от ARM.
Фрагмент кода 8 - Разрешение исключений BusFault, MemManage fault и UsageFault
SCB->SHCSR |= SCB_SHCSR_USGFAULTENA;
SCB->SHCSR |= SCB_SHCSR_BUSFAULTENA;
SCB->SHCSR |= SCB_SHCSR_MEMFAULTENA;
Таким образом, чтобы переход на заданный адрес произошел корректно, необходимо указывать в нулевом бите адреса перехода единицу, как показано в фрагментах кода 9 и 10.
Фрагмент кода 9 - Корректный переход по заданному адресу на языке Си// Указатель на функцию в памяти по известному адресу
typedef void (*funcptr)();
funcptr funcInRAM = (funcptr) (BASE_ADDR_FUNC_IN_RAM + 1);
Читайте также: