Как стать автором
Обновить

Комментарии 25

Есть пара неточностей в статье: внутри кристалла - не кварцевый резонатор (никто не пихает внутрь микросхемы кусок слюды), а RC-цепочка, именно поэтому внутренний источник так чувствителен к температуре. Точность у этой RC-цепочки вполне достаточна для работы UART, да и для ряда многих других приложений (там получается что-то в районе от нескольких сотен до пары тысяч PPM). Часы реального времени, построенные на встроенной RC-цепочке, будут уходить в среднем на пару десятков секунд в сутки, именно поэтому гуляет утверждение, что "низкочастотный внутренний осциллятор менее точен, чем высокочастотный": просто к нему предъявляются более жёсткие требования.

Да, вы правы, спасибо за уточнение.
Хочу отметить: в своей практике использования CAN шины в автотракторной технике, где температуры в кабине могут гулять зимой от - 30 до + 30 гр. С., заметил довольно сильный уход битрейта при использовании внутреннего осциллятора, что не позволяло принимать данные, пришлось отказаться от идеи его использования.

Интересно, а если попробовать один раз построить зависимость «температура по встроенному датчику - требуемое для компенсации значение HSITRIM» (так же софтово на плате с внешним резонатором), заложить таблицу в прошивку и периодически подстраивать HSI?

Если решите попробовать - термодатчику однозначно необходимо усреднение по нескольким выборкам, моментальная температура кристалла ощутимо гуляет в зависимости от нагрузки.

А это была идея для одной из следующих статей)

Всё равно точности кварца не получить даже близко. Плюс - у разных контроллеров очень большой разброс характеристик.

Так уже есть калибраторы... На сайте ST. Задействован внутренний температурный датчик. Только решение всё равно так себе.

А что натолкнуло на мысль об использовании внутреннего генератора?

Там из плюсов можно вспомнить только цену, экономию на площади платы и немного потребления в активном режиме.

Но в автопроме нет ни потребности экономить каждую долю цента, ни проблем с местом, а потребление всегда можно уменьшить уходом в сон.

Всегда не понимал людей, которые не втыкают резистор на питание от USB-C, кварцовый резонатор или по конденсатору на каждую ногу питания микроконтроллера. Для кого пишут Reference Manual? Для каждого отхода от рекомендаций производителя всегда нужно находить вескую причину.

К сожалению, мне не ясны были мотивы тех, кто решил не закладывать кварцевый резонатор, так как то устройство было спроектировано как раз к моему приходу на предприятие.

Звучит паршиво, вам придётся разгребать чужие ошибки.

Для колибровки разбега осциллятора от температуры (индивидуальной для каждого кристалла, так как тримминг RC тоже индивидуальный) не забудьте учесть и дрейф опорного напряжения АЦП внутреннего термометра и нестабильность напряжения на линии VCC (линейный стабилизатор тоже имеет свой температурный коэффициент, как и потребление), там же врядли аналоговый тракт отделён от цифрового.

Для индивидуальной калибровки, по идее, учитывать все дрейфы по отдельности как раз не нужно, нам же не нужны сами цифры, достаточно соответствий вида «температурный показометр показал -7 -> выставляем HSITRIM в 19».

А заводская индивидуальная калибровка, кстати, неявно суммируется с HSITRIM, который задаёт сдвиг относительно неё. Возможно, для конкретной задачи и требуемой ей точности (как CAN у автора), хватит и общей для всех устройств таблицы, полученной усреднением с нескольких кристаллов.

На пару десятков секунд в сутки запросто уходит обычный часовой кварц (не термокомпенсированный, без подстройки), а не RC-цепочка.

В сутках 86400 секунд, и какие-нибудь 5 процентов -- это ЧАС времени, а не 20 секунд.

Точность этой RC-цепочки часто НЕдостаточна для работы с UART во всём температурном диапазоне и хорошо работает лишь на столе, при стандартной температуре. На резонансную частоту этой цепочки влияет не только температура, но и технологическая невозможность получения стабильных характеристик на производстве. И лишь у некоторых контроллеров там то ли какая-то самокалибровка, то ли калибровка лазером на производстве. Не у самых дешёвых.

Вообще возможность подключения часового кварца к МК часто означает возможность отказа от второго высокочастотного резонатора. Можно запуститься с внутренним генератором и периодически подстраивать его работу ориентируясь на часовой кварц. Не для любых применений, но для тех гдe 5% достаточно и где МК позволяет подстраивать частоту HSI -- сгодится.

Идея прикольная. Как по мне, так проще завести генератор и осциллом посмотреть его колебания. На сколько часто уходит частота кварца? Вот заткнуться может (сам видел), ну так этот момент обрабатывается и переходим на внутреннее тактирование

А если плата идёт в устройства, которые делаются партиями в тысячи штук, на контрактном производстве? Проще поставить вот такой программный костыль.

Проще поставить кварц на известную частоту. А если кто-то полезет менять компоненты на плате от балды, основываясь исключительно на внешнем сходстве и не читая маркировку — ССЗБ.

Проще поставить изначально заложенный в проект кварц. Но данный костыль на то и костыль, что используется в тех случаях, когда кварцев заложенных в проект в наличии нет (например 8 МГц, но большое количество на 16/4 МГц), что позволяет не писать разные версии прошивки под разные кварцы.

Даже так проще поправить константу в коде, подправить множители/делители и пересобрать прошивку, чем городить искусственный мозг, который будет пытаться откалибровать внешний кварц по внутреннему RC-генератору с поиском ближайшего распространенного (ага, удачи!), пересчетом всех коэффициентов и молитвами всем технобогам чтобы эта комбинация множителей и делителей вообще существовала. Если впаяют 12.145 МГц например.

Год назад, например, была ситуация "ну хоть что-то есть, что можно впаять на эту позицию???"

Можно запроектировать сразу несколько кварцев с разной частотой на одну позицию и не ломать голову с несколькими вариантами прошивок в зависимости от наличия конкретных комплектующих у поставщиков.

Вообще замена компонентов на производстве на другой тип (даже с одинаковыми на первый взгляд характеристиками), без разрешения разработчика или заказчика -- ССЗБ. Потому, что после такой замены генератор может запускаться опять же на не своей штатной гармонике просто потому, что важны все составляющие, и ёмкость микроконтроллера, и конденсаторов, и она должна соответствовать выбранному типу резонатора. Просто заменить один 8МГц на другой 8МГц другой фирмы -- может вроде бы и прокатить, но потом на выходе окажется 10% брака, например.

На производстве тыкаться осциллографом в каждую плату -- неудобно во-первых, во-вторых долго и дорого, в третьих в сколько-нибудь сложной программе для МК работа внешнего генератора может носить периодический характер (потому, что МК будет "засыпать" вместе с генератором).

И наконец -- осциллограф это не прибор для определения частоты, частоту на нём можно оценить лишь приблизительно. Хотя это действительно не слишком принципиально. И щуп для осциллографа имеет порядочную ёмкостную составляющую, чтоб сбить работу генератора (особенно если забыть про делитель).

Насколько может уйти. В небольшом диапазоне может подстраиваться конденсаторами. Либо может стать сходу в три раза больше/меньше. В случаях повреждения резонатора (достаточно падения об пол) может стать какой угодно. Случаи бывают разные.

В случае перехода на внутреннее тактирование неплохо бы не тихо глючить, а как-то индицировать ошибку. Чтоб сразу было понятно в чём дело, а не трясли в каждом случае разработчика за рукав.

	for (uint32_t i = 0; i < 10000; i++){
		if(RCC->CR & RCC_CR_HSERDY)
            ...

Фрагмент кода не очень надёжный в том смысле, что его время выполнения несколько не предсказуемо (неизвестно сколько тактов CPU нужно на итерацию цикла, неизвестно как современные CPU распараллелят инструкции и где будут задержки, всё зависит от опций оптимизации компилятора). Лучше иметь итерацию до достижения таймером заданной величины. А таймер запрограмировать на нужное число тактов в зависимости от текущего выбранного источника тактирования. Генератору с кварцевым резонатором чтоб запуститься нужно от миллисекунд до нескольких десятков миллисекунд (для низкочастотных "часовых" резонаторов на порядок больше). Соответственно таймаут может быть на 100мс, например.

Так как заранее неизвестна частота тактирования низкочастотного резонатора...

Она-то как раз в даташите указывается. С погрешностью порядка 5%, но всё таки известна.

А внешний кварцевый резонатор в особо запущенных случаях запускается на какой-нибудь другой гармонике и частота действительно неизвестна. Это надо сказать типовая неисправность. Она может быть вызвана повреждением резонатора, ошибками монтажа, монтажом неправильных номиналов конденсаторов в цепи резонатора, монтажом не того типа резонатора... И стоило бы хотя бы грубо эту частоту оценить, чтоб принять решение, генератор с внешним резонатором вообще работоспособен или нет.

Обработчики прерывания для всего этого дела -- не нужны. Достаточно в цикле опрашивать специальные регистры. В конце концов, это делается только на старте и процессор в это время ничем другим не занимается.

Определим отношение периодов генератора LSI в тиках HSI к HSE и вернём значение enum, какой частоты генератор подключен...э

Сомнительная техника ввиду сказанного выше: так станет невозможно обнаруживать и сигнализировать о явных неисправностях (например, числом вспышек светодиодика). И не обнаруженная неисправность превращается в куда большую проблему, которую уже должен исследовать инженер (иначе бы ограничилось ремонтом на производстве), и сразу непонятно, программная она или вызвана неправильной работой схемы (потому, что с неправильным кварцем -- "программа глючит", что-то одно работает, что-то другое нет и т.п.)

Поэтому я бы предложил частоту резонатора знать заведомо, или вносить через какой-то механизм конфигурации (путём установки перемычек, путём программирования с компьютера).

В целом представленный программный код изобилует magic numbers в коде. Почему 10000, а не 100500? А если завтра контроллер будет с другой буковкой -- там 10000 ещё нормально, или уже нет? Или почему interruptsCounter == 100? Значит эта сотня где-то ещё закодирована. В code style некоторых компаний чуть ли не вообще запрещают "волшебные числа" в коде. Как минимум -- нужно объявить (через enum или #define в C, через const int в C++) константу и ей пользоваться, самой константе же дать осмысленные имя и комментарий. За исключением нулей, единиц и ряда очевидных констант. Рекомендую следовать такому же стилю.

Спасибо за ваш комментарий.

Она-то как раз в даташите указывается. С погрешностью порядка 5%, но всё таки известна.

В статье я приложил скриншот из даташита, он как раз и показывает возможную разбежку частоты низкочастотного резонатора от 17 кГц до 47 кГц.

Мне представляется сомнительной исходная идея - точность встроенного генератора недостаточна для работы интерфейса, поэтому измерим с его помощью внешний источник тактового сигнала и получим точность выше - как то странно.

Другое дело, если мы заранее предполагаем некоторый стандартный набор кварцев, существенно (на десятки процентов) отличающихся по частоте и выбираем 1 из них, как, собственно и сделано.

Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Истории