|
|
  |
Программный таймер, как красиво обойти переполнение? |
|
|
|
Jan 24 2014, 09:53
|

Местный
  
Группа: Участник
Сообщений: 318
Регистрация: 21-07-06
Из: Минск
Пользователь №: 18 986

|
Есть прерывание с периодом 1 мс, где инкрементируется 32-разрядный счетчик: Код void SysTick_Handler(void) { TSysTimer::Counter++; } При необходимости формирования интервала программа может запустить один из программных счетчиков: Код void TSoftTimer::Start(uint32_t t) { FinalCount = TSysTimer::Counter + t; } Истек ли интервал, проверяется так: Код bool TSoftTimer::Over(void) { return(TSysTimer::Counter >= FinalCount); } Всё хорошо, но примерно через 50 дней счетчик TSysTimer::Counter переполнится и всё сломается. Как красиво это обойти? При этом можно наложить ограничение, что формируемый интервал никогда не превышает половины (или даже четверти) периода счетчика, а проверка переполнения тоже делается часто, много раз за период счетчика.
--------------------
|
|
|
|
|
Jan 24 2014, 11:21
|

Местный
  
Группа: Свой
Сообщений: 397
Регистрация: 3-12-09
Из: Россия, Москва
Пользователь №: 54 040

|
не знаю, как на ARM, а для x64 вычитание не прокатывает (gcc 4.7.2): CODE int gggg( uint32_t a1, uint32_t a2 ) { 40076c: 55 push %rbp 40076d: 48 89 e5 mov %rsp,%rbp 400770: 89 7d fc mov %edi,-0x4(%rbp) 400773: 89 75 f8 mov %esi,-0x8(%rbp) return (a2 - a1) <= 0; 400776: 8b 45 f8 mov -0x8(%rbp),%eax 400779: 3b 45 fc cmp -0x4(%rbp),%eax 40077c: 0f 94 c0 sete %al 40077f: 0f b6 c0 movzbl %al,%eax } 400782: 5d pop %rbp 400783: c3 retq
|
|
|
|
|
Jan 24 2014, 12:24
|

Местный
  
Группа: Участник
Сообщений: 318
Регистрация: 21-07-06
Из: Минск
Пользователь №: 18 986

|
О, спасибо, точно! А я было зациклился на сравнениях и чуть не погряз в условиях. Код TSoftTimer::TSoftTimer(uint32_t t = 0) { Interval = t; }
void TSoftTimer::Start(uint32_t t) { Interval = t; StartCount = TSysTimer::Counter; }
void TSoftTimer::Start() { StartCount = TSysTimer::Counter; }
void TSoftTimer::SetInterval(uint32_t t) { Interval = t; }
bool TSoftTimer::Over(void) { return(TSysTimer::Counter - StartCount >= Interval); }
--------------------
|
|
|
|
|
Jan 24 2014, 13:49
|
Гуру
     
Группа: Свой
Сообщений: 4 256
Регистрация: 17-02-06
Пользователь №: 14 454

|
А я вечно горожу проверку что типа если текущее меньше начального, то сложить хвост и начала... вот я балда  ))) хотя последний раз я дошел до того что просто в таймере сделал if(Delay >0) Delay --; и если надо выждать 10 тиков, то Delay = 10; и проверяю что он не 0.... у вас все равно переменная Start задействована, так чего ей значение хранить, когда она может просто считаться назад?
|
|
|
|
|
Jan 24 2014, 18:48
|
Гуру
     
Группа: Свой
Сообщений: 4 256
Регистрация: 17-02-06
Пользователь №: 14 454

|
Цитата(mantech @ Jan 24 2014, 21:50)  Дак 64 бита никогда не переполнятся за всю жизнь  да ну бросьте. это всего навсего 584 942.41735507203247082699137494 года ничто по сравнению с жизнью вселенной... если тик микросекунда..., а если пико?
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|