STM32F1XX коррекция RTC
Хотел поделиться опытом, как улучшить точность хода часов в серии STM32F1XX до отклонения 3сек в месяц.
У более старших камней, учтены уже ошибки 100 серии и коррекция часов может и ускорять ход и замедлять.
В 100 серии, можно только пропускать такты часового резонатора, через каждые 2^20 тактов = 32сек.
Отталкиваясь от AN2604 алгоритм следующий
1. Выводим частотму кварцевого резонатора через аппаратный делитель на 64 на ножку Tamper.
2. Измеряем частотомером частоту равную примерно 512Гц.
3. Определяемся с установкой предделителя.
Тут можно остановиться поподбробнее.
Коррекция часов позволяет компенсировать отклонения в пределах 0-127ppm.
Можно легко посчитать диапазон допустимого отклонения частоты для диапазона предделителя 32765-32771.
формула - (ppm/1000000+1)*(предделитель/64)
32765 (0...127ppm) - 511,9531...512,0181
32766 (0...127ppm) - 511,9688...512,0338
32767 (0...127ppm) - 511,9844...512,0494
32768 (0...127ppm) - 512,0000...512,0650
32769 (0...127ppm) - 512,0156...512,0807
32770 (0...127ppm) - 512,0313...512,0963
32771 (0...127ppm) - 512,0469...512,1119
Видно что, диапазоны коррекции предделителей пересекаются между собой и вполне можно обойтись тремя предделителями:
32765, 32768, 32771
для расчета предделителя написал маленькую функцию, на вход необходимо задать частоту по частотометру * 10000
uint16_t Prescaller_calc (uint32_t in)
{
const uint32_t Correct_table [3][2] =
{
{32765, 5120000},
{32768, 5120650},
{32771, 5120650},
};
if (in<Correct_table[0][1]) return Correct_table[0][0]-1;
if (in>Correct_table[2][1]) return Correct_table[2][0]-1;
return Correct_table[1][0]-1;
// -1 - формат записи предделителя в МК
}
4. После выбора предделителя необходимо расчитать отклонение частоты от номинальной.
формула - (частота по частотомеру/(предделитель/64)-1)*1000000ppm
5. Далее, используя таблицу коррекции в AN2604, необходимо определить коэффициент коррекции.
для этого тоже написал функцию, на вход надо подать отклонение в ppm
uint8_t Correct_time_calc (uint16_t in)
{
//таблица коррекции
const uint16_t Correct_table [128] = {0,2,5,7,10,12,15,17,20,22,25,27,30,32,35,37,40,42,44,47,49,52,54,57,59,62,64,67,69,
72,74,77,79,82,84,87,89,97,94,96,99,101,104,106,109,111,114,116,119,121,124,126,129,131,133,136,138,141,143,
146,148,151,153,156,158,161,163,166,168,171,173,176,178,180,183,185,188,190,193,195,198,200,203,205,208,210,
213,215,218,220,222,225,227,230,232,235,237,240,242,245,247,250,252,255,257,260,262,264,267,269,272,274,277,
279,282,284,287,289,292,294,297,299,302,304,307,309,311,314};
int16_t res=1;//выполнение цикла минимум 1 раз
uint8_t i;
for (i=0; (i < 128) && (res>0); ++i)
{
res = in-Correct_table[i];
}
if (res==0 || (res>(Correct_table[i-1]-in))) return i; //выбор ближайшего числа
else return (i-1);
}
6. Записать новый предделитель и коэффициент коррекции в МК
hrtc.Init.AsynchPrediv = Prescaller_calc(Freq512); // Freq512 - частота по частотометру * 10000
Corr = (uint16_t)(((5100000.0f+(float)Freq512)/((float)(hrtc.Init.AsynchPrediv+1)*10000.0f/64.0f)-1.0f)*1000000.0f);
if (HAL_RTC_Init(&hrtc) != HAL_OK)
{
Error_Handler();
}
HAL_RTCEx_SetSmoothCalib(&hrtc,0,0,(uint32_t)Correct_time_calc(Corr));
Комментарии
Отправить комментарий