Продолжаю веселиться с микроконтроллерами STC, и опять попалась интересная задачка. В общем, частота на которой работает мк определяется хост компьютером по 8ми 16-битным числам, которые передает хосту контроллер в инфопакете. MCU измеряет какую-то часть временной диаграммы последовательности двух байт {0x7f, 0x7f} и передает 8 измерений хосту в инфопакете вместе с другими настройками. Из них надо получить частоту кварца/RC осциллятора в мегагерцах. Получилась хорошая задачка решающаяся небольшим количеством школьной математики.
Время передачи нескольких (n) бит идущих с известным баудрейтом измеряется 8 раз
У таймера который их меряет есть прескейлер, делящий частоту мк в сколько раз.
Надо найти частоту мк.
Давайте теперь запилим небольшое уравнение с парой параметров
Где T — период с которым считает счетчик. Теперь, учтем наличие прескейлера и вспомним как связаны частота и период:
Из (1) и (2) имеем:
Здесь Fmcu — искомая частота камня. Выглядит аппетитно, едем дальше и приводим это к божескому виду.
Или
Осталось определить два параметра: n и prescaler.
Можно на это, конечно забить, обозвать альфа и вычислить экспериментально,
Но это «не тру, не метально круто и не замогильно ужастно» (с). И даст ошибку округления. Но по счастью я заметил, что при кварце на 12M значение счетчика является временем 7 битного высокого уровня (лог. анализатор — хорошая штука!)
=> n = 7 (что кстати было очевидно с самого начала)
А раскурив даташит узнаем, что прескейлер таймера может быть либо 1 либо 12.
Есть еще прескейлер системного клока, но как видно из вышесказанного — он не используется.
=> prescaler = 12.
Отсюда получаем частоту, и переводим в мегагерцы. И оно дает правдоподобные значения, хотя и дает некоторое отклонение от того, что говорит официальная софтина.
Потому, я решил перепроверить:
Официальная тула сказала: 12.03912 Mhz
Логический анализатор выдал:
0x16b 0x16b 0x16b 0x16b 0x16b 0x16b 0x16b 0x16c
Преобразуем в флоат, берем среднее
float avg = ( (float) (0x16c * 7) + (float) 0x16d )/ 8.0; (Все помнят зачем я добавил +1 ? ) |
Это дает нам 364.125000, запишем теперь наше уравнение и найдем n
Получилось, что n = 6.968482746247234, что достаточно близко к 7. Отклонение где-то 0.03. Потому я тупо забил 6.97 как коэффицент, чтобы поведение было как у STC ISP tool, но тут надо понимать, что ошибку нам дают:
- Отклонение баудрейта от заданного, вызванного тем, как работает баудрейт прескейлер в преобразователе с usb на уарт.
- Погрешность кварца, который тактирует наш преобразователь (сверхточный кварц туда никто в здравом уме ставить не будет)
- Погрешность которую может вызвать сам дизайн преобразователя, задержки на мосфетах и т.п.
Можно конечно спаять для таких измерений донгл с точным кристаллом, откалибровать как следует и выяснить коэффицент сверхточно и только для этого сверхточного донгла…
Но оно вообще надо?
Моя реализация вышеуказанного матана тихонечко лежит на шитхабе