Необходимо реализовать синхронизацию даты/времени в устройстве с внешним хостом (по SNTP и другим протоколам) с точностью до сотен микросекунд. Задача, получившая эталонное время вызывает следующую функцию и передаёт ей структуру с временем:
CODE
void RTC_TimeSync(vTime DateTime)
{
uint32_t TimeReg, DateReg;
uint32_t SSR_old, SSR_new;
// Преобразование времени в BCD
TimeReg = ((DateTime.Sec % 10) & 0x0F);
TimeReg |= (((DateTime.Sec / 10) & 0x07) << 4);
TimeReg |= (((DateTime.Min % 10) & 0x0F) << 8);
TimeReg |= (((DateTime.Min / 10) & 0x07) << 12);
TimeReg |= (((DateTime.Hour % 10) & 0x0F) << 16);
TimeReg |= (((DateTime.Hour / 10) & 0x03) << 20);
// Преобразование даты в BCD
DateReg = ((DateTime.Day % 10) & 0x0F);
DateReg |= (((DateTime.Day / 10) & 0x03) << 4);
DateReg |= (((DateTime.Month % 10) & 0x0F) << 8);
DateReg |= (((DateTime.Month / 10) & 0x01) << 12);
DateReg |= (((DateTime.Year % 10) & 0x0F) << 16);
DateReg |= (((DateTime.Year / 10) & 0x0F) << 20);
// Пишем ключи для доступа к регистрам RTC
RTC->WPR = RTC_KEY1;
RTC->WPR = RTC_KEY2;
if (!(RTC->ISR & RTC_ISR_INITF)) // RTC не в режиме инициализации?
{
RTC->ISR = (uint32_t)RTC_INIT_MASK; // Переходим в режим инициализации RTC
while (!(RTC->ISR & RTC_ISR_INITF)); // Ждём установки бита INIT в RTC->ISR
}
RTC->TR = TimeReg; // Пишем время в RTC
RTC->DR = DateReg; // Пишем дату в RTC
RTC->ISR &= ~RTC_ISR_INIT; // Выходим из режима инициализации RTC
RTC->WPR = 0xFF; // Включаем защиту регистров RTC
// Пишем ключи для доступа к регистрам RTC
RTC->WPR = RTC_KEY1;
RTC->WPR = RTC_KEY2;
SSR_old = RTC->SSR; // Текущее значение синхронного счётчика
SSR_new = RTC_PREDIV_S - ((DateTime.t100mks * 16384) / 10000); // Желаемое значение синхронного счётчика
while (RTC->ISR & RTC_ISR_SHPF);
if (SSR_new >= SSR_old) // К счётчику нужно прибавить (откат времени назад)
RTC->SHIFTR = SSR_new - SSR_old;
else // От счётчика нужно отнять (приращение времени)
RTC->SHIFTR = ((16383 - SSR_old) + SSR_new) | RTC_SHIFTR_ADD1S;
RTC->WPR = 0xFF;
}
RTC_PREDIV_S = 0x3FFF
RTC_PREDIV_A = 0x01
Дата и время (до секунд) синхронизируется нормально, а вот коррекция доли секунд не отрабатывает. Вообще. Т.е. как будто я пишу только дату и время до секунд.
Если заменить RTC простым счётом по таймеру, то синхронизация проходит верно и часы идут синхронно с удалёнными часами (т.е. пересчёт между форматами времени сделан верно).
Сообщение отредактировал IgorKossak - Nov 26 2012, 07:20
Причина редактирования: [codebox] для длинного кода!!!