|
|
  |
Изменение периода таймера внутри прерывания, можно ли? |
|
|
|
Feb 1 2006, 16:11
|
Участник

Группа: Свой
Сообщений: 43
Регистрация: 26-01-06
Из: Минск, Беларусь
Пользователь №: 13 651

|
Можно ли изменять регистр периода таймера внутри процедуры обработки прерывания этого самого таймера ? "Тикнул" таймер, изменили период, снова тикнул - опять изменили. Вообще во время работы таймера его период менять можно. А именно в этом месте? Если нельзя, то как по-человеески организовать постоянно меняющиеся временные интервалы?
Сообщение отредактировал //Nikson - Feb 1 2006, 16:12
|
|
|
|
|
Feb 1 2006, 16:38
|
Гуру
     
Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882

|
Можно, если осторожно  Все дело в том, что если в режиме счета Count_Up период, задаваемый регистром CCR0, вы установите больше текущего, то все отработает нормально. Но если задаваемый период будет меньше текущего, то таймер сначала досчитает до переполнения 0xFFFF и только затем будет отрабатывать заданный период. Так что в последнем случае, кроме установки CCR0 нужно еще и сбрасывать счетчик таймера (TAR). Если вы используете таймер для формирования сигнала ШИМ, периодом которого желаете управлять, то можно использовать таймер в режиме Continuous и каждый раз по прерыванию CCR0 простым суммированием невзирая на переполнение добавлять новый период с текущему содержимому CCR0. Кстати, для Timer_B это выглядит еще проще. У него уже предусмотрена двойная буферизация регисторов сравнения CCRx. Резюмируя: читайте User's Guide, там все написано. Перевод см. тут. P.S. ну и совсем очевидную вещь добавлю. Учитывайте скорость выполнения программы (частоту сигнала MCLK) и частоту тактирования собственно таймера. Естественно, если они равны, то вы не сможете манипулировать периодами ШИМ величиной в единицы тактов. CPU просто не успеет.
|
|
|
|
|
Feb 1 2006, 16:45
|
Участник

Группа: Свой
Сообщений: 43
Регистрация: 26-01-06
Из: Минск, Беларусь
Пользователь №: 13 651

|
Можно, если осторожно и Так что в последнем случае, кроме установки CCR0 нужно еще и сбрасывать счетчик таймера (TAR).
спасибо, надеюсь всё будет теперь работать нормально.
PS Нет, это не ШИМ. Просто надо производить последовательно набор действий через различные промежутки времени. Вот мне и показалось что наиболее просто - выполнили действие, переставили таймер итд.
Сообщение отредактировал //Nikson - Feb 1 2006, 16:47
|
|
|
|
|
Feb 2 2006, 12:11
|
Участник

Группа: Свой
Сообщений: 43
Регистрация: 26-01-06
Из: Минск, Беларусь
Пользователь №: 13 651

|
Кстати, а если промежутки времени, через которые надо выполнять действия, по длительности сопоставимы с тактовым сигналом - может не стоит использовать таймер (пока выставишь период, пока произойдёт вызов итд итп пройдёт намного больше времени), а прямо в основной процедуре писать пошагово действия, разделяя их задержками? И что можно использовать в качестве таких задержек?
|
|
|
|
|
Feb 15 2006, 05:33
|
Частый гость
 
Группа: Свой
Сообщений: 81
Регистрация: 4-08-05
Из: г. Саратов
Пользователь №: 7 351

|
Цитата(sensor_ua @ Feb 14 2006, 19:42)  void delay(unsigned int N){ unsigned int StartTime; unsigned int CurrentTime; StartTime = (unsigned int)Tms; // начинаем считать от этого времени do{ CurrentTime = (unsigned int)Tms; } while( (CurrentTime-StartTime) < N) } Тогда уж лучше сделать так, поскольку будет тратится меньше процессорного времени Код void delay(unsigned int N) { unsigned int StopTime = (unsigned int)Tms+N; while ((unsigned int)Tms < StopTime); } и не забыть описать Tms как volatile
|
|
|
|
|
Feb 15 2006, 07:54
|
Профессионал
    
Группа: Свой
Сообщений: 1 266
Регистрация: 22-04-05
Из: Киев
Пользователь №: 4 387

|
Цитата Тогда уж лучше сделать так, поскольку будет тратится меньше процессорного времени
void delay(unsigned int N) { unsigned int StopTime = (unsigned int)Tms+N; while ((unsigned int)Tms < StopTime); } ИМХО, при некоторых условиях работать не будет. Представим, что Tms = 0xFFFFFFFE, N = 5, соответственно StopTime =0xFFFFFFFE+5= 3. Когда Tms переполнится (Tms ==0) выполнится условие ((unsigned int)Tms < StopTime) ==> (0<3), т.е. недосчитаем. На самом деле StartTime можно узнавать в любом удобном месте, откуда нужно начинать счёт, а проверку на ( (CurrentTime-StartTime) < N) выполнять также - в "нужном" месте - либо как системные дела, либо просто перед обработкой параметра в алгоритме - тогда это будет не пауза, а проверка на "не вышел ли указанный таймаут". Таким образом можно разгружать обработчики прерывания от if(timeout) --timeout; Цитата и не забыть описать Tms как volatile согласен
--------------------
aka Vit
|
|
|
|
|
Feb 15 2006, 08:41
|

Профессионал
    
Группа: Модераторы
Сообщений: 1 120
Регистрация: 17-06-04
Пользователь №: 37

|
у меня тоже тикает таймерное прерывание каждую милисекунду. Что-бы избежать всех вышеперечисленных ошибок, сделал тики unsigned long Код volatile unsigned long tick_ms; // милисекундные тики, хватит на 49 дней непрерывной работы прибора
void delay( unsigned long del ) { for ( del += tick_ms; del > tick_ms; ) ; } Кстати микросекундные задержки (> 10 мкс) можно делать через Compare. Через Compare у меня работает и 1-wire - общаюсь с DS1821
Сообщение отредактировал VAI - Feb 15 2006, 08:47
--------------------
Если зайца бить, его можно и спички научить зажигать Сколько дурака не бей - умнее не будет. Зато опытнее
|
|
|
|
|
Feb 15 2006, 09:05
|
Профессионал
    
Группа: Свой
Сообщений: 1 266
Регистрация: 22-04-05
Из: Киев
Пользователь №: 4 387

|
Цитата 2. Заводим переменную типа unsigned (например, int или long), назовем её unsigned long Tms = 0; Ну дык важно только чтобы обслужилось Цитата while( (CurrentTime-StartTime) < N) хотя бы раз за 49 суток, иначе придётся верить, что ничего плохого не произойдёт (не под конец этих 49-и суток начали отсчёт StartTime, например) и всё пучком, но Цитата хватит на 49 дней непрерывной работы прибора - подразумевает необязательность долговременой работы прибора. А микросекундные можно делать, используя вместо Tms непосредственно показания таймера, но ошибки нужно оценивать при малых интервалах
--------------------
aka Vit
|
|
|
|
|
Feb 15 2006, 11:26
|
Частый гость
 
Группа: Свой
Сообщений: 81
Регистрация: 4-08-05
Из: г. Саратов
Пользователь №: 7 351

|
Цитата ИМХО, при некоторых условиях работать не будет. Представим, что Tms = 0xFFFFFFFE, N = 5 Тут Вы правы, такая ошибка может возникнуть. Хотя если требуется долговременная работа прибора, то можно период отсчёта таймер сделать не 1 мс, а например 10 мс. Тогда счётчика хватит на 497 суток и проблемы с переполнением вряд ли возникнут (за такой срок прибор в любом случаи хотя раз да перезапустится) Хотя всё это сильно зависит от задачи, у меня например период отсчёта таймер 100 мс. Как говорится "А мне больше и не надо"
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|