Таймеры/счётчики в AVR
Re: Таймеры/счётчики в AVR
Привет всем, у меня вопрос такой: можно ли "склеить" 2 таймера на Меге8 - таймер1 и таймер2 с расчётом получить 24 битный таймер? Необязательно напрямую, можно через прерывания, например, таймер2 по переполнению а таймер1 работал бы в режиме СТС?. Просто нехватает точности 16-разрядного. Мне нужен 1-секундный интервал. Сейчас имею: частота ядра 16Мгц от внешнего генератора SG51P, предделитель 1/256, считаем до 62500. Получаю слишком длинную секунду. При 62499 - слишком короткую. Вот и думаю, если выключить прескалер и склеить таймеры, можно было бы иметь секунду с точностью 0,0625 мкс. Или есть способ попроще? Типа сделать секунду короче и выключить на некоторое время таймер1? Но нехочется делать тупых задержек. Подскажите, пожалуйста.
ПС. Питание стабильное, температура-тоже. Пишу в Студии на асме
ПС. Питание стабильное, температура-тоже. Пишу в Студии на асме
Я всё-всё узнAю и стану профессором.
Re: Таймеры/счётчики в AVR
Расширить Т1 дополнительной регистровой парой, в которой считать число переполнений. Т1 без предделителя, после 244 переполнений досчитать ещё 9'216 тактов.
Последний раз редактировалось akl Пн июл 18, 2016 10:12:54, всего редактировалось 1 раз.
- ARV
- Ум, честь и совесть. И скромность.
- Сообщения: 18544
- Зарегистрирован: Чт дек 28, 2006 08:19:56
- Откуда: Новочеркасск
- Контактная информация:
Re: Таймеры/счётчики в AVR
что мешает использовать предделитель 1024 и CTC на значение 15625?
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
Re: Таймеры/счётчики в AVR
Ну блин!!, А что сам-то не додумался? Этож надо- на ровном месте! Спасибо, akl!akl писал(а):Расширить Т1 дополнительной регистровой парой, в которой считать число переполнений. Т1 без предделителя.
ARV, и Вам спасибо, только с 16-разрядным счётчиком как ни крути, а точность интервала зависит только от точности генератора и его частоты., Я уже пробовал всякие варианты. Вывод - надо увеличить разрядность счётчика
Я всё-всё узнAю и стану профессором.
Re: Таймеры/счётчики в AVR
Ну вот и программка, ещё не симулял. Это если я правильно понял. Зае заразмножался с подсчётом что надо (в идеале) подсунуть в регистр Sekunda. И я не уверен, что подсчитал правильно, наверно, в железе надо будет тестить.
Спойлер
Код: Выделить всё
.cseg
.org 0
rjmp reset
.org OC1Aaddr
rjmp MatchT1
.org OVF1addr
rjmp OvfT1
.equ Sekunda = 9216 ;4321 counted manually
.def temp r16
.def cnt1 r17
.def cnt2 r18
.def ;...............
reset:
ldi temp,Low(RAMEND)
out SPL,temp
ldi temp,High(RAMEND)
out SPH,temp
;PORT ini....
;other settings
clr temp
out TCCR1A,temp
ldi temp,1<<CS10
out TCCR1B,temp
ldi temp,1<<TOIE1
out TIMSK,temp
ldi cnt1,244
sei
main:
rjmp main
OvfT1:
in r1,sreg ;1
dec cnt1 ;1
brne exit1 ;2/1
ldi temp,high(Sekunda) ;prepare timer1 ;1
out OCR1AH,temp ;to count in CTC mode ;1
ldi temp,low(Sekunda) ;1
out OCR1AL,temp ;1
ldi temp,(1<<WGM12)|(1<<CS10) ;1
out TCCR1B,temp ;1
clr temp ;do I need this "clr"? ;1
ldi temp,1<<OCIE1A ;1
out TIMSK,temp ;1
exit1:
out sreg,r1 ;1
reti ;4
;total OvfT1: 8/17 cycles or 0,5/1,0625 uS @16MHz approx.+rjmp=2*244+reti=4*244
;14/23, with rjmp/reti, timer1=65536+2+4=65542
;243*(65542+14)+65542+23+6=15995679 uS
;Sekunda=4321
MatchT1:
in r1,sreg ;1
ldi cnt1,244 ;1
clr temp ;1
out TCCR1A,temp ;1
ldi temp,1<<CS10 ;1
out TCCR1B,temp ;1 =6 ticks=0,375 uS, timer starts here
ldi temp,1<<TOIE1 ;1
out TIMSK,temp ;1
; Have 1 Second here...
out sreg,r1
reti
Я всё-всё узнAю и стану профессором.
Re: Таймеры/счётчики в AVR
Вы правильно поняли. Правда, код с недостатками.
Так можно формировать секунду для любого кварца.
Спойлер
Код: Выделить всё
.INCLUDE "m8DEF.INC"
.cseg
.org 0
rjmp reset
.org OC1Aaddr
SET
RET
; rjmp MatchT1
.org OVF1addr
OvfT1:
in r1,sreg ;1
dec cnt1 ;1
brne exit1 ;2/1
ldi temp,(1<<WGM12)|(1<<CS10) ;1
out TCCR1B,temp ;1
ldi temp,1<<OCIE1A ;1
out TIMSK,temp ;1
;*************
OUT TIFR,TEMP
;*************
exit1:
out sreg,r1 ;1
reti ;4
; rjmp OvfT1
;*************************************************
.equ Sekunda = 9216 ;4321 counted manually
.def temp = r16
.def cnt1 = r17
.def cnt2 = r18
;.def ;...............
reset:
ldi temp,Low(RAMEND)
out SPL,temp
ldi temp,High(RAMEND)
out SPH,temp
;PORT ini....
;other settings
GO:
CLI
ldi temp,high(Sekunda-1) ;prepare timer1 ;1
out OCR1AH,temp ;to count in CTC mode ;1
ldi temp,low(Sekunda-1) ;1
out OCR1AL,temp ;1
ldi temp,1<<CS10
out TCCR1B,temp
ldi temp,1<<TOIE1
out TIMSK,temp
OUT TIFR,temp
ldi cnt1,244
CLT
sei
main:
BRTC main
RJMP GO
; rjmp main
;total OvfT1: 8/17 cycles or 0,5/1,0625 uS @16MHz approx.+rjmp=2*244+reti=4*244
;14/23, with rjmp/reti, timer1=65536+2+4=65542
;243*(65542+14)+65542+23+6=15995679 uS
;Sekunda=4321
;MatchT1:
; in r1,sreg ;1
; ldi cnt1,244 ;1
; clr temp ;1
; out TCCR1A,temp ;1
; ldi temp,1<<CS10 ;1
; out TCCR1B,temp ;1 =6 ticks=0,375 uS, timer starts here
; ldi temp,1<<TOIE1 ;1
; out TIMSK,temp ;1
; Have 1 Second here...
; out sreg,r1
; reti
.EXIT
Спойлер
Код: Выделить всё
.INCLUDE "m8DEF.INC"
.equ Fo=16012344
.equ OVER=Fo/65536
.equ Sekunda=Fo-OVER*65536
.def temp = r16
.def cnt1 = r17
.def cnt2 = r18
.cseg
.org 0
rjmp reset
.org OC1Aaddr
SET
RET
.org OVF1addr
OvfT1:
; in r1,sreg ;1
dec cnt1 ;1
brne exit1 ;2/1
ldi temp,(1<<WGM12)|(1<<CS10) ;1
out TCCR1B,temp ;1
ldi temp,1<<OCIE1A ;1
out TIMSK,temp ;1
;*************
OUT TIFR,TEMP
;*************
exit1:
; out sreg,r1 ;1
reti ;4
;*************************************************
reset:
ldi temp,Low(RAMEND)
out SPL,temp
ldi temp,High(RAMEND)
out SPH,temp
;PORT ini....
;other settings
GO:
CLI
LDI R22,(1<<SE)
OUT MCUCR,R22 ; режим SLEEP IDLE
ldi temp,high(Sekunda-1) ;prepare timer1 ;1
out OCR1AH,temp ;to count in CTC mode ;1
ldi temp,low(Sekunda-1) ;1
out OCR1AL,temp ;1
ldi temp,1<<CS10
out TCCR1B,temp
ldi temp,1<<TOIE1
out TIMSK,temp
OUT TIFR,temp
LDI cnt1,OVER
; ldi cnt1,244
CLT
sei
main:
SLEEP
BRTC main
RJMP GO
.EXIT
- ARV
- Ум, честь и совесть. И скромность.
- Сообщения: 18544
- Зарегистрирован: Чт дек 28, 2006 08:19:56
- Откуда: Новочеркасск
- Контактная информация:
Re: Таймеры/счётчики в AVR
наверное, можно, не вникал. но принципиально - зачем это может быть необходимо? все-таки достаточно "частые" прерывания по считающему на 16МГц таймеру - это весьма приличная нагрузка на ядро - оно действительно необходимо?akl писал(а):Так можно формировать секунду для любого кварца.
например, человечество не заморачивается с тем, что Земля облетает Солнце не ровно за 365 дней... а просто раз в 4 года добавляют сутки, и все. если у вас кварц не точный, то, например, для часов было бы достаточно каждую, допустим, 12845-ю секунду увеличивать счетчик секунд не на 1, а на 2, или наоборот, пропускать инкремент счетчика - и точность хода часов была бы 1 секунда в год.
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
Re: Таймеры/счётчики в AVR
Ув. ARV, в системах охраны так и сделано (DSC). Есть ячейка, в которой записано количество секунд последней в сутках минуты. По дефолту там 60. Но.. надо так..
akl, спасибо Вам, сейчас разбираюсь как и что в Вашем коде (в перерывах между основной работой
).
Ещё не понял, почему Sekunda-1 и зачем писать в TIFR?. По даташиту :
Вот я почему-то и подумал, что флаг устанавливается аппаратно.
Где я сморозил?
akl, спасибо Вам, сейчас разбираюсь как и что в Вашем коде (в перерывах между основной работой
Ещё не понял, почему Sekunda-1 и зачем писать в TIFR?. По даташиту :
• Bit 4 – OCIE1A: Timer/Counter1, Output Compare A Match Interrupt Enable
When this bit is written to one, and the I-flag in the Status Register is set (interrupts globally
enabled), the Timer/Counter1 Output Compare A match interrupt is enabled. The corresponding
Interrupt Vector (see “Interrupts” on page 46) is executed when the OCF1A Flag, located in
TIFR, is set.
Вот я почему-то и подумал, что флаг устанавливается аппаратно.
Где я сморозил?
Я всё-всё узнAю и стану профессором.
Re: Таймеры/счётчики в AVR
Следовательно, для точного сравнения нужно заносить значение на 1 меньшее требуемого.If TCNT equals OCR1x the comparator signals a match. A match will set the Output Compare Flag (OCF1x) at the next timer clock cycle. If enabled (OCIE1x = 1), the Output Compare Flag generates an Output Compare interrupt.
Да, а вот сбрасываются они аппаратно при обработке прерывания или программной записью лог. 1. Флаги в AVR всегда расположены на той же позиции в регистре локально разрешающем оные.dgrett писал(а):Вот я почему-то и подумал, что флаг устанавливается аппаратно.
Запись типа
Код: Выделить всё
ldi temp,1<<TOIE1
out TIMSK,temp
OUT TIFR,temp
Последний раз редактировалось akl Вт июл 19, 2016 08:28:04, всего редактировалось 1 раз.
Re: Таймеры/счётчики в AVR
Вот, теперь проясняется
Читать и читать даташит. И чтоб не отвлекал никто 
Я всё-всё узнAю и стану профессором.
Re: Таймеры/счётчики в AVR
Опять вопрос, хотя работает и так. Но может необязательно каждую секунду загружать OCR1A ? Можно его грузить единожды в общих настройках. Ведь менять я его не собираюсь в ходе программы? Или тут ещё какие камни под водой с острыми краями?
Я всё-всё узнAю и стану профессором.
Re: Таймеры/счётчики в AVR
В такой программе можно и единожды загружать OCR1A. Но, По возможности, подтверждать режим работы считаю более надежным решением. Или, например, программу можно переписать, используя только прерывание OC1A.
Re: Таймеры/счётчики в AVR
Спасибо, я тоже так подумал, для надёжности, ведь несколько доп. тактов (их количество не меняется в ходе программы) не "спасёт отца русской демократии".
Я всё-всё узнAю и стану профессором.
- hosturik
- Потрогал лапой паяльник
- Сообщения: 354
- Зарегистрирован: Чт июл 24, 2014 23:09:23
- Откуда: Киев
Re: Таймеры/счётчики в AVR
Подскажите что может быть. Есть atmega 168, работает на
8 МГц, в Makefile тоже указано 8000000. Таймер с максимальным предделителем на 1024 срабатывает по переполнению, срабатывает в четыре раза медленнее чем нужно. Считал так.
1/(8 000 000/1 024/1 024)*1 000 = 131 мс
В реальности получается 32 миллисекунды
Что это за глюк и как с ним боротся?
Компилятор - Winavr 2010
8 МГц, в Makefile тоже указано 8000000. Таймер с максимальным предделителем на 1024 срабатывает по переполнению, срабатывает в четыре раза медленнее чем нужно. Считал так.
1/(8 000 000/1 024/1 024)*1 000 = 131 мс
В реальности получается 32 миллисекунды
Что это за глюк и как с ним боротся?
Компилятор - Winavr 2010
Re: Таймеры/счётчики в AVR
1000000/8000000=0.125мкс. 0,125*1024*256=32768мкс или 32,768мс
- baron_P
- Нашел транзистор. Понюхал.
- Сообщения: 183
- Зарегистрирован: Вт сен 14, 2010 23:07:10
- Откуда: Ростов
Re: Таймеры/счётчики в AVR
baron_P писал(а):Доброго времени суток.
Есть странный затуп с МК ATMega8. Хочу использовать для генерации ШИМ-сигнала Т/С1 в режиме FastPWM со счетом до ICR1.
...
Вся эта штука работает правильно, если выбран обычный FastPWM или, например, PhaseCorrectPWM c отсчетом до ICR1. А если выбрать нужный мне FastPWM с отсчетом до ICR1, то не работает функция считывания нажатия кнопок. Если режим переключить переменной, то все ок (запускается ШИМ и тд.), а включить вручную никак: состояние PINC (на котором висят кнопки и входные сигналы) ни в какую не хочет считываться.
Подскажите, пожалуйста, куда примерно думать. Что-то совсем не могу понять, как это может быть связано между собой.
Нашел проблему. При такой
Код: Выделить всё
TCCR1A |= (1 << COM1A1)Код: Выделить всё
TCCR1A |= (1 << COM1A1) | (1 << COM1A1)Код: Выделить всё
OCR1A = ICR1 - PWM_refWe do what we must because we can (c) GLaDOS
- hosturik
- Потрогал лапой паяльник
- Сообщения: 354
- Зарегистрирован: Чт июл 24, 2014 23:09:23
- Откуда: Киев
Re: Таймеры/счётчики в AVR
Подскажите, можно ли так делить частоту прерываний, все работает, но правильно ли так делать?
ISR (TIMER2_OVF_vect) //32 миллисекунды
{
static char delenie_in_seven = 0;
if(++delenie_in_seven == 7) //Получаем нужную длительность такта 229 миллисекунд
{
delenie_in_seven = 0;
//Код
}
}
ISR (TIMER2_OVF_vect) //32 миллисекунды
{
static char delenie_in_seven = 0;
if(++delenie_in_seven == 7) //Получаем нужную длительность такта 229 миллисекунд
{
delenie_in_seven = 0;
//Код
}
}
Re: Таймеры/счётчики в AVR
Теоретически, никто не запрещает использовать статические переменные в обработчике прерывания. Единственное, я бы убрал начальную инициализацию, т.к. static по требованию стандарта зануляется перед первым употреблением. Оно, конечно, и в таком виде абсолютно законно, но несколько двусмысленно. По аналогии с обычными переменными возникает ассоциация, что переменная обнуляется при каждом входе в обработчик, что на самом деле не так.
Re: Таймеры/счётчики в AVR
Помогите с таймером в меге168 1MHZ не срабатывает каждые 5 секунд.
Код: Выделить всё
OCR2A = 0x1E85;
TCCR2A |= (1 << WGM21);
// Set to CTC Mode
TIMSK2 |= (1 << OCIE2A);
//Set interrupt on compare match
TCCR2B |= (1 << CS21);
interrupt [TIM2_COMPA] void timer2_compa_isr(void)
{
unsigned char i;
LED_ON;
delay_us(400);
LED_OFF;
}
- COKPOWEHEU
- Говорящий с текстолитом
- Сообщения: 1525
- Зарегистрирован: Чт июн 10, 2010 20:11:19
Re: Таймеры/счётчики в AVR
А ничего что у m168 таймер T2 восьмибитный?OCR2A = 0x1E85;
Да и остальная логика на первый взгляд странная.
Чему равны остальные биты этого регистра? Лучше при настройке делать прямое присваивание.TCCR2A |= (1 << WGM21);
TCCR2B |= (1 << CS21); делитель F_CPU/8 = 125 кГц
OCR2A = 0x1E85; если предположить, что этот регистр 16-битный, делитель равен 7814
Тогда прерывание возникает с частотой F_CPU/8/7814 = 16 Гц, то есть с интервалом 62,5 мс.