|
|
  |
Вычисление делителя для таймера. |
|
|
|
Jan 23 2017, 15:48
|
Профессионал
    
Группа: Участник
Сообщений: 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
|
|
|
|
|
Jan 25 2017, 10:52
|
Профессионал
    
Группа: Участник
Сообщений: 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
|
|
|
|
|
Jan 25 2017, 11:19
|
Профессионал
    
Группа: Участник
Сообщений: 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.
|
|
|
|
|
Jan 25 2017, 11:56
|
Профессионал
    
Группа: Участник
Сообщений: 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
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|