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

 
 
 
Reply to this topicStart new topic
> Ламерский вопрос по 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
megajohn
сообщение Sep 16 2014, 05:38
Сообщение #2


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

Группа: Свой
Сообщений: 1 080
Регистрация: 16-11-04
Из: СПб
Пользователь №: 1 143



Цитата(brag @ Sep 16 2014, 00:43) *
Собственно в сабже есть режим 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? Получается только путем переконфигурировать и дождатся события(или форс вручную)?


на память: TCNT1 считает от 0 до 256
если стоит OCR1A = 100 и Set OC1A/OC1B on Compare Match
то при TCNT1=0...99 на ножке будет 0, при TCNT1=100...255 на ножке будет 1
если же стоит Clear то будет инвертированно, и в 1 встанет само при TCNT1=0


--------------------
Марс - единственная планета, полностью населенная роботами (около 7 штук).
Go to the top of the page
 
+Quote Post
alexeyv
сообщение Sep 16 2014, 07:35
Сообщение #3


Местный
***

Группа: Участник
Сообщений: 298
Регистрация: 26-01-09
Из: Пермь
Пользователь №: 43 940



Цитата(megajohn @ Sep 16 2014, 11:38) *
на память: TCNT1 считает от 0 до 256

может все таки до 255?
Go to the top of the page
 
+Quote Post
brag
сообщение Sep 16 2014, 07:58
Сообщение #4


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

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



Цитата
то при TCNT1=0...99 на ножке будет 0, при TCNT1=100...255 на ножке будет 1
если же стоит Clear то будет инвертированно, и в 1 встанет само при TCNT1=0

не верно. это для режима PWM так, а для CTC нет. в CTC ножка только сбрасывается/устанавливается при compare match.
если стоит OCR1A = 100 и Set OC1A/OC1B on Compare Match
то когда TCNT1=100 нога установится в лог 1 и будет висеть в нем вечно.

Цитата
может все таки до 255?

ta хоть до 65535

скорее всего врядли что-то дельное получится из этой avr, прийдется наверное вешать сверху платку с простенькой cpld, на которой и сделать вменяемый таймер.
Go to the top of the page
 
+Quote Post
=GM=
сообщение Sep 16 2014, 09:24
Сообщение #5


Ambidexter
*****

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



Ну, насчёт дельности это вы погорячились. Вас легко спасет режим WGM=14 (или 15)


--------------------
Делай сразу хорошо, плохо само получится
Go to the top of the page
 
+Quote Post
brag
сообщение Sep 16 2014, 10:28
Сообщение #6


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

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



WGM14 не подходит тк When the ICR1 is used as TOP value (see description of the WGM13:0 bits located in the
TCCR1A and the TCCR1B Register), the ICP1 is disconnected and consequently the Input Cap-ture function is disabled.
WGM15 не подходит из за using OCR1A for defining TOP (WGM13:0 = 15) since the OCR1A then will be double buffered. Тоесть, когда я в обработчике TIMER1_CAPT запишу OCR1A - изменения вступят в силу уже после срабатывания compare event.

вот так это выглядит графически. пунктиром показано поведение, если прерывание(capture event) не возникнет
параметры pusle width и delay должны быть настраиваемые

разве что вот так можно сделать. Режим WGM14
Код
init(){
    ICR1=FGD_MIN;
    OCR1B=pw;
}
ISR(ANALOG_COMP_vect){
    U16 t,t0;
    t=TCNT1;
    t0=OCR1B;
    if(t<t0+200)return;
    ICR1=t+((t-t0)>>2)-48; // add delay, subtract interrupt-process time
    OCR1B=pw;
}

ISR(TIMER1_CAPT_vect){ // end of cycle
    ICR1=FGD_MIN;   // reset ICR1
}


Других прерываний быть не должно, иначе глюкнется. Джиттер будет в 1-2 такта.
Эскизы прикрепленных изображений
Прикрепленное изображение
 
Go to the top of the page
 
+Quote Post
=GM=
сообщение Sep 16 2014, 18:33
Сообщение #7


Ambidexter
*****

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



Не пойдет, ICP1 отключена и прерывание TIMER1_CAPT_vect никогда не сработает.

Ещё один путь - взять МК с двумя ICP1 и ICP3 модулями, таймеры пусть работают синхронно, один модуль будет срабатывать от входного события, а второй будет выдавать fast pwm (14/15). Как-то так.


--------------------
Делай сразу хорошо, плохо само получится
Go to the top of the page
 
+Quote Post
brag
сообщение Sep 17 2014, 08:17
Сообщение #8


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

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



Цитата
Не пойдет, ICP1 отключена и прерывание TIMER1_CAPT_vect никогда не сработает.

Все там нормально срабатывает: When the Input Capture Register(ICR1) is set by the WGM13:0 to be used as the TOP value, the ICF1 Flag is set when the counter reaches the TOP value. режим WGM14.
В принципе TIMER1_CAPT_vect можно заменить на TIMER1_OVF_vect, будет точно такое же поведение.

Данный алгоритм работает, но прерываний других использовать нельзя(кроме аварийных). Что в принципе не является особой проблеммой, работать с остальной периферией можно в вечном цикле.

Цитата
Ещё один путь - взять МК с двумя ICP1 и ICP3 модулями, таймеры пусть работают синхронно, один модуль будет срабатывать от входного события, а второй будет выдавать fast pwm (14/15). Как-то так.

На сколько я помню, у AVR нету синхронизации между T1 и T3. Если даже изначально TCNT1==TCNT3 (хотя как это сделать я не представляю синхронизацию сделать можно через TSM,PSR) - если ICP1 словит входное событие, запишет ICP3=ICP1+блабла, Т3 сбросится при достижении ICP3, a T1 продолжит дальше считать - вот тут они и рассинхронизируются.
Если уж менять железо, то лучше рядом с Atmega88 поставить CPLD и сделать на нем нужную логику. Таймер нужен 12-битный максимум, + еще 2 регистра(типа OCR1A и OCR1B) тоже 12-битных, + сумматор + немного логики. EPM3064 должно хватить - 36 MC уйдет под регистры и еще 28 останется для логики. А,да еще как-то надо загружать туда регистр из атмеги, допустим по spi, тогда нужен еще 1 буфферный 12-битный регистр, тогда возможно понадобится cpld на больше макроячеек.
Ну или найти другой МК, где это можно реализовать аппаратными средствами.
Go to the top of the page
 
+Quote Post
=GM=
сообщение Sep 17 2014, 09:58
Сообщение #9


Ambidexter
*****

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



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

Цитата(brag @ Sep 17 2014, 07:17) *
На сколько я помню, у AVR нету синхронизации между T1 и T3. Если даже изначально TCNT1==TCNT3 (хотя как это сделать я не представляю синхронизацию сделать можно через TSM,PSR) - если ICP1 словит входное событие, запишет ICP3=ICP1+блабла, Т3 сбросится при достижении ICP3, a T1 продолжит дальше считать - вот тут они и рассинхронизируются

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


--------------------
Делай сразу хорошо, плохо само получится
Go to the top of the page
 
+Quote Post
brag
сообщение Sep 17 2014, 10:37
Сообщение #10


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

Группа: Свой
Сообщений: 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
Сообщение #11


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
brag
сообщение Sep 17 2014, 12:05
Сообщение #12


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

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



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

ну вообще то событие (точка 2) названо comparator IRQ/capture event sm.gif
В данном случаи(код для атмега88 ANALOG_COMP_vect) правильно будет software capture event или тип того. Но в идеале это должен быть настоящий железный capture

Цитата
В один таймер пишете 0, в другой 1. Запускаете первый, потом второй.

разве что на ассемблере с точным подсчетом тактов между запусками таймеров, и скорее не 1, а где-то 4 + не совсем известно сколько проходит тактов с момента начала выполнения инструкции до собственно старта таймера(мож в даташите и написано). это костыль, есть же бит TSM для этих целей.
Go to the top of the page
 
+Quote Post

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

 


RSS Текстовая версия Сейчас: 19th July 2025 - 02:19
Рейтинг@Mail.ru


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