Таймеры/счётчики в AVR
Re: Таймеры/счётчики в AVR
Как вариант генерации нот. Меандр на PB2.
- Вложения
-
- GEN_NOTE_TN25.zip
- (1.59 КБ) 124 скачивания
Re: Таймеры/счётчики в AVR
[uquote="Just_Fluffy",url="/forum/viewtopic.php?p=4707647#p4707647"]darkkis89, фрагмент кода в студию[/uquote]
К сожалению, при попытке отделения кода от остальной программы и его выполнении он начинал работать как нужно, в принципе я уже немного его изменил и всё заработало как нужно, спасибо за отклик.
К сожалению, при попытке отделения кода от остальной программы и его выполнении он начинал работать как нужно, в принципе я уже немного его изменил и всё заработало как нужно, спасибо за отклик.
Re: Таймеры/счётчики в AVR
Здравствуйте! Прошу совета. Если такое уже спрашивали ткните носом. Имеется следующий код для atmega48. Его задача выдать импульс заданной длительности в ответ на отпускание кнопки. Кнопка опрашивается по переполнению таймера 0. Если фиксируется нажатие на кнопку режим таймера меняется на CTC с другим предделителем. В данном примере я пытаюсь сделать импульс 10мс, но вместо этого получаю 16мкс.
Опытным путем я установил, что такой импульс получится, если подать частоту на таймер вообще без делителя, то есть биты CS00 CS02 устанавливаются с какой-то задержкой. Предделитель я обнуляю, это не помогает. Почему так получается? Можно ли вообще менять настройки таймера на ходу?
Спойлер
Код: Выделить всё
#include "timer.h"
volatile uint8_t btn0_clk = 0;
ISR(TIMER0_OVF_vect)
{
PORTB^=(1<<PB7);
//-------------опрос кнопки, подавление дребезга контактов-----------------
if (~PINB&(1<<PB0))
{
if (btn0_clk<=10) btn0_clk++;
}
else
{
if (btn0_clk>=10) //////////////
{
//PORTB ^= (1<<PB1);
exposition(0);
btn0_clk=0;
}
else btn0_clk=0;
}
TIFR0=0;
}
ISR(TIMER0_COMPA_vect)
{
PORTB&=~(1<<PB1); // тушим лампу
timer0_ini(); // запускаем опрос по переполнению, normal mode
}
void timer0_ini(void)
{
TCCR0B &= ~((1<<CS00) | (1<<CS01) | (1<<CS02));
TCCR0A &= ~(1<<WGM01); // normal mode
TIMSK0 &= ~(1<<OCIE0A);
TCCR0B |= (1<<CS01) | (1<<CS00); // запуск ~ 500Гц
TIMSK0 |= (1<<TOIE0); // разрешить прерывание по переполнению
TCNT0 = 0;
}
void exposition(uint16_t exp_time) // выдержка в мс
{
TIMSK0 &= ~(1<<TOIE0);
PORTB |= (1<<PB1); // зажигаем лампу
TCCR0B &= ~((1<<CS00) | (1<<CS01) | (1<<CS02));
TCCR0A |= (1<<WGM01); // режим СТС
GTCCR |= (1<<PSRSYNC);
OCR0A = 78; // прерывание каждые 10 мс
TIFR0=0;
TCNT0 = 0;
TIMSK0 |= (1<<OCIE0A); // прерывание по совпадению
TCCR0B |= (1<<CS00) | (1<<CS02); // делитель на 1024
}Спойлер
[img]url=https://img.radiokot.ru/files/161177/medium/3t8lhcz6h6.png][img]https://img.radiokot.ru/files/161177/[/img]- VNS
- Говорящий с текстолитом
- Сообщения: 1614
- Зарегистрирован: Пт дек 10, 2021 12:48:46
- Откуда: Тюмень
Re: Таймеры/счётчики в AVR
[uquote="komstek",url="/forum/viewtopic.php?p=4739403#p4739403"]Если фиксируется нажатие на кнопку режим таймера меняется на CTC с другим предделителем. В данном примере я пытаюсь сделать импульс 10мс, но вместо этого получаю 16мкс.[/uquote]
Ваш код не смотрел, так как ничего в нём не понимаю, но предполагаю, что вы перед переходе на режим СТС не сбросили флаг прерывания (OCF0A) с регистром сравнения (OCRA). Потому когда разрешаете глобальные прерывания, прерывание по сравнению осуществляется, так как флаг прерывания по сравнению (OCF0A) уже давно был установлен, а сбрасывается он только, или автоматически при возникновении прерывания, или записью в него 1.
Как я вижу алгоритм данной задачи: вам необходимо в прерывании по переполнению регистра TCNT0 (после фиксации нажатой кнопки), сбросить флаг прерывания сравнения (OCF0A), затем перенастроить таймер в режим СТС, установить нужное значение регистра OCRA, разрешить прерывание (Timer 0 / Compare Match A), установить 1 на нужном выводе. Далее в прерывании (по Timer 0 Compare Match A), снять установленную 1 с вывода, далее перевести таймер в режим Normal, перенастроить прерывания по переполнению (Timer 0 / Overflow) и выйти из данного прерывания. Далее в прерываниях по переполнению отслеживать нажатия кнопки и когда нажатие вновь будет зафиксировано повторить алгоритм по перенастройке данного таймера на режим СТС как описано выше. Всё.
Ваш код не смотрел, так как ничего в нём не понимаю, но предполагаю, что вы перед переходе на режим СТС не сбросили флаг прерывания (OCF0A) с регистром сравнения (OCRA). Потому когда разрешаете глобальные прерывания, прерывание по сравнению осуществляется, так как флаг прерывания по сравнению (OCF0A) уже давно был установлен, а сбрасывается он только, или автоматически при возникновении прерывания, или записью в него 1.
Как я вижу алгоритм данной задачи: вам необходимо в прерывании по переполнению регистра TCNT0 (после фиксации нажатой кнопки), сбросить флаг прерывания сравнения (OCF0A), затем перенастроить таймер в режим СТС, установить нужное значение регистра OCRA, разрешить прерывание (Timer 0 / Compare Match A), установить 1 на нужном выводе. Далее в прерывании (по Timer 0 Compare Match A), снять установленную 1 с вывода, далее перевести таймер в режим Normal, перенастроить прерывания по переполнению (Timer 0 / Overflow) и выйти из данного прерывания. Далее в прерываниях по переполнению отслеживать нажатия кнопки и когда нажатие вновь будет зафиксировано повторить алгоритм по перенастройке данного таймера на режим СТС как описано выше. Всё.
Re: Таймеры/счётчики в AVR
Действительно, дело было в флаге. Теперь работает, спасибо большое за помощь!
Выходит, я не правильно понимал работу флагов. Они устанавливаются при выполнении условия прерывания, даже если это прерывание не разрешено, правильно?
Выходит, я не правильно понимал работу флагов. Они устанавливаются при выполнении условия прерывания, даже если это прерывание не разрешено, правильно?
- VNS
- Говорящий с текстолитом
- Сообщения: 1614
- Зарегистрирован: Пт дек 10, 2021 12:48:46
- Откуда: Тюмень
Re: Таймеры/счётчики в AVR
[uquote="komstek",url="/forum/viewtopic.php?p=4739450#p4739450"]Они устанавливаются при выполнении условия прерывания, даже если это прерывание не разрешено, правильно?[/uquote]
Да.
Да.
Re: Таймеры/счётчики в AVR
Теперь понял.
Re: Таймеры/счётчики в AVR
Приветствую всех.
Есть рабочая плата на Atmega88 программно настроено управление выводом OC1A, непрерывно выводится в режиме CTC меанд на OC1A(PB1).
Понадобилось изменить пин вывода на OC1B(PB2).
Внёс изменения в программу настойки регистра сравнения таймера OCR1B,
выставил TCCR1A Bit 5:4 – COM1B1:0: Toggle OC1B on compare match.
Выход OC1B не меняется.
Вопрос возможно ли так , или всё таки мне придётся на плате пере коммутировать выводы , чего бы не хотелось.
Есть рабочая плата на Atmega88 программно настроено управление выводом OC1A, непрерывно выводится в режиме CTC меанд на OC1A(PB1).
Понадобилось изменить пин вывода на OC1B(PB2).
Внёс изменения в программу настойки регистра сравнения таймера OCR1B,
выставил TCCR1A Bit 5:4 – COM1B1:0: Toggle OC1B on compare match.
Выход OC1B не меняется.
Вопрос возможно ли так , или всё таки мне придётся на плате пере коммутировать выводы , чего бы не хотелось.
Re: Таймеры/счётчики в AVR
Лапу PB2/OC1B на вывод установили?
Код: Выделить всё
SBI DDRB,2
LDI R16,1<<COM1B0
STS TCCR1A,R16
LDI R16,HIGH(10-1)
STS OCR1AH,R16
LDI R16,LOW(10-1)
STS OCR1AL,R16
LDI R16,HIGH(5-1)
STS OCR1BH,R16
LDI R16,LOW(5-1)
STS OCR1BL,R16
LDI R16,1<<WGM12|1<<CS10
STS TCCR1B,R16
RJMP PCRe: Таймеры/счётчики в AVR
Спасибо "akl".
пример заработал.
У меня почему то влияет изменения OCR1A, и на OCR1B.
А значение в OCR1B меньше чем в OCR1A не влияет на частоту выхода OC1B.
Большее значение OCR1B чем в OCR1A - меандр на OC1B останавливает - это понятно.
Но почему то меньшее значение на частоту не влияет?
ldi temp,0b0101.0000 ; Bit 7:6 – COM1A1:0: Compare output mode for channel A
sts TCCR1A,temp ; Bit 5:4 – COM1B1:0: Compare output mode for channel B
;
ldi temp,0b0000.1001 ;
sts TCCR1B,temp
;
ldi temp,0
sts TCNT1H,temp
sts TCNT1L,temp
;------------------------
.equ SYNS_A=25 ; ~ 156kHz
;
ldi temp,high(SYNS_A) ;
sts OCR1AH,temp
ldi temp,low(SYNS_A) ;
sts OCR1AL,temp
;------------------------
;
.equ SYNS_B=10 ; Значение SYNS_B <= SYNS_A не влияет на частоту выхода OC1B
;
ldi temp,high(SYNS_B)
sts OCR1BH,temp
ldi temp_1,low(SYNS_B)
sts OCR1BL,temp
;
Добавлено after 25 minutes 19 seconds:
То что мне нужно было с заменой выводов OC1А на OC1B без вмешательство в плату Работает!.
Ещо раз спасибо "akl".
У меня не работало из за того что значение в OCR1B было больше чем OCR1А.
пример заработал.
У меня почему то влияет изменения OCR1A, и на OCR1B.
А значение в OCR1B меньше чем в OCR1A не влияет на частоту выхода OC1B.
Большее значение OCR1B чем в OCR1A - меандр на OC1B останавливает - это понятно.
Но почему то меньшее значение на частоту не влияет?
ldi temp,0b0101.0000 ; Bit 7:6 – COM1A1:0: Compare output mode for channel A
sts TCCR1A,temp ; Bit 5:4 – COM1B1:0: Compare output mode for channel B
;
ldi temp,0b0000.1001 ;
sts TCCR1B,temp
;
ldi temp,0
sts TCNT1H,temp
sts TCNT1L,temp
;------------------------
.equ SYNS_A=25 ; ~ 156kHz
;
ldi temp,high(SYNS_A) ;
sts OCR1AH,temp
ldi temp,low(SYNS_A) ;
sts OCR1AL,temp
;------------------------
;
.equ SYNS_B=10 ; Значение SYNS_B <= SYNS_A не влияет на частоту выхода OC1B
;
ldi temp,high(SYNS_B)
sts OCR1BH,temp
ldi temp_1,low(SYNS_B)
sts OCR1BL,temp
;
Добавлено after 25 minutes 19 seconds:
То что мне нужно было с заменой выводов OC1А на OC1B без вмешательство в плату Работает!.
Ещо раз спасибо "akl".
У меня не работало из за того что значение в OCR1B было больше чем OCR1А.
- Starichok51
- Модератор
- Сообщения: 19039
- Зарегистрирован: Сб авг 14, 2010 15:05:51
- Откуда: г. Озерск, Челябинская обл.
Re: Таймеры/счётчики в AVR
потому, что режим СТС работает только по регистру OCR1A. поэтому любое значение в OCR1B никак не может влиять на частоту выхода OC1B.kuber писал(а):А значение в OCR1B меньше чем в OCR1A не влияет на частоту выхода OC1B.
даже если будет изменяться скважность на выходе OC1B частота задается регистром OCR1A.
Мудрость приходит вместе с импотенцией...
Когда на русском форуме переходят на Вы, в реальной жизни начинают бить морду.
Когда на русском форуме переходят на Вы, в реальной жизни начинают бить морду.
Re: Таймеры/счётчики в AVR
Это я выяснил в процессе эксперимента.
Замысел был перенаправить событие на другой пин OC1А на OC1B без вмешательство в плату.
Всё удачно получилось. Работает.
Всем Спасибо.
Замысел был перенаправить событие на другой пин OC1А на OC1B без вмешательство в плату.
Всё удачно получилось. Работает.
Всем Спасибо.
Re: Таймеры/счётчики в AVR
Уточню. Таймер формирует длительность полупериода (для меандра), соответственно частота на выходе будет в 2 раза ниже.
Re: Таймеры/счётчики в AVR
Приветствую. Чтобы не перепощивать, дам ссылку на топик. Кто-то может прояснить эту ситукцию? Вкратце, в режиме 15 как-то особенно работают таймеры (в топике - 14, но по итогу именно 15 режим ведет себя отлично от остальных). Стенд был простой - установка режима, задается необходимое количество пульсов в tx_counts, старт таймера, в прерывании TIMERx_COMPB_vect (одинаковое для всех режимов):
Количество пульсов отрабатывается корректно во всех режимах.
Спасибо.
Код: Выделить всё
if(!--tx_counts) {
stop_tx();
}
Спасибо.
- Starichok51
- Модератор
- Сообщения: 19039
- Зарегистрирован: Сб авг 14, 2010 15:05:51
- Откуда: г. Озерск, Челябинская обл.
Re: Таймеры/счётчики в AVR
dfxman, а зачем тебе нужна работа таймера в режиме ШИМ для работы со счетчиком tx_counts?
если тебе нужно просто прерывание таймера, то достаточно режима СТС.
если тебе нужно просто прерывание таймера, то достаточно режима СТС.
Мудрость приходит вместе с импотенцией...
Когда на русском форуме переходят на Вы, в реальной жизни начинают бить морду.
Когда на русском форуме переходят на Вы, в реальной жизни начинают бить морду.
Re: Таймеры/счётчики в AVR
Starichok51, скажем так, нужно генерировать сигналы, с определенными характеристиками, в том числе количеством импульсов, стартовать синхронно, выдавать максимально точную последовательность (в плане джиттера).
А по сути есть что сказать?
А по сути есть что сказать?
- Starichok51
- Модератор
- Сообщения: 19039
- Зарегистрирован: Сб авг 14, 2010 15:05:51
- Откуда: г. Озерск, Челябинская обл.
Re: Таймеры/счётчики в AVR
по сути я уже сказал - задал вопрос, на который не получил ответ.
Мудрость приходит вместе с импотенцией...
Когда на русском форуме переходят на Вы, в реальной жизни начинают бить морду.
Когда на русском форуме переходят на Вы, в реальной жизни начинают бить морду.
Re: Таймеры/счётчики в AVR
Занятно, вроде два профильных форума, а по делу никто ничего сказать не может. Конкретный вопрос, и даже с картинками, а ответы про все на свете, кроме, собственно, заданного вопроса. Жаль.
- Starichok51
- Модератор
- Сообщения: 19039
- Зарегистрирован: Сб авг 14, 2010 15:05:51
- Откуда: г. Озерск, Челябинская обл.
Re: Таймеры/счётчики в AVR
картинок я тут не увидел.
и, собственно, на мой заданный вопрос я ответ не получил.
одни только обиды на оба форума.
чтобы сказать по делу, нужно иметь ПОЛНУЮ информацию, а информации о проекте представлено абсолютный ноль.
и, собственно, на мой заданный вопрос я ответ не получил.
одни только обиды на оба форума.
чтобы сказать по делу, нужно иметь ПОЛНУЮ информацию, а информации о проекте представлено абсолютный ноль.
Мудрость приходит вместе с импотенцией...
Когда на русском форуме переходят на Вы, в реальной жизни начинают бить морду.
Когда на русском форуме переходят на Вы, в реальной жизни начинают бить морду.
Re: Таймеры/счётчики в AVR
Да какие обиды, что Вы. Просто констатация. Я не спрашивал, как мне что-то сделать, поэтому никакого смысла рассказывть про проект нет, это просто увод в сторону от темы. Картинки на другом форуме, сразу про это написал. Вопрос конкретный, про поведение определенного режима работы таймера. Не более. Полагал, что есть более опытные люди, которые с этим сталкивались, может, я чего не дочитал в даташитах или апнотах. Ан нет. Ладно, считаю вопрос закрытым, дальнейшую дискуссию бессмысленной.