реклама на сайте
подробности

 
 
> Ламерский вопрос по timer1 Atmega88
brag
сообщение Sep 15 2014, 20:43
Сообщение #1


Профессионал
*****

Группа: Свой
Сообщений: 1 047
Регистрация: 2-12-06
Из: Kyiv, Ukraine
Пользователь №: 23 046



Привет всем!
Собственно в сабже есть режим CTC и в нем есть фичи Clear OC1A/OC1B on Compare Match (Set output to low level) и Set OC1A/OC1B on Compare Match (Set output to high level).
Как ими пользоватся? wink.gif
В смысле, если я настрою выход OC1B как Clear OC1A/OC1B on Compare Match, то как сделать Set? Получается только путем переконфигурировать и дождатся события(или форс вручную)?

Вообще задача стоит так. Таймер T считает от 0 до X, при достижении X сбрасывается в 0 и так по кругу.
Когда T==0 set OC1A(или B,не важно). Когда T=a clear OC1A/B, при чем a<X. Тоесть обычный PWM.
Но, таймер должен еще сбрасыватся по компаратору(или внешнему пину), при чем с определенной задержкой.

Пока реализация вот такая. Режим CTC TOP=OCR1A. Clear OC1B on Compare Match и в OCR1B=a; OCR1A изначально равно X.
Код
ISR(TIMER1_CAPT_vect){
    OCR1A=ICR1+delay; // сброс таймера при достижении OCR1A
}

ISR(TIMER1_COMPA_vect){
    OCR1A=X;
}

Все было бы ок, если бы можно было заставить выход OC1B установится в лог1, когда таймер сбрасывается.
Ржим PWM не канает из за буфферизации OCR1x...

Можно как-то так, но эт как-то слишком глючно. На пример, если a слишком маленькое - есть риск что таймер его обгонит еще до того, как мы успеем обновить OCR1B и выход будет всегда висеть в единице, а это чревато последствиями sm.gif
Код
init(){
    TCCR1A=(1<<COM1B1)|(0<<COM1B0); //Clear OC1B on Compare Match
}

ISR(TIMER1_CAPT_vect){
    int t=ICR1+delay; // сброс таймера при достижении OCR1A
    OCR1A=t;
    OCR1B=t;
    TCCR1A=(1<<COM1B1)|(1<<COM1B0); // Set OC1B on Compare Match
}

ISR(TIMER1_COMPA_vect){
    OCR1A=X;
    OCR1B=a;
    TCCR1A=(1<<COM1B1)|(0<<COM1B0); //Clear OC1B on Compare Match
}
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов
brag
сообщение Sep 17 2014, 10:37
Сообщение #2


Профессионал
*****

Группа: Свой
Сообщений: 1 047
Регистрация: 2-12-06
Из: Kyiv, Ukraine
Пользователь №: 23 046



Цитата
Ничего не сработает. Вы спутали ICR с ICP. Внешнее событие никогда не наступит, поскольку InputCapturePin отключен в режиме 14/15.

посмотрите внимательно код, TIMER1_CAPT_vect ловит не внешнее событие, а TCNT1==ICR1 (режим WGM14). Внешнее событие ловит ANALOG_COMP_vect (вторая точка на графике).
Сейчас девайс лежит на столе и именно так и работает.

Цитата
Таймеры работают от одного источника, поэтому всегда "засинхронизированы". Если ICP1 словит входное событие, то текущее значение счетчика перепишется в ICP1, а таймер1 как считал, так и будет продолжать считать.

Ну не совсем всегда, их нужно еще засинхронизировать вручную через ТSМ, но это не столь важно. Важно, что таймер1 как считал, так и будет продолжать считать, а таймер Т3 сбросится при достижении ICR3(который равен ICR1+блабла) и теперь TCNT1!=TCNT3. Это можно заставить работать корректно, вычислять "истинный" ICR1(время между первой и второй точкой на графике) зная ICR1,ICR3,OCR3B и разрядность TCNT1.
+ такого 'двухтаймерного' решения перед предложенным в посту #6 в отсутствии джиттера в 4(кажись) такта.
- обеих решений в том, что нельзя использовать другие прерывания(нужно работаь с периферией в вечном цикле), поскольку время(delay на графике) между второй точкой(ICP1) и ICR3 может быть довольно коротким, если прерывание ICP1 не выполнится вовремя - есть риск,тчо timer3 обгонит ICR1+блабла еще до того, как мы его туда запишем в ICR3.
Go to the top of the page
 
+Quote Post
=GM=
сообщение Sep 17 2014, 11:11
Сообщение #3


Ambidexter
*****

Группа: Свой
Сообщений: 1 589
Регистрация: 22-06-06
Из: Oxford, UK
Пользователь №: 18 282



Цитата(brag @ Sep 17 2014, 10:37) *
Внешнее событие ловит ANALOG_COMP_vect (вторая точка на графике)

Ну раз так, то не надо его называть "capture event"

Цитата(brag @ Sep 17 2014, 10:37) *
Ну не совсем всегда, их нужно еще засинхронизировать вручную через ТSМ, но это не столь важно

Нет ничего проще, как засинхронизировать. В один таймер пишете 0, в другой 1. Запускаете первый, потом второй.


--------------------
Делай сразу хорошо, плохо само получится
Go to the top of the page
 
+Quote Post



Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 22nd July 2025 - 04:11
Рейтинг@Mail.ru


Страница сгенерированна за 0.01392 секунд с 7
ELECTRONIX ©2004-2016