jenya7 0 23 января, 2017 Опубликовано 23 января, 2017 (изменено) · Жалоба Я хочу чтоб таймер посто тикал. Каждый тик 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); Правильно ли я вычисляю? Изменено 23 января, 2017 пользователем Jenya7 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ohmjke 0 23 января, 2017 Опубликовано 23 января, 2017 (изменено) · Жалоба Странно считаете - либо включайте логику, либо не округляйте 13,(8) (периодическую дробь) так грубо до 13,8. При расчетах Вы сначала возводите 72M в -1 степень, а потом проделываете еще раз то же самое (плюс деление на 2) - не кажется странным, что в итоге получается что-то, не отличающееся в 2 раза? Итого - делитель нужен 36000, значит в регистр пишем 35999 (т.к. 0 соответствует делению на 1). Изменено 23 января, 2017 пользователем ohmjke Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jenya7 0 24 января, 2017 Опубликовано 24 января, 2017 · Жалоба Странно считаете - либо включайте логику, либо не округляйте 13,(8) (периодическую дробь) так грубо до 13,8. При расчетах Вы сначала возводите 72M в -1 степень, а потом проделываете еще раз то же самое (плюс деление на 2) - не кажется странным, что в итоге получается что-то, не отличающееся в 2 раза? Итого - делитель нужен 36000, значит в регистр пишем 35999 (т.к. 0 соответствует делению на 1). я понял. спасибо. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 24 января, 2017 Опубликовано 24 января, 2017 · Жалоба Кабы "чукча" был больше "читателем", он нашел бы на форуме ответы на большую часть своих вопросов, не задавая их. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jenya7 0 25 января, 2017 Опубликовано 25 января, 2017 (изменено) · Жалоба да. я задался этим вопросом вот по какому поводу. хочу периодически выполнять какие нибудь действия. скажем соорудить что нибудь такое 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); } } и прерываний не надо каждую милисекунду. вопрос насколько хорош такой метод? Изменено 25 января, 2017 пользователем Jenya7 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 25 января, 2017 Опубликовано 25 января, 2017 · Жалоба Уже писали, надо вычислять разность между текущим значением таймера и порогом, и сравнивать ее с нулем, тогда переполнения таймера не страшны. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jenya7 0 25 января, 2017 Опубликовано 25 января, 2017 · Жалоба Уже писали, надо вычислять разность между текущим значением таймера и порогом, и сравнивать ее с нулем, тогда переполнения таймера не страшны. а я проверял uint16_t var = 0Xfff0; var += 0Xff; printf("var is %x /n", var); при переполнении происходит rollover. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 25 января, 2017 Опубликовано 25 января, 2017 · Жалоба а я проверял при переполнении происходит rollover. Только ваша функция сравнения так не делает. Проверьте. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jenya7 0 25 января, 2017 Опубликовано 25 января, 2017 (изменено) · Жалоба Только ваша функция сравнения так не делает. Проверьте. мда. понял. спасибо. вобщем тут в чем проблема. переполнение можно отследить в 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)); } Изменено 25 января, 2017 пользователем Jenya7 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться