Перейти к содержанию
    

Правильность отсчета времени в таймере и RTC

Здравствуйте. Прошу помощи по следующим вопросам.

1. Во всех примерах пределитель на RTC необходимо ставить 32767 при внешнем кварце на 32768. Когда ставится данный пределитель часы считают очень медленно 1 секунда где то в 10-15мин. Начал изменять путем подбора вышел на значение пределителя где то 32. ЧТО ЭТО ЗНАЧИТ.

2. В таймере то же какой то глючек. Может ошибка общая с 1 пунктом. Частота шины 36МГц. Опрашивается через функцию RCC_GetClocksFreq. Ставлю пределитель 36000 и счет до 1000 прерывание срабатывает гораздо раньше.

 

Контроллер STM32F103RC. 16МГц кварц, на RTC кварц 32768.

 

P.S. Нет источника питания. Питание контроллера взято с ST-Link V2.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Здравствуйте. Прошу помощи по следующим вопросам.

1. Во всех примерах пределитель на RTC необходимо ставить 32767 при внешнем кварце на 32768. Когда ставится данный пределитель часы считают очень медленно 1 секунда где то в 10-15мин. Начал изменять путем подбора вышел на значение предlелителя где то 32. ЧТО ЭТО ЗНАЧИТ.

 

Контроллер STM32F103RC. 16МГц кварц, на RTC кварц 32768.

Это значит, что у вас ошибка в коде. Если кварц на 32768 Гц, то значение предделителя должно быть 32768, что приводит к ежесекундному увеличению времени на 1 секунду.

PS: Вы хотя бы код инициализации модуля RTC выложили.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Код инициализации:

    RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_BKP, ENABLE);

    /* LSI clock stabilization time */
    for(tmp=0;tmp<5000;tmp++) {; }

    if (BKP_ReadBackupRegister(RTC_CONSISTENCY_CHECK_REG) != RTC_CONSYSTENCY_KEY_VALUE) {
        PWR_BackupAccessCmd(ENABLE);
        BKP_DeInit();
        RCC_LSEConfig(RCC_LSE_ON);
        while (RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET) {; }
        RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);
        RCC_RTCCLKCmd(ENABLE);
        RTC_WaitForSynchro();
        //RTC_SetPrescaler(32767); /* RTC period = RTCCLK/RTC_PR = (32.768 KHz)/(32767+1) */
        RTC->PRLL  = 0x7FFF;
        //RTC->PRLL  = 0x20;

        RTC_WaitForLastTask();
        RTC_ITConfig(RTC_IT_SEC, ENABLE);
        RTC_WaitForLastTask();
        BKP_WriteBackupRegister(RTC_CONSISTENCY_CHECK_REG, RTC_CONSYSTENCY_KEY_VALUE);
    } else {
        RTC_WaitForSynchro();
        RTC_ITConfig(RTC_IT_SEC, ENABLE);
        RTC_WaitForLastTask();
    }

2 в 32-ой степени ни на что не намекает?

 

Немного не понял что имелось ввиду

Изменено пользователем IgorKossak
[codebox] для длинного кода. [code]-для короткого!!!

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

"…вышел на значение пределителя где то 32. ЧТО ЭТО ЗНАЧИТ."

 

Вот и пойми что имелось ввиду (;

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Здравствуйте. Прошу помощи по следующим вопросам.

1. Во всех примерах пределитель на RTC необходимо ставить 32767 при внешнем кварце на 32768. Когда ставится данный пределитель часы считают очень медленно 1 секунда где то в 10-15мин. Начал изменять путем подбора вышел на значение пределителя где то 32. ЧТО ЭТО ЗНАЧИТ.

2. В таймере то же какой то глючек. Может ошибка общая с 1 пунктом.

Непонятно, что именно вы называете ошибкой. В таймере ошибки точно нет. Наверное она у вас в голове.

Если вам непонятно почему при кварце 32768 задаётся 32767, то тут стандартный подход. При задании 0 = делит 1:1. Иначе получится как в MSP430FR433 к примеру. При задании 0 и 1 делит на 1. При задании 65535 делит на 65535. Поделить на 65536 не получается, хотя таймер 16-ти битный. Вопрос: так в каком CPU косяк?

А реализуется эта фича просто. Сравнение производится после вычитания.

Задаётся предделитель как правило так:

TIM_PWM_LIGHT->PSC = FPWM_PSC-1; // Прескалер

TIM_PWM_LIGHT->ARR = FPWM_MAX-1; // Частота ШИМ 200 Гц

 

Частота шины 36МГц. Опрашивается через функцию RCC_GetClocksFreq. Ставлю пределитель 36000 и счет до 1000 прерывание срабатывает гораздо раньше.

Контроллер STM32F103RC. 16МГц кварц, на RTC кварц 32768.

 

P.S. Нет источника питания. Питание контроллера взято с ST-Link V2.

Там, насколько я помню частота таймера в 2 раза выше чем частота шины к которой он подключен.

 

32768 = 2^15. То есть по сути 16-тый разряд двоичного счётчика. Вот на что вам намекали.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

В RTC у STMа есть особенность, что они довольно критичны к качеству кварца. Точнее, к самому кварцу, его обвязке (в лице двух конденсаторов) и монтажу (количеству флюса вокруг).

В погоне за микропотреблением узел получился весьма нежным.

 

Можно вывести на ногу CLKOUT частоту кварца (подробности - в reference manual) и проверить осциллографом, что оно работает стабильно.

Напрямую в ноги часового кварца тыкать бесполезно - сразу же останавливается.

 

Очень похоже, что кварц постоянно останавливается-запускается.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

В RTC у STMа есть особенность, что они довольно критичны к качеству кварца. Точнее, к самому кварцу, его обвязке (в лице двух конденсаторов) и монтажу (количеству флюса вокруг).

В погоне за микропотреблением узел получился весьма нежным.

 

Можно вывести на ногу CLKOUT частоту кварца (подробности - в reference manual) и проверить осциллографом, что оно работает стабильно.

Напрямую в ноги часового кварца тыкать бесполезно - сразу же останавливается.

 

Очень похоже, что кварц постоянно останавливается-запускается.

 

Дело в том что пробовал поднять RTC на LSI. Ситуация та же. Изменение регистра счета происходит примерно через 10-15 мин

 

Инициализация таймера:

RCC_GetClocksFreq(&rcc_Clocks);

 

//Включается тактирование таймера TIM6

RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6,ENABLE);

// Настраиваем делитель что таймер тикал 1000 раз в секунду (

TIM6->PSC = (rcc_Clocks.PCLK1_Frequency / 1000) - 1; //36000

// Чтоб прерывание случалось раз в секунду

TIM6->ARR = 1000 ;

//разрешаем прерывание от таймера

TIM6->DIER |= TIM_DIER_UIE;

// Начать отсчёт!

TIM6->CR1 |= TIM_CR1_CEN;

//Разрешение TIM6_DAC_IRQn прерывания

NVIC_EnableIRQ (TIM6_IRQn);

 

СКАЖИТЕ ПОЖАЛУЙСТА через какое время должно срабатывать прерывание

Изменено пользователем dimon_rub

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Код выглядит нормально.

Разве что, не очень понятно, что содержится в rcc_Clocks. Можно легко и просто испортить дефайны, чтобы там оказалось что-то не то.

 

Единственное замечание: у STM'ок есть кэширование регистррв таймера (в т.ч. ARR). Чтобы принудительно его обновить, надо сделать TIMx->EGR = TIM_EGR_UG;

 

 

PS дурацкий вопрос: это точно STM32F103 ? Не китаец? ;-)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Код выглядит нормально.

Разве что, не очень понятно, что содержится в rcc_Clocks. Можно легко и просто испортить дефайны, чтобы там оказалось что-то не то.

 

 

 

Единственное замечание: у STM'ок есть кэширование регистррв таймера (в т.ч. ARR). Чтобы принудительно его обновить, надо сделать TIMx->EGR = TIM_EGR_UG;

 

Спасибо попробую.

 

 

PS дурацкий вопрос: это точно STM32F103 ? Не китаец? ;-)

 

RCC_ClocksTypeDef rcc_Clocks;

 

Поднял RTC на LSI. На LSE не как не хочет. Совсем начал зависать наверно действительно что то с кварцом. На SLI вроде работает но есть одно каждая десятая секунда как будто задерживается (9 в логе). Возможно неправильно выбран пределитель. По аналогии с LSE поставил 39999. ПОДСКАЖИТЕ какой нужно. Вывод лога с USART опрос каждую секунду по таймеру регистров счета:

RTC_GetCounter=00000000<0><0>; RTC_GetDivide00002783<0><0>

RTC_GetCounter=00000001<0><0>; RTC_GetDivide00006477<0><0>

RTC_GetCounter=00000002<0><0>; RTC_GetDivide00010172<0><0>

RTC_GetCounter=00000003<0><0>; RTC_GetDivide00013863<0><0>

RTC_GetCounter=00000004<0><0>; RTC_GetDivide00017553<0><0>

RTC_GetCounter=00000005<0><0>; RTC_GetDivide00021243<0><0>

RTC_GetCounter=00000006<0><0>; RTC_GetDivide00024936<0><0>

RTC_GetCounter=00000007<0><0>; RTC_GetDivide00028626<0><0>

RTC_GetCounter=00000008<0><0>; RTC_GetDivide00032316<0><0>

RTC_GetCounter=00000009<0><0>; RTC_GetDivide00036006<0><0>

RTC_GetCounter=00000009<0><0>; RTC_GetDivide00039699<0><0>

RTC_GetCounter=00000010<0><0>; RTC_GetDivide00003385<0><0>

RTC_GetCounter=00000011<0><0>; RTC_GetDivide00007073<0><0>

RTC_GetCounter=00000012<0><0>; RTC_GetDivide00010762<0><0>

RTC_GetCounter=00000013<0><0>; RTC_GetDivide00014452<0><0>

RTC_GetCounter=00000014<0><0>; RTC_GetDivide00018140<0><0>

RTC_GetCounter=00000015<0><0>; RTC_GetDivide00021827<0><0>

RTC_GetCounter=00000016<0><0>; RTC_GetDivide00025517<0><0>

RTC_GetCounter=00000017<0><0>; RTC_GetDivide00029204<0><0>

RTC_GetCounter=00000018<0><0>; RTC_GetDivide00032893<0><0>

RTC_GetCounter=00000019<0><0>; RTC_GetDivide00036582<0><0>

RTC_GetCounter=00000019<0><0>; RTC_GetDivide00000271<0><0>

RTC_GetCounter=00000020<0><0>; RTC_GetDivide00003957<0><0>

RTC_GetCounter=00000021<0><0>; RTC_GetDivide00007644<0><0>

RTC_GetCounter=00000022<0><0>; RTC_GetDivide00011330<0><0>

RTC_GetCounter=00000023<0><0>; RTC_GetDivide00015018<0><0>

RTC_GetCounter=00000024<0><0>; RTC_GetDivide00018703<0><0>

RTC_GetCounter=00000025<0><0>; RTC_GetDivide00022388<0><0>

RTC_GetCounter=00000026<0><0>; RTC_GetDivide00026073<0><0>

RTC_GetCounter=00000027<0><0>; RTC_GetDivide00029761<0><0>

RTC_GetCounter=00000028<0><0>; RTC_GetDivide00033446<0><0>

RTC_GetCounter=00000029<0><0>; RTC_GetDivide00037131<0><0>

RTC_GetCounter=00000029<0><0>; RTC_GetDivide00000813<0><0>

RTC_GetCounter=00000030<0><0>; RTC_GetDivide00004500<0><0>

RTC_GetCounter=00000031<0><0>; RTC_GetDivide00008185<0><0>

RTC_GetCounter=00000032<0><0>; RTC_GetDivide00011869<0><0>

RTC_GetCounter=00000033<0><0>; RTC_GetDivide00015554<0><0>

RTC_GetCounter=00000034<0><0>; RTC_GetDivide00019242<0><0>

RTC_GetCounter=00000035<0><0>; RTC_GetDivide00022927<0><0>

RTC_GetCounter=00000036<0><0>; RTC_GetDivide00026611<0><0>

RTC_GetCounter=00000037<0><0>; RTC_GetDivide00030294<0><0>

RTC_GetCounter=00000038<0><0>; RTC_GetDivide00033981<0><0>

RTC_GetCounter=00000039<0><0>; RTC_GetDivide00037665<0><0>

RTC_GetCounter=00000039<0><0>; RTC_GetDivide00001347<0><0>

RTC_GetCounter=00000040<0><0>; RTC_GetDivide00005032<0><0>

 

 

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

RCC_ClocksTypeDef rcc_Clocks;

 

Поднял RTC на LSI. На LSE не как не хочет. Совсем начал зависать наверно действительно что то с кварцом. На SLI вроде работает но есть одно каждая десятая секунда как будто задерживается (9 в логе). Возможно неправильно выбран пределитель. По аналогии с LSE поставил 39999. ПОДСКАЖИТЕ какой нужно. Вывод лога с USART опрос каждую секунду по таймеру регистров счета:

LSI - это внутренний RC-генератор, менее точный, чем кварцевый (LSE), частота его отличается от 40кГц, поэтому нужно подбирать значение предделителя под конкретный образецю

Изменено пользователем Pridnya

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Поднял RTC в качестве эксперимента на частоте основного кварца/128. Все вроде работает нормально но опять же при ежесекундном опросе через таймер есть глючек только теперь на каждой 10 секунде (в логе 10, 20 и т.д.). ОЧЕНЬ ИНТЕРЕСНО ЧТО ВРЕТ. Может это таймер. Сегодня еще поиграюсь. Может кто что посоветует где собака....

Изменено пользователем dimon_rub

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

То ли вы не можете внятно описать что вас не устраивает, то ли мы понять. Я так точно не могу понять.

Если вы опрашиваете узел, то могут быть биения. У вас асинхронный узел, по отношению к основному кварцу. Вы работаете на основном таймере при чтении RTC у вас будут биения. То есть раз в n число чтений либо проглатывать секунду либо удваивать.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А не должно быть так ?

// Чтоб прерывание случалось раз в секунду

TIM6->ARR = ( 1000 - 1 ) ;

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...