Занимательная математика

Продолжаю веселиться с микроконтроллерами STC, и опять попалась интересная задачка. В общем, частота на которой работает мк определяется хост компьютером по 8ми 16-битным числам, которые передает хосту контроллер в инфопакете. MCU измеряет какую-то часть временной диаграммы последовательности двух байт {0x7f, 0x7f} и передает 8 измерений хосту в инфопакете вместе с другими настройками. Из них надо получить частоту кварца/RC осциллятора в мегагерцах. Получилась хорошая задачка решающаяся небольшим количеством школьной математики.

Время передачи нескольких (n) бит идущих с известным баудрейтом измеряется 8 раз
У таймера который их меряет есть прескейлер, делящий частоту мк в сколько раз.
Надо найти частоту мк.
Давайте теперь запилим небольшое уравнение с парой параметров

<br /> T * average\_counter\_value = \frac{n}{baudrate} \hfill (1)<br />

Где T — период с которым считает счетчик. Теперь, учтем наличие прескейлера и вспомним как связаны частота и период:

<br /> T = \frac{1}{F/prescaler} = \frac{prescaler}{F} \hfill (2)<br />

Из (1) и (2) имеем:

<br /> \frac{prescaler}{Fmcu} = \frac{n}{baudrate * average\_counter\_value}<br />

Здесь Fmcu — искомая частота камня. Выглядит аппетитно, едем дальше и приводим это к божескому виду.

<br /> Fmcu = \frac{baudrate * average\_counter\_value * prescaler}{ n } Hz<br />

Или

<br /> Fmcu = \frac{baudrate * average\_counter\_value * prescaler}{ n * 1000000} MHz<br />

Осталось определить два параметра: 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 на уарт.
  • Погрешность кварца, который тактирует наш преобразователь (сверхточный кварц туда никто в здравом уме ставить не будет)
  • Погрешность которую может вызвать сам дизайн преобразователя, задержки на мосфетах и т.п.

Можно конечно спаять для таких измерений донгл с точным кристаллом, откалибровать как следует и выяснить коэффицент сверхточно и только для этого сверхточного донгла…
Но оно вообще надо?

Моя реализация вышеуказанного матана тихонечко лежит на шитхабе

 

Добавить комментарий