AVR Mega8 Timer2 в режиме генератора частоты
AVR Mega8 Timer2 в режиме генератора частоты
Уже неделю бьюсь, не могу найти ошибку.
Таймер 2 включен в режиме СТС (СОМ2=01, WGM21=1, делитель=256)
На ноге PB3 генерируется сигнал с частотой в зависимости от значения в регистре OCR2.
Беда в том, что при изменении этого регистра, для изменения частоты, первый период после изменения регистра OCR2 с сигналом происходят какие-то глюки - импульс на ноге PB3 может иметь какой-то произвольный интервал, то очень короткий, то длинный, как результат плавное изменение частоты не получается.
Помогите в чем может быть проблема. Спасибо.
Таймер 2 включен в режиме СТС (СОМ2=01, WGM21=1, делитель=256)
На ноге PB3 генерируется сигнал с частотой в зависимости от значения в регистре OCR2.
Беда в том, что при изменении этого регистра, для изменения частоты, первый период после изменения регистра OCR2 с сигналом происходят какие-то глюки - импульс на ноге PB3 может иметь какой-то произвольный интервал, то очень короткий, то длинный, как результат плавное изменение частоты не получается.
Помогите в чем может быть проблема. Спасибо.
- Реклама
Re: AVR Mega8 Timer2 в режиме генератора частоты
Получается, хрень какая-то: когда я в процессе работы таймера меняю значение в регистре сравнения OCR2 (устанавливаю новую частоту) таймер досчитывает до старого значения регистра OCR2, инвертирует выход, не сбрасывает счетчик и продолжает считать до нового значения OCR2, дойдя до него уже сбрасывает счетчик и потом уже работает нормально.
Это глюки или настройка таймера не правильная?
Это глюки или настройка таймера не правильная?
- Roman Venom
- Сверлит текстолит когтями
- Сообщения: 1135
- Зарегистрирован: Сб июл 11, 2009 18:42:21
- Откуда: Украина, г.Николаев
Re: AVR Mega8 Timer2 в режиме генератора частоты
Так это 8 битный таймер.
Сигнал получается такой:

Здесь видно два места где уменьшалась частота (изменялся регистр OCR2).
Код:
Инициализация таймера:
LDI R16,0b00011110
OUT TCCR2,R16
Этот кусок берет из таблицы значения частоты по индексу в R4 и записывает в OCR2
LDI R30,Low(Tab4*2)
LDI R31,High(Tab4*2)
CLR R16
ADD R30,R4
ADC R31,R16
LPM
OUT OCR2,R0
Короче прошел пошагово - так и есть при изменении OCR2 он помнит предыдущее его значении и при совпадении с ним инвертирует выход но не сбрасывает счетчик.
Что делать?
Сигнал получается такой:

Здесь видно два места где уменьшалась частота (изменялся регистр OCR2).
Код:
Инициализация таймера:
LDI R16,0b00011110
OUT TCCR2,R16
Этот кусок берет из таблицы значения частоты по индексу в R4 и записывает в OCR2
LDI R30,Low(Tab4*2)
LDI R31,High(Tab4*2)
CLR R16
ADD R30,R4
ADC R31,R16
LPM
OUT OCR2,R0
Короче прошел пошагово - так и есть при изменении OCR2 он помнит предыдущее его значении и при совпадении с ним инвертирует выход но не сбрасывает счетчик.
Что делать?
- vitalik_1984
- Поставщик валерьянки для Кота
- Сообщения: 2482
- Зарегистрирован: Пт авг 27, 2010 05:57:06
- Откуда: Тюмень
- Контактная информация:
Re: AVR Mega8 Timer2 в режиме генератора частоты
это может объясняться двумя причинами:
1 ошибка в коде
2 все в порядке просто архитектура таймера такая: если пытаешься рядом со значением совпадения таймера присвоить новое значение или если присваиваешь значение на один больше(в случае уменьшения значений счетчика) или меньше на один,то может не произойти события СОВПАДЕНИЯ таймера.
Хотя можно и такое упущение расценивать как недостаток в коде:)
1 ошибка в коде
2 все в порядке просто архитектура таймера такая: если пытаешься рядом со значением совпадения таймера присвоить новое значение или если присваиваешь значение на один больше(в случае уменьшения значений счетчика) или меньше на один,то может не произойти события СОВПАДЕНИЯ таймера.
Хотя можно и такое упущение расценивать как недостаток в коде:)
В поисках истины человек развивается.
- Реклама
- aleksey_gregul
- Встал на лапы
- Сообщения: 130
- Зарегистрирован: Ср дек 29, 2010 17:30:34
Re: AVR Mega8 Timer2 в режиме генератора частоты
Разрешите прерывание TIMER2 COMP и сбросьте его в прерывании.dandan писал(а):но не сбрасывает счетчик. Что делать?
Я бы перегружал OCR2 тоже именно в прерывании, до сброса таймера.
Re: AVR Mega8 Timer2 в режиме генератора частоты
Думал так попробовать, а потом подумал, разницы же нет когда менять OCR2 в прерывании или другом месте.aleksey_gregul писал(а):Разрешите прерывание TIMER2 COMP и сбросьте его в прерывании.dandan писал(а):но не сбрасывает счетчик. Что делать?
Я бы перегружал OCR2 тоже именно в прерывании, до сброса таймера.
Странно, что в даташите об этом ничего не сказано.
И если так делать, то тогда теряется весь смысл режима СТС. Можно просто по переполнению устанавливать счетчик таймера в нужное значение (чем и задавать частоту) и инвертировать выход. Что я в результате и сделал.
Но в этом случае портится точность сигнала, ведь в момент прерывания по переполнению может работать другое прерывание и тогда изменение фронта сигнала немного сместиться.
Re: AVR Mega8 Timer2 в режиме генератора частоты
Попробовал менять OCR2 в прерывании по совпадению. Результат тот-же. Не работает оно нормально.aleksey_gregul писал(а):Разрешите прерывание TIMER2 COMP и сбросьте его в прерывании.dandan писал(а):но не сбрасывает счетчик. Что делать?
Я бы перегружал OCR2 тоже именно в прерывании, до сброса таймера.
И еще. Если порт настроен на выход то установка 1 в PIN инвертирует его. В Протеусе это работает, а в железе нет. В чем подвох?
- aleksey_gregul
- Встал на лапы
- Сообщения: 130
- Зарегистрирован: Ср дек 29, 2010 17:30:34
Re: AVR Mega8 Timer2 в режиме генератора частоты
Есть небольшая разница. Вы попробуйте вместе со сбросом таймера.dandan писал(а):Думал так попробовать, а потом подумал, разницы же нет когда менять OCR2 в прерывании или другом месте.
А в режиме СТС этого не будет. Пин будет меняться аппаратно, что у Вас и происходит.dandan писал(а):И если так делать, то тогда теряется весь смысл режима СТС.
Но в этом случае портится точность сигнала ... фронта сигнала немного сместиться.
Сброс таймера в прерывании (при Вашем прескалере) не изменит момента смены пина.
Чтобы понять, почему нужно перегружать OCR2 и попутно сбрасывать таймер, прочтите выдержку из даташита.
If the interrupt is enabled, the interrupt handler routine can be
used for updating the TOP value. However, changing the TOP to a value close to BOTTOM
when the counter is running with none or a low prescaler value must be done with
care since the CTC mode does not have the double buffering feature. If the new value
written to OCR2 is lower than the current value of TCNT2, the counter will miss the
Compare Match. The counter will then have to count to its maximum value (0xFF) and
wrap around starting at 0x00 before the Compare Match can occur.
Попробуйте и расскажите результат. Самому интересно стало.
Re: AVR Mega8 Timer2 в режиме генератора частоты
aleksey_gregul, спасибо за ответ.
То, что счетчик может проскочить новое устанавливаемое значение OCR и будет считать до 255 это понятно и это можно предвидеть и корректировать TCNT. Я пробовал это делать.
Тут дело в другом. При изменении OCR счетчик помнит старое значение OCR и при достижении его инвертирует выход. Затем считает дальше и при достижении нового (уже записанного если оно больше старого) значения OCR снова инвертирует выход и сбрасывает TCNT на 0. Счетчик действительно так работает, я проходил пошагово.
Получается, что новое, записанное в OCR значение, вступает в силу при совпадении TCNT со старым значением OCR, но зачем при этом инвертируется выход?
Вы предлагаете в прерывании по совпадению устанавливать новое значение OCR. Это не помогает и счетчик все равно досчитав до старого значения инвертирует выход и продолжает считать дальше.
В этом же прерывании еще сбросить счетчик? Так он же уже сброшен? TCNT=0 Или как его еще сбросить.
То, что счетчик может проскочить новое устанавливаемое значение OCR и будет считать до 255 это понятно и это можно предвидеть и корректировать TCNT. Я пробовал это делать.
Тут дело в другом. При изменении OCR счетчик помнит старое значение OCR и при достижении его инвертирует выход. Затем считает дальше и при достижении нового (уже записанного если оно больше старого) значения OCR снова инвертирует выход и сбрасывает TCNT на 0. Счетчик действительно так работает, я проходил пошагово.
Получается, что новое, записанное в OCR значение, вступает в силу при совпадении TCNT со старым значением OCR, но зачем при этом инвертируется выход?
Вы предлагаете в прерывании по совпадению устанавливать новое значение OCR. Это не помогает и счетчик все равно досчитав до старого значения инвертирует выход и продолжает считать дальше.
В этом же прерывании еще сбросить счетчик? Так он же уже сброшен? TCNT=0 Или как его еще сбросить.
- aleksey_gregul
- Встал на лапы
- Сообщения: 130
- Зарегистрирован: Ср дек 29, 2010 17:30:34
Re: AVR Mega8 Timer2 в режиме генератора частоты
Значит я Вас неправильно понял?dandan писал(а):Короче прошел пошагово - так и есть при изменении OCR2 он помнит предыдущее его значении и при совпадении с ним инвертирует выход но не сбрасывает счетчик.
Что делать?
Сброс сброшенного счетчика никому (при Вашем прескаллере) не помешает.
Он сможет помочь в цитируемой ситуации.
Есть такое понятие double buffering. Просто прожужжите 1 такт(с учетом прескаллера). Но не получите корявого импульса.
Re: AVR Mega8 Timer2 в режиме генератора частоты
Вчера проверил это в железе на Mega48 - работает.И еще. Если порт настроен на выход то установка 1 в PIN инвертирует его. В Протеусе это работает, а в железе нет. В чем подвох?
- aleksey_gregul
- Встал на лапы
- Сообщения: 130
- Зарегистрирован: Ср дек 29, 2010 17:30:34
Re: AVR Mega8 Timer2 в режиме генератора частоты
И еще.
Неправильно подсовывать таймеру новое значение когда попало и ожидать от него мгновенной реакции. Дайте ему отработать свой цикл. Чтобы форма сигнала не портилась.
И именно в конце цикла подсуньте новое значение. Но напомните ему при этом вручную, что считать уже пора по-новой.
Надеюсь поняли?
Неправильно подсовывать таймеру новое значение когда попало и ожидать от него мгновенной реакции. Дайте ему отработать свой цикл. Чтобы форма сигнала не портилась.
И именно в конце цикла подсуньте новое значение. Но напомните ему при этом вручную, что считать уже пора по-новой.
Надеюсь поняли?
Re: AVR Mega8 Timer2 в режиме генератора частоты
Понял но не совсем.aleksey_gregul писал(а):И еще.
Неправильно подсовывать таймеру новое значение когда попало и ожидать от него мгновенной реакции. Дайте ему отработать свой цикл. Чтобы форма сигнала не портилась.
И именно в конце цикла подсуньте новое значение. Но напомните ему при этом вручную, что считать уже пора по-новой.
Надеюсь поняли?
Подсовывать новое значение пробовал в прерывании на совпадении. Это не повлияло ни на что.
А что значит вручную сбросить таймер? Как это реализовать? Выключить-включить делитель?
Попробовал установкой бита PRS2 (сброс прескаллера), тоже самое досчитывает до прошлого значения OСR и инвертирует выход.
- aleksey_gregul
- Встал на лапы
- Сообщения: 130
- Зарегистрирован: Ср дек 29, 2010 17:30:34
Re: AVR Mega8 Timer2 в режиме генератора частоты
В прерывании в TCNT2 записать ноль;dandan писал(а): А что значит вручную сбросить таймер? Как это реализовать?
Этого делать нельзя! поплывет сам делитель. Это применимо только при измерениях сигналов.dandan писал(а):Выключить-включить делитель?
И это правильно. Иначе - в выходном сигнале появится период сигнала с непредсказуемо завышенной частотой. И только после этого пойдет сигнал с правильной частотой. Если Вам это не мешает, ради Бога!dandan писал(а):тоже самое досчитывает до прошлого значения OСR и инвертирует выход.
А так, как я предложил- получите просто запаздывние в реакции Вашего генератора на 1 такт выходного сигнала. Зато гарантировано частота до изменения стабильна и равна заданной. И после изменения тоже стабильна и равна заданной. (без попадания в спектр ни единого такта с непредсказуемой частотой)
- vitalik_1984
- Поставщик валерьянки для Кота
- Сообщения: 2482
- Зарегистрирован: Пт авг 27, 2010 05:57:06
- Откуда: Тюмень
- Контактная информация:
Re: AVR Mega8 Timer2 в режиме генератора частоты
Во во именно это я и хотел сказать:) может немного корявый перевод на память.aleksey_gregul писал(а):Есть небольшая разница. Вы попробуйте вместе со сбросом таймера.dandan писал(а):Думал так попробовать, а потом подумал, разницы же нет когда менять OCR2 в прерывании или другом месте.
А в режиме СТС этого не будет. Пин будет меняться аппаратно, что у Вас и происходит.dandan писал(а):И если так делать, то тогда теряется весь смысл режима СТС.
Но в этом случае портится точность сигнала ... фронта сигнала немного сместиться.
Сброс таймера в прерывании (при Вашем прескалере) не изменит момента смены пина.
Чтобы понять, почему нужно перегружать OCR2 и попутно сбрасывать таймер, прочтите выдержку из даташита.
If the interrupt is enabled, the interrupt handler routine can be
used for updating the TOP value. However, changing the TOP to a value close to BOTTOM
when the counter is running with none or a low prescaler value must be done with
care since the CTC mode does not have the double buffering feature. If the new value
written to OCR2 is lower than the current value of TCNT2, the counter will miss the
Compare Match. The counter will then have to count to its maximum value (0xFF) and
wrap around starting at 0x00 before the Compare Match can occur.
Попробуйте и расскажите результат. Самому интересно стало.
В поисках истины человек развивается.
Re: AVR Mega8 Timer2 в режиме генератора частоты
В прерывании там уже "0", какой смысл его писать снова? (у меня делитель 256)aleksey_gregul писал(а):В прерывании в TCNT2 записать ноль;dandan писал(а): А что значит вручную сбросить таймер? Как это реализовать?
Ничего подобного. Так было бы, если бы он инвертировал выход и сбрасывал счетчик, далее считал уже до нового значения OСR.aleksey_gregul писал(а):И это правильно. Иначе - в выходном сигнале появится период сигнала с непредсказуемо завышенной частотой. И только после этого пойдет сигнал с правильной частотой. Если Вам это не мешает, ради Бога!dandan писал(а):тоже самое досчитывает до прошлого значения OСR и инвертирует выход.
Но при совпадении со старым значением OСR счетчик не сбрасывается, прерывание по совпадению не генерируется, только зачем-то инвертируется выход. Затем счетчик считает дальше и при совпадении с уже установленным OСR работает нормально. В результате получаем короткие скачки как на графике длительностью равной разнице между новым и старым значением OСR.
- aleksey_gregul
- Встал на лапы
- Сообщения: 130
- Зарегистрирован: Ср дек 29, 2010 17:30:34
Re: AVR Mega8 Timer2 в режиме генератора частоты
Странно!dandan писал(а):Ничего подобного. Так было бы, если бы он инвертировал выход и сбрасывал счетчик, далее считал уже до нового значения OСR.
Но при совпадении со старым значением OСR счетчик не сбрасывается, прерывание по совпадению не генерируется, только зачем-то инвертируется выход.
Вы в чем это проверяете?
Специально создал проектик. У меня совсем противоположные. При совпадении со старым значением OСR счетчик не сбрасывается и не инвертируется выход!
Протеус как-то странно симулит! Частота должна падать, что в студии и вижу, а в протеусе все наоборот.

Только я програмлю на С в ИАР_е.
Код: Выделить всё
#include <iom8.h>
#include <stdio.h>
#include <inavr.h>
#define XTALL 8.0
#define delay_us(us) __delay_cycles (XTALL * us);
#define delay_ms(ms) delay_us (1000 * ms)
volatile unsigned char ch=10;
void inittimer2(void)
{
TCCR2 = 0x00; //stop
ASSR = 0x00; //set async mode
TCNT2 = 0x00; //setup
OCR2 = 10;
TIMSK = 0x80; //timer interrupt sources
TCCR2 = 0x1E; //start
__enable_interrupt();
}
#pragma vector = TIMER2_COMP_vect // âûïîëíÿåòñÿ 12.56us
__interrupt void t2handler(void)//
{
TCNT2=0;
OCR2=ch;
}
void main( void )
{
PORTB = 0x00;
DDRB = 0xFF;
inittimer2();
while(1)
{
delay_ms(10);
ch=ch+10;
}
}
Re: AVR Mega8 Timer2 в режиме генератора частоты
Странно, у Васaleksey_gregul писал(а): TCCR2 = 0x1E; //start
1E это 00010110 - это не режим СТС (судя по даташиту это режим NORMAL, считает до 0хFF)
у меня 00011110.
Прохожу пошагово в AVR Studio, симулирую в Протеусе - работает одинаково.
- aleksey_gregul
- Встал на лапы
- Сообщения: 130
- Зарегистрирован: Ср дек 29, 2010 17:30:34
Re: AVR Mega8 Timer2 в режиме генератора частоты
После более детального исследования происходящих процессов, выяснилось, что и прерывания наступают и таймер сбрасывается и пин меняется абсолютно одновременно (по крайней мере, если прерывания разрешены). За исключением одного НО.
Вводит в заблуждение понятие COMPARE. По привычке мы ожидаем, что само событие должно произойти именно в момент совпадения состояния счетчика с записанным в OCR2 числом. Но, в отладчике аврстудии, а я симулировал в "Avr Simulator" все происходит немножко по другому. При досчете таймера до OCR2, ничего не происходит. И как только таймер сменит свое зачение, наступает момент смены пина, обнуления таймера и генерирования прерывания. Т.Е. к примеру, в OCR2=5. Таймер досчитал до пяти и ничего не произошло. Но как только таймер досчитает до 6, тут же все и произойдет. Не знаю, как там в железе, но в "Avr Simulator" именно так.
Т.е. В прерывании ресетить таймер - действительно лишнее. А вот перегружать OCR2 следует именно в прерывании. В майне, только готовить для него данные.
С неразрешенными прерываниями не проверял. Возможно, ситуация изменится на ту, которую Вы описываете. Я без прерываний перегружать регистры таймера не буду и поэтому далее экспериментировать просто влом.
Вводит в заблуждение понятие COMPARE. По привычке мы ожидаем, что само событие должно произойти именно в момент совпадения состояния счетчика с записанным в OCR2 числом. Но, в отладчике аврстудии, а я симулировал в "Avr Simulator" все происходит немножко по другому. При досчете таймера до OCR2, ничего не происходит. И как только таймер сменит свое зачение, наступает момент смены пина, обнуления таймера и генерирования прерывания. Т.Е. к примеру, в OCR2=5. Таймер досчитал до пяти и ничего не произошло. Но как только таймер досчитает до 6, тут же все и произойдет. Не знаю, как там в железе, но в "Avr Simulator" именно так.
Т.е. В прерывании ресетить таймер - действительно лишнее. А вот перегружать OCR2 следует именно в прерывании. В майне, только готовить для него данные.
С неразрешенными прерываниями не проверял. Возможно, ситуация изменится на ту, которую Вы описываете. Я без прерываний перегружать регистры таймера не буду и поэтому далее экспериментировать просто влом.


