При написании публикации про ATtiny85 я обратил внимание на то, как реализовано изменение частоты микроконтроллера: достаточно выбрать нужное значение тактовой частоты в меню IDE Ардуино и затем выполнить команду "Записать загрузчик". А почему бы не сделать так же для Ардуино? Чтобы можно было простыми действиями настроить ее на тактирование либо от внешнего резонатора на 16МГц, либо от внутреннего RC-генератора на 8МГц. Кстати при тактировании от внутреннего генератора микроконтроллер можно извлечь из Ардуино, тем самым значительно снизить энергопотребление. В общем, тема весьма интересная, подробности под катом.
Содержание
Что нужно знать о тактировании AVR микроконтроллеров
Редактирование файла boards.txt
Что такое Optiboot
Компиляция Optiboot для работы на частотах 8МГц и 1МГц
Изменение частоты и источника тактирования Ардуино
Редактирование файла boards.txt
Что такое Optiboot
Компиляция Optiboot для работы на частотах 8МГц и 1МГц
Изменение частоты и источника тактирования Ардуино
Что нужно знать о тактировании AVR микроконтроллеров
AVR микроконтроллеры способны работать с различными источниками тактового сигнала. Это может быть внешний резонатор, RC-цепочка (внутренняя или внешняя), а так же внешний сигнал синхронизации. Источник тактирования выбирается исходя из требований к устройству. Так для построения точных микроконтроллерных систем следует использовать внешние кварцевые или керамические резонаторы, так как они обладают высокой стабильностью и не чувствительны к изменениям температуры. В этом плане им уступают генераторы на основе времязадающей RC-цепочки: они менее стабильны и чувствительны к изменениям температуры и напряжения. С другой стороны внутренний RC-генератор присутствует практически во всех AVR микроконтроллерах и его использование будет наиболее простым и экономичным решением в системах, не предъявляющих высоких требований к стабильности тактового сигнала.Настройка микроконтроллера на работу с тем или иным источником тактового сигнала осуществляется установкой конфигурационных битов (фьюзов) при помощи программатора. Применительно к нашей ситуации установка фьюзов происходит при выполнении команды "Записать загрузчик" из меню IDE Ардуино, значения фьюзов берутся из файла boards.txt. Он же отвечает за добавление новых пунктов в меню Инструменты. Поэтому доработка IDE Ардуино для добавления в нее меню выбора частоты начинается с редактирования файла boards.txt
Редактирование файла boards.txt
Перейдите в каталог Arduino_dir\hardware\arduino\avr\, где Arduino_dir - это каталог, в который установлена среда разработки Ардуино. У меня этот путь выглядит так: d:\Arduino\arduino-1.6.12\hardware\arduino\avr\. Перед внесением изменений в файл boards.txt я рекомендую сделать его резервную копию. Теперь открываем файл boards.txt в текстовом редакторе (подойдет notepad++ или другой, поддерживающий кодировку UTF-8, чтобы не было проблем с отображением русских букв в IDE Ардуино) и добавляем в него строку menu.clock=ТактированиеЗатем находим секцию для Ардуино Уно (я опишу порядок действий применительно к Ардуино Уно, но таким же образом можно скорректировать секции других плат с поправкой на микроконтроллер):
Здесь нужно добавить наше подменю для выбора источника тактирования и частоты. Для этого сперва удалим строки, определяющие:
- скорость загрузки - uno.upload.speed;
- значения фьюзов - uno.bootloader.low_fuses, .high_fuses, .extended_fuses;
- имя файла загрузчика - uno.bootloader.file;
- частоту микроконтроллера - uno.build.f_cpu.
uno.menu.clock.external16=Внешний резонатор 16МГц
uno.menu.clock.external16.upload.speed=115200
uno.menu.clock.external16.bootloader.low_fuses=0xFF
uno.menu.clock.external16.bootloader.high_fuses=0xDE
uno.menu.clock.external16.bootloader.extended_fuses=0xFF
uno.menu.clock.external16.bootloader.file=optiboot/optiboot_atmega328.hex
uno.menu.clock.external16.build.f_cpu=16000000L
uno.menu.clock.internal8=Внутренний RC-генератор 8МГц
uno.menu.clock.internal8.upload.speed=57600
uno.menu.clock.internal8.bootloader.low_fuses=0xE2
uno.menu.clock.internal8.bootloader.high_fuses=0xDE
uno.menu.clock.internal8.bootloader.extended_fuses=0xFF
uno.menu.clock.internal8.bootloader.file=optiboot/optiboot_atmega328_8.hex
uno.menu.clock.internal8.build.f_cpu=8000000L
uno.menu.clock.internal1=Внутренний RC-генератор 1МГц
uno.menu.clock.internal1.upload.speed=4800
uno.menu.clock.internal1.bootloader.low_fuses=0x62
uno.menu.clock.internal1.bootloader.high_fuses=0xDE
uno.menu.clock.internal1.bootloader.extended_fuses=0xFF
uno.menu.clock.internal1.bootloader.file=optiboot/optiboot_atmega328_1.hex
uno.menu.clock.internal1.build.f_cpu=1000000L
Для наглядности я приведу скриншот моего файла boards.txt, каким он был и каким стал после выполнения описанных изменений:
Таким образом мы описали меню из трех пунктов, для каждого из них указали скорость загрузки скетчей, значения фьюзов, имя файла загрузчика (об этом чуть позже) и частоту микроконтроллера. При помощи онлайн калькулятора вы можете расшифровать приведенные значения фьюзов и увидеть, как происходит выбор источника тактирования. И что для получения тактовой частоты 1МГц при работе от внутреннего RC-генератора используется деление частоты на 8 (фьюз CKDIV8).
Сохраните файл в кодировке UTF-8 без BOM и запустите IDE. Если все сделано правильно, то при выборе платы Arduino Uno вам станет доступно меню Инструменты->Тактирование. Но этих изменений пока еще мало. Если сейчас выбрать в меню, например, Внутренний RC-генератор 8МГц и выполнить запись загрузчика, то новые значения фьюзов, конечно, запишутся в микроконтроллер и он начнет работать с внутренним RC-генератором. Но мы потеряем возможность загружать в Ардуино новые скетчи, потому что записанный в нее загрузчик рассчитан на частоту 16МГц. Выход - скомпилировать загрузчик для работы на частотах 8МГц и 1МГц. Если у вас нет желания заморачиваться с компиляцией загрузчика, то можете скачать уже скомпилированные файлы отсюда, поместить их в каталог Arduino_dir\hardware\arduino\avr\bootloaders\optiboot\ и перейти к пункту Изменение частоты и источника тактирования Ардуино. А кому интересно могут скомпилировать их самостоятельно. О том как это сделать описано далее.
Что такое Optiboot
Optiboot - это загрузчик для AVR микроконтроллеров, созданный Питером Найтом (Peter Knight). В его основу легли труды нескольких разработчиков и групп (Jason P. Kyle, Arduino group, Spiff , AVR-Libc group, Ladyada), впоследствии он значительно развился. Загрузчик получился настолько удачным, что компания-разработчик Ардуино стала использовать его в своей плате Ардуино Уно. С недавнего времени Optiboot является официальным загрузчиком и для других плат на базе ATmega328p (Нано, Мини). По сравнению с использовавшимся в них старым загрузчиком Optiboot обладает рядом преимуществ:
- занимает всего 512 байт, освобождая 1,5кб для программ пользователя;
- значительно быстрее выполняет загрузку скетчей;
- поддерживает альтернативные серийные порты, скорости загрузки и частоты микроконтроллера.
С 2011 года поддержкой Optiboot занимается Билл Вестфилд (Bill Westfield). Это самостоятельный проект, не финансируемый какими-либо организациями.
Компиляция Optiboot для работы на частотах 8МГц и 1МГц
Исходные файлы Optiboot входят в состав IDE Ардуино и находятся в каталоге Arduino_dir\hardware\arduino\avr\bootloaders\optiboot\. Там же расположен батник omake.bat для сборки загрузчика. Вот только для его сборки в составе IDE Ардуино (начиная с версий 1.5.x) не хватает утилиты make.exe. Наиболее простое решение - это скопировать ее из старой версии. Для этого:
- скачайте IDE версии 1.0.6;
- распакуйте архив и перейдите каталог \arduino-1.0.6\hardware\;
- скопируйте или переместите каталог tools в Arduino_dir\hardware\arduino\ вашей рабочей IDE;
- IDE 1.0.6 больше не нужна, ее можно удалить.
Между ней и началом следующей секции для Sanguino вставляем код:
atmega328_8: TARGET = atmega328
atmega328_8: MCU_TARGET = atmega328p
atmega328_8: CFLAGS += '-DLED_START_FLASHES=3' '-DBAUD_RATE=57600'
atmega328_8: AVR_FREQ = 8000000L
atmega328_8: LDSECTIONS = -Wl,--section-start=.text=0x7e00 -Wl,--section-start=.version=0x7ffe
atmega328_8: $(PROGRAM)_atmega328_8.hex
atmega328_8: $(PROGRAM)_atmega328_8.lst
atmega328_1: TARGET = atmega328
atmega328_1: MCU_TARGET = atmega328p
atmega328_1: CFLAGS += '-DLED_START_FLASHES=3' '-DBAUD_RATE=4800'
atmega328_1: AVR_FREQ = 1000000L
atmega328_1: LDSECTIONS = -Wl,--section-start=.text=0x7e00 -Wl,--section-start=.version=0x7ffe
atmega328_1: $(PROGRAM)_atmega328_1.hex
atmega328_1: $(PROGRAM)_atmega328_1.lst
Это копии секции atmega328. От исходной они отличаются частотой микроконтроллера и скоростью загрузки скетчей. Эти значения соответствуют указанным нами ранее в файле boards.txt. Думаю, можно указать и большую скорость загрузки, но я не экспериментировал с этим. Однозначно, при слишком высокой скорости ошибки будут неизбежны, поэтому с уменьшением частоты микроконтроллера я уменьшаю и скорость загрузки.
Теперь нужно скомпилировать загрузчик для работы на пониженной частоте. Для этого, находясь в каталоге Arduino_dir\hardware\arduino\avr\bootloaders\optiboot\, запустите командную строку, введите и выполните по очереди команды:
omake.bat atmega328_8
omake.bat atmega328_1
Загрузчики для работы на частоте 8МГц и 1МГц готовы! Теперь нужно удалить папку tools, которую мы позаимствовали из IDE Ардуино 1.0.6. Если этого не сделать, то среда не запустится. Связано это с тем, что содержимое Arduino_dir\hardware\arduino\ должно иметь определенную структуру и папке tools здесь не место.
Итак, запускаем среду разработки Ардуино, выбираем в списке плат Arduino/Genuino Uno, в меню Инструменты->Тактирование выбираем значение Внутренний RC-генератор 8МГц. Подключаем программатор к компьютеру, выставляем соответствующее значение в меню Инструменты->Программатор. Записываем загрузчик. После этого отключаем программатор, подключаем Ардуино напрямую к компьютеру и в меню Инструменты->Программатор выставляем стандартное значение - AVRISP mkII. Теперь можете проверить работу платы, загрузив в нее скетч Blink из стандартных примеров. Когда решите снова изменить частоту, нужно будет повторно выполнить запись загрузчика, выбрав соответствующее значение в меню Тактирование.
Если при записи загрузчика на 1МГц через USBasp у вас возникнет следующая ошибка:
- не пугайтесь, просто нужно установить перемычку JP3 на программаторе. При использовании Ардуино в качестве программатора такая ошибка не возникает.
Теперь было бы интересно вынуть ATmega328P из Ардуино и измерить его энергопотребление при работе на 8МГц / 1МГц, а также в режиме PowerDown. Но это я оставлю для будущей публикации - Энергопотребление ATmega328P при тактировании от внутреннего RC-генератора
omake.bat atmega328_8
omake.bat atmega328_1
Загрузчики для работы на частоте 8МГц и 1МГц готовы! Теперь нужно удалить папку tools, которую мы позаимствовали из IDE Ардуино 1.0.6. Если этого не сделать, то среда не запустится. Связано это с тем, что содержимое Arduino_dir\hardware\arduino\ должно иметь определенную структуру и папке tools здесь не место.
Изменение частоты и источника тактирования Ардуино
Для изменения частоты и источника тактирования необходимо записать в Ардуино новый загрузчик. Для выполнения этой процедуры нужен программатор. Если у вас его нет, то можете использовать в качестве программатора другую плату Ардуино, в статье Arduino as ISP - программатор из Ардуино эта тема подробно расписана. Я для записи загрузчика воспользуюсь программатором USBasp.Итак, запускаем среду разработки Ардуино, выбираем в списке плат Arduino/Genuino Uno, в меню Инструменты->Тактирование выбираем значение Внутренний RC-генератор 8МГц. Подключаем программатор к компьютеру, выставляем соответствующее значение в меню Инструменты->Программатор. Записываем загрузчик. После этого отключаем программатор, подключаем Ардуино напрямую к компьютеру и в меню Инструменты->Программатор выставляем стандартное значение - AVRISP mkII. Теперь можете проверить работу платы, загрузив в нее скетч Blink из стандартных примеров. Когда решите снова изменить частоту, нужно будет повторно выполнить запись загрузчика, выбрав соответствующее значение в меню Тактирование.
Если при записи загрузчика на 1МГц через USBasp у вас возникнет следующая ошибка:
- не пугайтесь, просто нужно установить перемычку JP3 на программаторе. При использовании Ардуино в качестве программатора такая ошибка не возникает.
Теперь было бы интересно вынуть ATmega328P из Ардуино и измерить его энергопотребление при работе на 8МГц / 1МГц, а также в режиме PowerDown. Но это я оставлю для будущей публикации - Энергопотребление ATmega328P при тактировании от внутреннего RC-генератора
Здравия , спасибо за статью.
ОтветитьУдалитьПришли с Али про мини 10шт.
И как то не правильно работают.
Нашел скетч, проверил платы, а кварцы стоят на 12мгц.
Попробую по вашему методу добавить выбор для 12мгц кварца.
Добрый день!
УдалитьНапишите о результатах когда попробуете.
Доброй ночи.
ОтветитьУдалитьПрошел по ссылке в статье на калькулятор фьюзов - не все понял по инглишу.
Нашел наш сайт по русски. http://fusecalc.mirmk.ru/
Не знаю как вставить картинку. Оставлю вам ссылку на картинку в моем гугл диске
https://drive.google.com/file/d/1WNwAR7cZNer5GB_v2GqG78Yd9JyqBqER/view?usp=sharing
_________________________________________________
"Режимы синхронизации и задержки запуска (CKSEL, SUT)"
---------------------------------------------------
-"выбор кварца 8мгц и выше" - получается не важно 16 или 12 мгц кварц.
Проверял примером с блинком. 10 морганий время: при 16мгц - 20с, 12мгц - 16с, 8мгц - 10с. Использовал две про мини 328p 5v с кварцем 16мгц и 12мгц. результат одинаковый.
Редактировал только boards.txt
Это было
## Arduino Pro or Pro Mini (5V, 16 MHz) w/ ATmega328P
## --------------------------------------------------
pro.menu.cpu.16MHzatmega328=ATmega328P (5V, 16 MHz)
pro.menu.cpu.16MHzatmega328.upload.maximum_size=30720
pro.menu.cpu.16MHzatmega328.upload.maximum_data_size=2048
pro.menu.cpu.16MHzatmega328.upload.speed=57600
pro.menu.cpu.16MHzatmega328.bootloader.low_fuses=0xFF
pro.menu.cpu.16MHzatmega328.bootloader.high_fuses=0xDA
pro.menu.cpu.16MHzatmega328.bootloader.extended_fuses=0xFD
pro.menu.cpu.16MHzatmega328.bootloader.file=atmega/ATmegaBOOT_168_atmega328.hex
pro.menu.cpu.16MHzatmega328.build.mcu=atmega328p
pro.menu.cpu.16MHzatmega328.build.f_cpu=16000000L
Поменял только последнюю строку значение с 16000000 на 12000000
## Arduino Pro or Pro Mini (5V, 12MHz) w/ ATmega328P
pro.menu.cpu.12MHzatmega328=ATmega328P (5V, 12 MHz)
pro.menu.cpu.12MHzatmega328.upload.maximum_size=30720
pro.menu.cpu.12MHzatmega328.upload.maximum_data_size=2048
pro.menu.cpu.12MHzatmega328.upload.speed=57600
pro.menu.cpu.12MHzatmega328.bootloader.low_fuses=0xFF
pro.menu.cpu.12MHzatmega328.bootloader.high_fuses=0xDA
pro.menu.cpu.12MHzatmega328.bootloader.extended_fuses=0xFD
pro.menu.cpu.12MHzatmega328.bootloader.file=atmega/ATmegaBOOT_168_atmega328.hex
pro.menu.cpu.12MHzatmega328.build.mcu=atmega328p
pro.menu.cpu.12MHzatmega328.build.f_cpu=12000000L
"Проверял примером с блинком. 10 морганий время: при 16мгц - 20с, 12мгц - 16с, 8мгц - 10с. Использовал две про мини 328p 5v с кварцем 16мгц и 12мгц. результат одинаковый."
УдалитьХрень какая-то. Чем ниже частота кварца, тем длиннее должны быть интервалы
Товарищ пишет, что и f_cpu тоже менял. Тогда бы при соответствии кварца указанному в f_cpu значению время мигания должно быть одинаковым.
УдалитьПохоже будто f_cpu действительно изменяли, а кварц во всех случаях оставался на 16:
F_cpu 16мгц - 20с - норм.
F_cpu 8мгц - 10с - обманули МК вдвое, он быстрее и выполнил.
F_cpu 12мгц - 16с - смысл как в предыдущем пункте с разницей примерно в четверть.
И возвращаясь к исходному предположению о кварце на 12МГц в пришедших из Китая про мини - оно ошибочно, кварцы стоят на 16, тогда всё сходится
Еще обнаружил что только половина из 10 этих про мини с 12-м кварцем, остальные с 16-м
ОтветитьУдалитьБудет свободное время залью еще раз скетч, во все эти про мини.
Так они вроде рабочие, а пины D6 D7 на которые идет сигнал не работают.
Ссылка на ARDUINO 1.0.6 не работает (устарела?), сейчас такая ссылка: https://downloads.arduino.cc/arduino-1.0.6-windows.zip
ОтветитьУдалитьСпасибо, поправил.
УдалитьЗдравствуйте! Вот у меня та же проблема с тактированием и временем. Я собрал плату, на ней стоит кварц 16 Мгц. Для удобства программирования и проверки на лету в DIP28 в который потом встанет Atmega8 вставил Nano (сделал отладочную на базе NANO). Боролся за каждый байт, чтобы влезло на AM8. И вот все заработало на NANO, я радостный заливаю скетч Arduino SPI в AM8 и... чехарда из звуков. Ладно, - напутал наверное. Раньше звуки из пищалки не нужны были. На NANO яркие и звонкие, на AM8 дребезг. Стал играться тактовой частотой, и как я только не заливал и с внутренним и внешним, но ВЫХОДИТ ОДНО И ТО ЖЕ. 1 секунда в скетче (напр. delay(1000)) при 8Мгц хоть при внутреннем, хоть при внешнем тактировании равна 8 сек. Аналогично, 16Мгц - 16 секунд. Пересмотрел кучу видео и прочита уйму статей, вот и тут я о этому самому поводу. Перепробовал десятки вариантов, убил несколько МК, результ нулевой.
ОтветитьУдалитьПришлось установить внутреннюю тактовую частоту 1 Мгц. Только так 1 сек = 1 сек реального времени.
Кстати, совершенно нет разницы, стоит внешний кварц или нет.
Как вывод, устройство хорошо работает только на AM328 на 1 Мгц внутреннего тактирования.
На АМ8 на 1Мгц программа работает, но звуки всегда - однотонный дребезг.
Есть какие нибудь предложения?
Этот комментарий был удален автором.
ОтветитьУдалитьДобрый день!
УдалитьНесоответствие указанных в программе задержек реальным значениям - это несоответствие реальной частоты микроконтроллера и указанной в IDE (в случае с IDE Arduino - это файл boards.txt, параметры build.f_cpu). Вот прям к гадалке не ходи. И к этой ситуации 2 пути: неверные значения фьюзов или неверное значение f_cpu в этом самом boards.txt. Проверьте оба варианта.
Этот комментарий был удален автором.
ОтветитьУдалитьЭтот комментарий был удален автором.
ОтветитьУдалитьВсем доброго времени суток!
ОтветитьУдалитьИтак что я выяснил. Мои МК 8 на заводе прошиты как (проверил чтением avrdude_prog-v.3.3):
Внутренний RC генератор 1МГц; Запуск: 6 CK + 0 мс; [CKSEL=0001 SUT=00]
Проблема в том, что если перепрошивать фьюзы USBisp в avrdude под другую частоту, например Внешний кварц 16 Мгц, то МК убивается, (штук 5 выбросил и 8 и 328). Сначала появляется сообщение что всё ОК, но повторное чтение сообщает ОШИБКА! (avrdude.exe: warning: cannot set sck period. please check for usbasp firmware update.
avrdude.exe: error: programm enable: target doesn't answer. 1
avrdude.exe: initialization failed, rc=-1
Double check connections and try again, or use -F to override
this check.
)
Та же проблема и с прошиванием Загрузчика в среде Arduino IDE программатором Arduino ISP. Сначала, вроде, МК даже читается с новыми фьзами в avrdude_prog-v.3.3 и потом тут же можно Запрограммировать залив hex файл со своим скетчем, но пусть вас это не радует, установив МК в свою плату он не заработает. Повторное тестирование в avrdude_prog-v.3.3 покажет ту же ошибку!
!!!! А выбросил зря, ибо нашел ролик где рассказывается (в рунете и англоязычном сайте), что эта проблема из за проседания 5v во время процедуры прошивки, и стоит только к МК подключить внешнее питание 5v (только VCC, земля ОБЩАЯ). Прошивается на УРА.
Итак действия для новичков!
Для прошивки своих DIP28 Atmega8 328 можно использовать старую UNO.
У USBasp программатора на шлейфе отпаиваете питание VCC, вообщем питание Atmega должно быть внешнее- свое, но Земля общая!!!
Если прошиваете в Arduino IDE, то сначала создаете в конструкторе прошивку - это и есть ЗАГРУЗЧИК. ВАЖНО ПОНИМАТЬ, например вы создали несколько прошивок для своей Atmega8
1. внешний кварц резонатор 16Мгц
2. внешний кварц резонатор 8Мгц
3. внутренний генератор 1Мгц
4. внутренний генератор 4Мгц
и загрузили Загрузчик в свой МК.
Так вот, надо точно помнить какой свой МК как вы прошили, ибо если вы потом захотите свой МК в котором прошивка на внутренний генератор 8Мгц установить скетч выбрав плату с установками "внешний кварц резонатор 16Мгц", то скетч зальется, но начнется белиберда со временем как у меня, ибо я сразу не уловил, что загрузчик вшитый никуда не девается. полагал, что выбирая плату с новыми установками меняю автоматом и загрузчик, в чем и ошибался.
Но и про отдельное питание для МК не забываем (только VCC? Земля общая).
Владимиру за свой блог жму руку, СПАСИБО!
Мне под 60 лет, программируемой электроний занялся года 4 назад, когда купил 3D принтер, тогда и узнал об Arduino и ее возможностях.
В 60 теория дается тяжело, опыт накопленный блокирует ее.