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));


Комментарии