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

Вычисление делителя для таймера.

Я хочу чтоб таймер посто тикал. Каждый тик 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

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


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

Странно считаете - либо включайте логику, либо не округляйте 13,(8) (периодическую дробь) так грубо до 13,8.

При расчетах Вы сначала возводите 72M в -1 степень, а потом проделываете еще раз то же самое (плюс деление на 2) - не кажется странным, что в итоге получается что-то, не отличающееся в 2 раза?

Итого - делитель нужен 36000, значит в регистр пишем 35999 (т.к. 0 соответствует делению на 1).

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

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


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

Странно считаете - либо включайте логику, либо не округляйте 13,(8) (периодическую дробь) так грубо до 13,8.

При расчетах Вы сначала возводите 72M в -1 степень, а потом проделываете еще раз то же самое (плюс деление на 2) - не кажется странным, что в итоге получается что-то, не отличающееся в 2 раза?

Итого - делитель нужен 36000, значит в регистр пишем 35999 (т.к. 0 соответствует делению на 1).

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

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


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

Кабы "чукча" был больше "читателем", он нашел бы на форуме ответы на большую часть своих вопросов, не задавая их.

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


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

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

скажем соорудить что нибудь такое

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

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


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

Уже писали, надо вычислять разность между текущим значением таймера и порогом, и сравнивать ее с нулем, тогда переполнения таймера не страшны.

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


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

Уже писали, надо вычислять разность между текущим значением таймера и порогом, и сравнивать ее с нулем, тогда переполнения таймера не страшны.

а я проверял

uint16_t var = 0Xfff0;
var += 0Xff;
printf("var is %x /n", var);

при переполнении происходит rollover.

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


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

а я проверял

при переполнении происходит rollover.

Только ваша функция сравнения так не делает. Проверьте.

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


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

Только ваша функция сравнения так не делает. Проверьте.

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

 

вобщем тут в чем проблема. переполнение можно отследить в 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

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


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

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

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

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

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

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

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

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

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

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