реклама на сайте
подробности

 
 
 
Reply to this topicStart new topic
> Вычисление делителя для таймера.
Jenya7
сообщение Jan 23 2017, 15:48
Сообщение #1


Профессионал
*****

Группа: Участник
Сообщений: 1 778
Регистрация: 29-03-12
Пользователь №: 71 075



Я хочу чтоб таймер посто тикал. Каждый тик 1 милисекунда. А я буду считывать каунтер (TIM7->CNT) и буду знать сколько милисекунд он нащелкал.
Вычисления такие. Частота кристала CPU = 72 мега. Делитель = 2 (иначе не влезем в размер прескейлер регистра). 1/72M = 13.8ns. 1ms/13.8ns/2 = 36231.
Следовательно
Код
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_TimeBaseStructure.TIM_Period = 0xFFFF;    
TIM_TimeBaseStructure.TIM_Prescaler = 36231;  
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV2;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM7, &TIM_TimeBaseStructure);
TIM_Cmd(TIM7,ENABLE);

Правильно ли я вычисляю?

Сообщение отредактировал Jenya7 - Jan 23 2017, 16:22
Go to the top of the page
 
+Quote Post
ohmjke
сообщение Jan 23 2017, 19:59
Сообщение #2


Частый гость
**

Группа: Участник
Сообщений: 116
Регистрация: 27-01-10
Из: СПб
Пользователь №: 55 094



Странно считаете - либо включайте логику, либо не округляйте 13,(8) (периодическую дробь) так грубо до 13,8.
При расчетах Вы сначала возводите 72M в -1 степень, а потом проделываете еще раз то же самое (плюс деление на 2) - не кажется странным, что в итоге получается что-то, не отличающееся в 2 раза?
Итого - делитель нужен 36000, значит в регистр пишем 35999 (т.к. 0 соответствует делению на 1).

Сообщение отредактировал ohmjke - Jan 23 2017, 20:02
Go to the top of the page
 
+Quote Post
Jenya7
сообщение Jan 24 2017, 08:13
Сообщение #3


Профессионал
*****

Группа: Участник
Сообщений: 1 778
Регистрация: 29-03-12
Пользователь №: 71 075



Цитата(ohmjke @ Jan 24 2017, 00:59) *
Странно считаете - либо включайте логику, либо не округляйте 13,(8) (периодическую дробь) так грубо до 13,8.
При расчетах Вы сначала возводите 72M в -1 степень, а потом проделываете еще раз то же самое (плюс деление на 2) - не кажется странным, что в итоге получается что-то, не отличающееся в 2 раза?
Итого - делитель нужен 36000, значит в регистр пишем 35999 (т.к. 0 соответствует делению на 1).

я понял. спасибо.
Go to the top of the page
 
+Quote Post
ViKo
сообщение Jan 24 2017, 08:40
Сообщение #4


Универсальный солдатик
******

Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362



Кабы "чукча" был больше "читателем", он нашел бы на форуме ответы на большую часть своих вопросов, не задавая их.
Go to the top of the page
 
+Quote Post
Jenya7
сообщение Jan 25 2017, 10:52
Сообщение #5


Профессионал
*****

Группа: Участник
Сообщений: 1 778
Регистрация: 29-03-12
Пользователь №: 71 075



да. я задался этим вопросом вот по какому поводу. хочу периодически выполнять какие нибудь действия.
скажем соорудить что нибудь такое
Код
static inline uint16_t GetTimerCount(TIM_TypeDef *timer)
{
  return timer->CNT;
}

void SYSTIMER_Set(TIM_TypeDef *timer, uint16_t *compare_val, uint32_t count_ms)
{
    uint16_t timer_count_val = GetTimerCount(timer);
    *compare_val = timer_count_val + count_ms;
}

uint32_t SYSTIMER_Elapsed(TIM_TypeDef *timer, uint16_t *compare_val)
{
    uint16_t timer_count_val = GetTimerCount(timer);
    return (timer_count_val >= *compare_val);
}

и потом
Код
while(1)
{
    if (SYSTIMER_Elapsed(TIM7, &compare_val))
    {
         //do something every 100ms
         SYSTIMER_Set(TIM7, &compare_v, 100);
    }
}

и прерываний не надо каждую милисекунду. вопрос насколько хорош такой метод?

Сообщение отредактировал Jenya7 - Jan 25 2017, 10:56
Go to the top of the page
 
+Quote Post
ViKo
сообщение Jan 25 2017, 11:06
Сообщение #6


Универсальный солдатик
******

Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362



Уже писали, надо вычислять разность между текущим значением таймера и порогом, и сравнивать ее с нулем, тогда переполнения таймера не страшны.
Go to the top of the page
 
+Quote Post
Jenya7
сообщение Jan 25 2017, 11:19
Сообщение #7


Профессионал
*****

Группа: Участник
Сообщений: 1 778
Регистрация: 29-03-12
Пользователь №: 71 075



Цитата(ViKo @ Jan 25 2017, 17:06) *
Уже писали, надо вычислять разность между текущим значением таймера и порогом, и сравнивать ее с нулем, тогда переполнения таймера не страшны.

а я проверял
Код
uint16_t var = 0Xfff0;
var += 0Xff;
printf("var is %x /n", var);

при переполнении происходит rollover.
Go to the top of the page
 
+Quote Post
ViKo
сообщение Jan 25 2017, 11:33
Сообщение #8


Универсальный солдатик
******

Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362



Цитата(Jenya7 @ Jan 25 2017, 14:19) *
а я проверял
при переполнении происходит rollover.

Только ваша функция сравнения так не делает. Проверьте.
Go to the top of the page
 
+Quote Post
Jenya7
сообщение Jan 25 2017, 11:56
Сообщение #9


Профессионал
*****

Группа: Участник
Сообщений: 1 778
Регистрация: 29-03-12
Пользователь №: 71 075



Цитата(ViKo @ Jan 25 2017, 17:33) *
Только ваша функция сравнения так не делает. Проверьте.

мда. понял. спасибо.

вобщем тут в чем проблема. переполнение можно отследить в while. как в этом примере.
Код
void delay_1us (void) {
  uint32_t start, end;
  
  start = DWT_CYCCNT;
  end = start + HCLK/1000000;
  if (end < start) while (dwt_cnt() > start);
  while (end >= dwt_cnt());
}


но если как у меня - в одном месте установили порог а в другом сравниваем - без дополнительных флагов не обойтись.

скажем такой подход не решает проблему переполнения
Код
uint32_t DWT_Get(void)
{
    return DWT_CYCCNT;
}

uint8_t DWT_Compare(int32_t tp)
{
    return (((int32_t)DWT_Get() - tp) < 0);
}

void DWT_Delay(uint32_t us) // microseconds
{
    int32_t tp = DWT_Get() + us * (SystemCoreClock/1000000));
    while (DWT_Compare(tp));
}


Сообщение отредактировал Jenya7 - Jan 25 2017, 15:12
Go to the top of the page
 
+Quote Post

Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 19th July 2025 - 05:27
Рейтинг@Mail.ru


Страница сгенерированна за 0.01462 секунд с 7
ELECTRONIX ©2004-2016