Таймеры/счётчики в AVR
- Ivanoff-iv
- Друг Кота
- Сообщения: 7077
- Зарегистрирован: Пт ноя 11, 2016 05:48:09
- Откуда: Сердце Пармы
Re: Таймеры/счётчики в AVR
да.
Для тех, кто не учил магию мир полон физики 
Безграмотно вопрошающим про силовую или высоковольтную электронику я не отвечаю, а то ещё посадят за участие в (само)убиении оболтуса...
Безграмотно вопрошающим про силовую или высоковольтную электронику я не отвечаю, а то ещё посадят за участие в (само)убиении оболтуса...
- Реклама
Re: Таймеры/счётчики в AVR
Даже не знаю в какую тему писать но по смыслу сюда. Ни у кого не бывало, что прерывание срабатывает не как положено, например на atmega8 16 битный таймер настроен на срабатывание по переполнению раз в 10 сек, все прекрасно работает. меняешь кварц, соответственно меняешь настройки частоты камня, I2C, UART. И прерывание работает но не так. TCCR1B|=((1<<CS12)|(1<<CS10)); TCNT1=29535; кварц 3,6864МГц, но срабатывает не раз в 10 сек, а в 18, то есть полный перебор с 0. Сделано в атмел студио. Может кто помочь объяснить что не так? Кстати, 8 битный таймер также начал филонить аналогично.
TCCR0|=((1<<CS02)|(1<<CS00)); //предделитель 1024, срабатывает раз в (1/3686400)*1024*255=0,0708(3) секунды, для 0,02с нужно записать tcnt0=183 раз в 0,02с ровно;
TIMSK |= (1<<TOIE0); // разрешить прерывание по переполнению таймера счетчика 0;
TCNT0=183; //начало счета от 183;
TCCR0|=((1<<CS02)|(1<<CS00)); //предделитель 1024, срабатывает раз в (1/3686400)*1024*255=0,0708(3) секунды, для 0,02с нужно записать tcnt0=183 раз в 0,02с ровно;
TIMSK |= (1<<TOIE0); // разрешить прерывание по переполнению таймера счетчика 0;
TCNT0=183; //начало счета от 183;
- Z_h_e
- Собутыльник Кота
- Сообщения: 2708
- Зарегистрирован: Сб май 14, 2011 21:16:04
- Откуда: г. Чайковский
Re: Таймеры/счётчики в AVR
Потому что тайме будет считать до 65535 и затем обнулится и начнет считать с начала, с нуля, а не с 29535.
Re: Таймеры/счётчики в AVR
Всё верно… используете таймер 16 разрядный, а в формуле 255 вместо 65535… потому так и получается.
- Реклама
Re: Таймеры/счётчики в AVR
Всем спасибо кто ответил. Походу камешек сдох - прописал так:
TCNT1 =29535;
USART_Transmit(contr);
USART_Transmit(TCNT1H);
USART_Transmit(TCNT1L);
так он переменную правильно передает - а значение регистра равно 0.
То есть он просто напросто его не записывает.
перезапись, стирание, сброс настроек - не работает.
придется попаять.
PS
1.Z_h_e - раньше работало и не сбивалось, было все четко.
2.dgrett - СТС - не мое.
3.АСУ - насчет 255 - это относится к таймеру 8 битному, на нем тоже самое.
TCNT1 =29535;
USART_Transmit(contr);
USART_Transmit(TCNT1H);
USART_Transmit(TCNT1L);
так он переменную правильно передает - а значение регистра равно 0.
То есть он просто напросто его не записывает.
перезапись, стирание, сброс настроек - не работает.
придется попаять.
PS
1.Z_h_e - раньше работало и не сбивалось, было все четко.
2.dgrett - СТС - не мое.
3.АСУ - насчет 255 - это относится к таймеру 8 битному, на нем тоже самое.
Re: Таймеры/счётчики в AVR
[uquote="Mixail_BM",url="/forum/viewtopic.php?p=3498182#p3498182"]3.АСУ - насчет 255 - это относится к таймеру 8 битному, на нем тоже самое.[/uquote]
Да... я не туда посмотрел...
Да... я не туда посмотрел...
- Z_h_e
- Собутыльник Кота
- Сообщения: 2708
- Зарегистрирован: Сб май 14, 2011 21:16:04
- Откуда: г. Чайковский
Re: Таймеры/счётчики в AVR
ну тогда ладноMixail_BM писал(а):1.Z_h_e - раньше работало и не сбивалось, было все четко.
Добавлено after 5 minutes 56 seconds:
Из серии раньше работало. Еще поглядите как нужно правильно считывать значение 16битного счетчика в разделе "Accessing 16-bit Registers"Mixail_BM писал(а):USART_Transmit(TCNT1H);
USART_Transmit(TCNT1L);
Re: Таймеры/счётчики в AVR
[uquote="Z_h_e",url="/forum/viewtopic.php?p=3498165#p3498165"]Потому что тайме будет считать до 65535 и затем обнулится и начнет считать с начала, с нуля, а не с 29535.[/uquote]
Прошу прощенья, вы были правы. Надо вводить при каждом прерывании. Но он, зараза так хорошо работал.
Нашел на одном сайте, что TCNT1 =29535; надо вводить в самом начале прерывания, первой строчкой. Теперь все отрабатывает
Прошу прощенья, вы были правы. Надо вводить при каждом прерывании. Но он, зараза так хорошо работал.
Нашел на одном сайте, что TCNT1 =29535; надо вводить в самом начале прерывания, первой строчкой. Теперь все отрабатывает
Re: Таймеры/счётчики в AVR
Всем привет.
Я тут пытаюсь разобраться с Timer/Counter1 (ATmega16), режим CTC, вывод OC1A устанавливается в "1", когда TCNT достигнет заданного значения в OCR1A.
Пользуюсь AVRStudio 4.06, в железе пока не проверял.
Запускаю счетчик так:
Когда счетчик TCNT досчитывает до заданного значения, вывод OC1A устанавливается в "1".
После срабатывания счетчика, запрещаю его работу:
Подскажите, как правильно сбрасывать пин PD5 (OC1A)?
cbi PortD,5 - результата не дает.
cbi PinD,5 - пин порта сбрасывается. По крайней мере, в AVRStudio...
Следующий код сбрасывает вывод PD5 в ноль:
Еще можно принудительно изменить состояние вывода OC1A путем записи "1" в FOC1A регистра TCCR1A, но тогда надо перенастраивать этот TCCR1A... Что-то у меня с этим ничего не получилось. Перенастраивал по-всякому, пин PD5 не сбрасывается.
Я тут пытаюсь разобраться с Timer/Counter1 (ATmega16), режим CTC, вывод OC1A устанавливается в "1", когда TCNT достигнет заданного значения в OCR1A.
Пользуюсь AVRStudio 4.06, в железе пока не проверял.
Запускаю счетчик так:
Код: Выделить всё
in temp,TCCR1A
sbr temp,0b11000000 ;При совпадении (CTC) вывод OC1A устанавливается в "1"
out TCCR1A,temp
ldi temp,$01
out OCR1AH,temp
ldi temp,$FF
out OCR1AL,temp
in temp,TCCR1B
sbr temp,0b00001001 ;Режим CTC. Тактовая частота CK/1
out TCCR1B,tempПосле срабатывания счетчика, запрещаю его работу:
Код: Выделить всё
in temp,TCCR1B
cbr temp,0b00001001 ;Обнулить биты
out TCCR1B,temp
clr temp
out TCNT1H,temp ;Очистить счетчик
out TCNT1L,temp
in temp,TIFR
sbr temp,0b00010000 ;Сбросить флаг OCF1A
out TIFR,tempcbi PortD,5 - результата не дает.
cbi PinD,5 - пин порта сбрасывается. По крайней мере, в AVRStudio...
Следующий код сбрасывает вывод PD5 в ноль:
Код: Выделить всё
in temp,TCCR1A
cbr temp,0b11000000 ;Обнулить биты COM1A1 и COM1A0
out TCCR1A,tempRe: Таймеры/счётчики в AVR
Не хватает SBI DDRD,5. Тогда и CBI PORTD,5 заработает, когда уберете COM1A1, COM1A0.
Последний раз редактировалось akl Ср ноя 07, 2018 17:53:21, всего редактировалось 1 раз.
Re: Таймеры/счётчики в AVR
[uquote="akl",url="/forum/viewtopic.php?p=3500064#p3500064"]Не хватает SBI DDRD,5.[/uquote]5-ый пин порта D у меня на выход настроен (все согласно даташита), и в "0" сброшен.
[uquote="akl",url="/forum/viewtopic.php?p=3500064#p3500064"]Тогда и CBI PORTD,5 заработает, когда уберете COM1A1, COM1A0.[/uquote]Когда я убираю COM1A1, COM1A0, вывод PD5 сам сбрасывается в ноль и дополнительная команда CBI PORTD,5 не нужна.
[uquote="akl",url="/forum/viewtopic.php?p=3500064#p3500064"]CBI PIND,5-режим переключения в новых камнях, у ATmega16 не работает.[/uquote]AVRStudio 4.06 как бы не очень новая и m16def.inc от сентября 2001-го. ATmega16 тогда не очень-то и старая была. Странно.
[uquote="akl",url="/forum/viewtopic.php?p=3500064#p3500064"]Тогда и CBI PORTD,5 заработает, когда уберете COM1A1, COM1A0.[/uquote]Когда я убираю COM1A1, COM1A0, вывод PD5 сам сбрасывается в ноль и дополнительная команда CBI PORTD,5 не нужна.
[uquote="akl",url="/forum/viewtopic.php?p=3500064#p3500064"]CBI PIND,5-режим переключения в новых камнях, у ATmega16 не работает.[/uquote]AVRStudio 4.06 как бы не очень новая и m16def.inc от сентября 2001-го. ATmega16 тогда не очень-то и старая была. Странно.
Re: Таймеры/счётчики в AVR
Вам кодом был показан вариант сброса PD5/OC1A ATmega16.
Старые камни или новые не суть. Главное, чтобы была объявлена возможность
Старые камни или новые не суть. Главное, чтобы была объявлена возможность
У mega16(a) такого режима нет.Toggling the Pin
Writing a '1' to PINxn toggles the value of PORTxn, independent on the value of DDRxn. The SBI instruction can be used to toggle one single bit in a port.
Re: Таймеры/счётчики в AVR
[uquote="akl",url="/forum/viewtopic.php?p=3500203#p3500203"]Вам кодом был показан вариант сброса PD5/OC1A ATmega16.[/uquote]Как я понял, пин PD5 вы очищаете так же, как и я - обнулением TCCR1A (+очистка OCF1A), что и требовалось подтвердить. Правда, зачем-то вы используете для этого ZH. У вас в нем всегда 0 что ли?
Здесь нет явной записи ZH, т.е. в нем может быть все, что угодно. И что означает "длительность 1 на PD5 30 тактов"? А, наверное, длительность лог. единицы на пине PD5 30 тактов...
А тут что означает "длительность 1 на PD5 14 тактов"? Ок, тут тоже тогда понятно.
И много лишнего в этом коде - запрещение аналогового компаратора, режим сна, прерывания. Спасибо, конечно, но я всего этого не просил.
Я стараюсь более понятно писать, чтобы можно было понять свою же программу спустя годы. И уж тем более, если придется кому-то свой код показать.
Я вот МК не занимался более 10 лет и сейчас, просматривая свои программы начала 2000-х, очень самому себе благодарен за понятные комментарии, оставленные тогда к разным участкам кода.
У каждого своя манера писать код, и легче написать свой, чем разобраться в чужом.
А стек я вот так назначаю (в конце SRAM):
Спойлер
Код: Выделить всё
.INCLUDE "M16def.inc"
.equ Fo=8000000
.def TEMP=R16
;************************************************
.CSEG
.ORG $0000
RESET:
RJMP START ; On Reset
.ORG $000C
T1_COMP_A:
RETI
;*************************************************
;*************************************************
;*************************************************
START:
LDI ZH,0
LDI ZL,-1
OUT SPH,ZH
OUT SPL,ZL
SBI ACSR,ACD ; выключить аналоговый компаратор
SBI DDRD,5
LDI R16,1<<SE
OUT MCUCR,R16 ; режим SLEEP IDLE
ldi temp,$01
out OCR1AH,temp
ldi temp,$FF
out OCR1AL,temp
OUT TCCR1A,ZH ;длительность 1 на PD5 30 тактов
LDI R17,1<<COM1A1|1<<COM1A0
OUT TCCR1A,R17
LDI R16,1<<OCIE1A ; прерывания
OUT TIMSK,R16
OUT TIFR,R16
LDI R16,1<<WGM12|1<<CS10 ; Fo/1, CTC
OUT TCCR1B,R16
WAIT:
SEI
SLEEP
; OUT TCCR1A,ZH ;длительность 1 на PD5 14 тактов
NOP
RJMP START
.EXITКод: Выделить всё
ldi temp,$01
out OCR1AH,temp
ldi temp,$FF
out OCR1AL,temp
OUT TCCR1A,ZH ;длительность 1 на PD5 30 тактовКод: Выделить всё
WAIT:
SEI
SLEEP
; OUT TCCR1A,ZH ;длительность 1 на PD5 14 тактов
NOP
RJMP START
.EXITИ много лишнего в этом коде - запрещение аналогового компаратора, режим сна, прерывания. Спасибо, конечно, но я всего этого не просил.
Я стараюсь более понятно писать, чтобы можно было понять свою же программу спустя годы. И уж тем более, если придется кому-то свой код показать.
Я вот МК не занимался более 10 лет и сейчас, просматривая свои программы начала 2000-х, очень самому себе благодарен за понятные комментарии, оставленные тогда к разным участкам кода.
У каждого своя манера писать код, и легче написать свой, чем разобраться в чужом.
А стек я вот так назначаю (в конце SRAM):
Код: Выделить всё
ldi temp,high(RAMEND) ;назначить стек
out SPH,temp
ldi temp,low(RAMEND)
out SPL,tempRe: Таймеры/счётчики в AVR
Не пойму, почему T/C1 по-разному считает.
Здесь у меня бесконечный цикл. В начале T/C1 настраивается и запускается. 0.5 секунды он считает; после окончания счета выставляет "1" на 5 пине порта D. После проходит еще ~0.5 сек., T/C1 останавливается и обнуляется ("0" на 5 пине порта D). И по-новой. 0.5 сек - "0", 0.5 сек - "1".
Но, почему-то, с момента, когда устанавливается TCCR1B и счетчик начинает считать, и до момента окончания счета, когда выставляется флаг OCF1A проходит разное время. 500195.00 мкс, 500156.50 мкс, 500030.50 мкс и т.д. (кварц на 4 МГц)
А если предделитель не использовать, то считает одинаково.
Спойлер
Код: Выделить всё
ldi r16,$07 ;$07A1 = 0.5 секунды
out OCR1AH,r16
ldi temp,$A1
out OCR1AL,r16
;***********************************
;Разрешить Timer/Counter1
Cycle: ldi r16,(1<<COM1A1)|(1<<COM1A0)
out TCCR1A,r16
ldi r16,(1<<WGM12)|(1<<CS12)|(1<<CS10) ;Установить бит WGM12=1 (режим CTC). Предделитель CK/1024 (CS12=1, CS11=0, CS10=1)
out TCCR1B,r16
;***********************************
;Временная задержка (1.011491 сек) на 4 МГц
Tim_dl: ldi r20,$15
ldi r21,$A9
ldi r22,$18
D_r_1x: dec r22
brne D_r_1x
ldi r22,$FF
dec r21
brne D_r_1x
ldi r21,$FF
dec r20
brne D_r_1x
;***********************************
;Запретить и обнулить Timer/Counter1
ldi r16,(0<<WGM12)|(0<<CS12)|(0<<CS10)
out TCCR1B,r16
ldi r16,(0<<COM1A1)|(0<<COM1A0)
out TCCR1A,r16
clr r16
out TCNT1H,r16
out TCNT1L,r16
ldi r16,1<<OCF1A
out TIFR,r16
;***********************************
rjmp CycleНо, почему-то, с момента, когда устанавливается TCCR1B и счетчик начинает считать, и до момента окончания счета, когда выставляется флаг OCF1A проходит разное время. 500195.00 мкс, 500156.50 мкс, 500030.50 мкс и т.д. (кварц на 4 МГц)
А если предделитель не использовать, то считает одинаково.
Re: Таймеры/счётчики в AVR
Почувствуйте разницу.
Спойлер
Код: Выделить всё
.INCLUDE "M16def.inc"
.equ Fo=4000000
;************************************************
.CSEG
.ORG $0000
RESET:
; RJMP START ; On Reset
;.ORG $000C
;T1_COMP_A:
; RETI
;*************************************************
;*************************************************
;*************************************************
START:
; LDI ZH,0
; LDI ZL,-1
; OUT SPH,ZH
; OUT SPL,ZL
SBI DDRD,5
; LDI R16,1<<SE
; OUT MCUCR,R16 ; режим SLEEP IDLE
LDI R16,HIGH(5*Fo/10/64-1) ; (5*Fo/10/64-1)= 0.5 секунды
OUT OCR1AH,R16
LDI R16,LOW(5*Fo/10/64-1)
OUT OCR1AL,R16
LDI R16,0<<COM1A1|1<<COM1A0
OUT TCCR1A,R16 ; переключение лапы PD5/OC1A при совпадении
LDI R16,1<<WGM12|1<<CS11|1<<CS10 ; Fo/64, CTC
OUT TCCR1B,R16
; LDI R16,1<<OCIE1A
; OUT TIMSK,R16
; OUT TIFR,R16
WAIT:
; SEI
; SLEEP
; NOP
RJMP WAIT
.EXIT
Re: Таймеры/счётчики в AVR
Немножко не то, что мне нужно.
Я буду "вручную" обнулять счетчик, а в "1" он должен перебрасываться сам, по счету. То, что я выложил, это я временно так организовал код - для проверки.
Мне непонятно, почему счетчик после обнуления и нового запуска отмеряет разные интервалы времени до установки OC1A в "1".
После выполнения команды "clr r16" (в конце, перед "out TCNT1H,r16") OC1A сбрасывается в "0" и в этот момент я засекаю время (обнуляю Stop Watch). Потом ловлю момент установки OC1A в "1" (долго и муторно) и это время каждый раз разное. А почему - мне непонятно...
Формулы, типа "(5*Fo/10/64-1)" я редко когда использовал, уже и забыл, что так можно. Спасибо за подсказку.
Добавлено after 51 minute 13 seconds:
Мне посоветовали добавить в начале сброс предделителей (PSR10 в SFIOR), но ничего не изменилось:
Добавлено after 1 hour 52 minutes 20 seconds:
Я переписал временнУю задержку, чтоб удобнее было отслеживать появление "1" на 5 пине порта D.
Сначала нужно обнулить Stop Watch в AVRStudio в момент, когда 5 пин очищается - после записи (0<<COM1A1)|(0<<COM1A0) в TCCR1A.
Теперь достаточно поставить курсор на оператор "nop" и нажать Ctrl+F10. Stop Watch в AVRStudio показывает разное прошедшее время.
Добавлено after 1 hour 37 minutes 18 seconds:
Заметил, что время, через которое срабатывает счетчик не гуляет бессистемно, а все время увеличивается от прогона к прогону. Сначала счетчик срабатывает через 499990.00 мкс, на следующем прогоне через 500012.50 мкс, потом через 500035.00 мкс и т.д. Дошло до 500214.50 мкс и следующая задержка уже была 499981.25 мкс и опять начала увеличиваться (500003.75 мкс ...). Все время увеличиваясь на одну и ту же величину - 22.5 мкс (90 тактов на 4 МГц).
Тогда я добавил в цикл 90 пустых команд "nop", и счетчик стал срабатывать через одинаковое время - 500223.25 мкс.
Но это же никуда не годится... Что это за 22.5 мкс такие?
Вот полная моя программа:
Я буду "вручную" обнулять счетчик, а в "1" он должен перебрасываться сам, по счету. То, что я выложил, это я временно так организовал код - для проверки.
Мне непонятно, почему счетчик после обнуления и нового запуска отмеряет разные интервалы времени до установки OC1A в "1".
После выполнения команды "clr r16" (в конце, перед "out TCNT1H,r16") OC1A сбрасывается в "0" и в этот момент я засекаю время (обнуляю Stop Watch). Потом ловлю момент установки OC1A в "1" (долго и муторно) и это время каждый раз разное. А почему - мне непонятно...
Формулы, типа "(5*Fo/10/64-1)" я редко когда использовал, уже и забыл, что так можно. Спасибо за подсказку.
Добавлено after 51 minute 13 seconds:
Мне посоветовали добавить в начале сброс предделителей (PSR10 в SFIOR), но ничего не изменилось:
Код: Выделить всё
Cycle: ldi r16,1<<PSR10
out SFIOR,r16
ldi r16,(1<<COM1A1)|(1<<COM1A0)
out TCCR1A,r16
ldi r16,(1<<WGM12)|(1<<CS12)|(1<<CS10) ;Установить бит WGM12=1 (режим CTC). Предделитель CK/1024 (CS12=1, CS11=0, CS10=1)
out TCCR1B,r16
...Я переписал временнУю задержку, чтоб удобнее было отслеживать появление "1" на 5 пине порта D.
Сначала нужно обнулить Stop Watch в AVRStudio в момент, когда 5 пин очищается - после записи (0<<COM1A1)|(0<<COM1A0) в TCCR1A.
Теперь достаточно поставить курсор на оператор "nop" и нажать Ctrl+F10. Stop Watch в AVRStudio показывает разное прошедшее время.
Спойлер
Код: Выделить всё
;Временная задержка (1.011491 сек) на 4 МГц
Tim_dl: ldi r20,$15
ldi r21,$A9
ldi r22,$18
D_r_1x: sbic PIND,5
nop
dec r22
brne D_r_1x
ldi r22,$FF
dec r21
brne D_r_1x
ldi r21,$FF
dec r20
brne D_r_1xЗаметил, что время, через которое срабатывает счетчик не гуляет бессистемно, а все время увеличивается от прогона к прогону. Сначала счетчик срабатывает через 499990.00 мкс, на следующем прогоне через 500012.50 мкс, потом через 500035.00 мкс и т.д. Дошло до 500214.50 мкс и следующая задержка уже была 499981.25 мкс и опять начала увеличиваться (500003.75 мкс ...). Все время увеличиваясь на одну и ту же величину - 22.5 мкс (90 тактов на 4 МГц).
Тогда я добавил в цикл 90 пустых команд "nop", и счетчик стал срабатывать через одинаковое время - 500223.25 мкс.
Но это же никуда не годится... Что это за 22.5 мкс такие?
Вот полная моя программа:
Спойлер
Код: Выделить всё
.include "m16def.inc"
.CSEG
;***** Определения портов В/В *****
;Port D:
.equ DIRD =0b00100000
.equ PUPD =0b00000000
;***** Векторы Прерываний *****
.CSEG
.org $000
rjmp RESET ;Сброс вектор
.org $002
reti
.org $004
reti
.org $006
reti
.org $008
reti
.org $00A
reti
.org $00C
reti
.org $00E
reti
.org $010
reti
.org $012
reti
.org $014
reti
.org $016
reti
.org $018
reti
.org $01A
reti
.org $01C
reti
.org $01E
reti
.org $020
reti
.org $022
reti
.org $024
reti
.org $026
reti
.org $028
reti
;***** Программное выполнение начинается здесь *****
RESET: ldi r16,high(RAMEND) ;назначить стек
out SPH,r16
ldi r16,low(RAMEND)
out SPL,r16
;*********************
;Установка портов В/В:
ldi r16,DIRD
out DDRD,r16 ;установка направления PORTD
ldi r16,PUPD
out PORTD,r16 ;инициализация PORTD
START: ldi r16,$07 ;$07A1 = 0.5 секунды
out OCR1AH,r16
ldi r16,$A1
out OCR1AL,r16
Cycle: in r16,SFIOR
sbr r16,00000001
; ldi r16,1<<PSR10
out SFIOR,r16
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
ldi r16,(1<<COM1A1)|(1<<COM1A0)
out TCCR1A,r16
ldi r16,(1<<WGM12)|(1<<CS12)|(1<<CS10) ;Установить бит WGM12=1 (режим CTC). Предделитель CK/1024 (CS12=1, CS11=0, CS10=1)
out TCCR1B,r16
;***********************************
;Временная задержка (1.011491 сек) на 4 МГц
Tim_dl: ldi r20,$15
ldi r21,$A9
ldi r22,$18
D_r_1x: sbic PIND,5
nop
dec r22
brne D_r_1x
ldi r22,$FF
dec r21
brne D_r_1x
ldi r21,$FF
dec r20
brne D_r_1x
;***********************************
;Запретить и обнулить Timer/Counter1
ldi r16,(0<<WGM12)|(0<<CS12)|(0<<CS10)
out TCCR1B,r16
ldi r16,(0<<COM1A1)|(0<<COM1A0) ;Обнулить вывод 5 порта D
out TCCR1A,r16
clr r16
out TCNT1H,r16
out TCNT1L,r16
ldi r16,1<<OCF1A
out TIFR,r16
;***********************************
rjmp CycleRe: Таймеры/счётчики в AVR
Запустил программу на своей студии 4,19. Вместо 1 секунды отсчитывается 1,6832. Думаю из-за магических чисел в программе задержки.
Переделал.
Получил

Спойлер
Спойлер
Код: Выделить всё
.include "m16def.inc"
.CSEG
;***** Определения портов В/В *****
;Port D:
.equ DIRD =0b00100000
.equ PUPD =0b00000000
.def zero=R15
;***** Векторы Прерываний *****
.CSEG
.org $000
rjmp RESET ;Сброс вектор
.org $002
reti
.org $004
reti
.org $006
reti
.org $008
reti
.org $00A
reti
.org $00C
reti
.org $00E
reti
.org $010
reti
.org $012
reti
.org $014
reti
.org $016
reti
.org $018
reti
.org $01A
reti
.org $01C
reti
.org $01E
reti
.org $020
reti
.org $022
reti
.org $024
reti
.org $026
reti
.org $028
reti
;***** Программное выполнение начинается здесь *****
RESET: ldi r16,high(RAMEND) ;назначить стек
out SPH,r16
ldi r16,low(RAMEND)
out SPL,r16
;*********************
;Установка портов В/В:
ldi r16,DIRD
out DDRD,r16 ;установка направления PORTD
ldi r16,PUPD
out PORTD,r16 ;инициализация PORTD
START:
LDI R16,HIGH(5*Fo/10/64-1) ; (5*Fo/10/64-1)= 0.5 секунды
OUT OCR1AH,R16
LDI R16,LOW(5*Fo/10/64-1)
OUT OCR1AL,R16
; ldi r16,$07 ;$07A1 = 0.5 секунды
; out OCR1AH,r16
; ldi r16,$A1
; out OCR1AL,r16
;Равно 500000/256=1953,125+1=1954*256=500224мкс
CLR ZERO
Cycle:
ldi r16,(1<<COM1A1)|(1<<COM1A0)
out TCCR1A,r16
ldi r16,(1<<WGM12)|(1<<CS12)|(1<<CS10) ;Установить бит WGM12=1 (режим CTC). Предделитель CK/1024 (CS12=1, CS11=0, CS10=1)
out TCCR1B,r16
;***********************************
.equ Fo=4000000
LDI R20,BYTE3(Fo/5)
LDI R21,BYTE2(Fo/5)
LDI R22,BYTE1(Fo/5)
LOOP:
SUBI R22,BYTE1(1)
SBCI R21,BYTE2(1)
SBCI R20,BYTE3(1)
BRNE LOOP
;Временная задержка (1.011491 сек) на 4 МГц
;Tim_dl: ldi r20,$15
; ldi r21,$A9
; ldi r22,$18
;D_r_1x: sbic PIND,5
; nop
; dec r22
; brne D_r_1x
; ldi r22,$FF
; dec r21
; brne D_r_1x
; ldi r21,$FF
; dec r20
; brne D_r_1x
;***********************************
;Запретить и обнулить Timer/Counter1
; ldi r16,(0<<WGM12)|(0<<CS12)|(0<<CS10)
; out TCCR1B,r16
OUT TCCR1A,ZERO
; ldi r16,(0<<COM1A1)|(0<<COM1A0) ;Обнулить вывод 5 порта D
; out TCCR1A,r16
; clr r16
; out TCNT1H,r16
; out TCNT1L,r16
; ldi r16,1<<OCF1A
; out TIFR,r16
;***********************************
rjmp Cycle
.EXIT
Спойлер
- Вложения
-
- TIME_1000002.PNG
- (32.9 КБ) 734 скачивания
-
- TIME_1683200.PNG
- (29.04 КБ) 806 скачиваний
Re: Таймеры/счётчики в AVR
Да задержка это такое, на глаз, особой роли точность не играет.
Просто я пытаюсь понять, как работает этот T/C1. В студии 4,06 у меня вывод PD5 половину времени в "0", половину в "1" - типа меандр. А в железе это нифига не работает - на этом PD5 практически постоянно "1" и на очень короткое время появляется "0". Я светодиод повесил и видно, как он еле-еле блымкает пару раз в секунду.
Пробовал свою программку в Atmel Studio 7.0 - она подтверждает, что на выходе практически постоянно "1". И появляется она в начале цикла, после команды:
Потом идет задержка.
После нее, после команды:
PD5 переходит в "0".
Потом идет переход в начало цикла и опять, после установки (1<<COM1A1)|(1<<COM1A0) в TCCR1A он переходит в "1".
Т.е. "0" появляется всего на несколько микросекунд, как и в железе я это вижу.
А у вас в студии 4,19 как работает? 2-3 прогона цикла сделать надо, потому что в Atmel Studio 7.0 в первом проходе "0" держится все время задержки, а потом появляется "1".
Я тут пробовал AVR Studio 5.1, Atmel Studio 6.2 и 7.0. Какие же они тяжелые в работе и неудобные...
У меня есть AVR Studio v4.16.628, попробую еще в ней.
Просто я пытаюсь понять, как работает этот T/C1. В студии 4,06 у меня вывод PD5 половину времени в "0", половину в "1" - типа меандр. А в железе это нифига не работает - на этом PD5 практически постоянно "1" и на очень короткое время появляется "0". Я светодиод повесил и видно, как он еле-еле блымкает пару раз в секунду.
Пробовал свою программку в Atmel Studio 7.0 - она подтверждает, что на выходе практически постоянно "1". И появляется она в начале цикла, после команды:
Код: Выделить всё
ldi r16,(1<<COM1A1)|(1<<COM1A0)
out TCCR1A,r16После нее, после команды:
Код: Выделить всё
ldi r16,(0<<COM1A1)|(0<<COM1A0) ;Обнулить вывод 5 порта D
out TCCR1A,r16Потом идет переход в начало цикла и опять, после установки (1<<COM1A1)|(1<<COM1A0) в TCCR1A он переходит в "1".
Т.е. "0" появляется всего на несколько микросекунд, как и в железе я это вижу.
А у вас в студии 4,19 как работает? 2-3 прогона цикла сделать надо, потому что в Atmel Studio 7.0 в первом проходе "0" держится все время задержки, а потом появляется "1".
Я тут пробовал AVR Studio 5.1, Atmel Studio 6.2 и 7.0. Какие же они тяжелые в работе и неудобные...
У меня есть AVR Studio v4.16.628, попробую еще в ней.
- SIM31
- Это не хвост, это антенна
- Сообщения: 1363
- Зарегистрирован: Чт апр 04, 2013 22:22:57
- Откуда: Белгород, РФ
Re: Таймеры/счётчики в AVR
Да можно же в конфигураторе Codevision AVR мышкой пощелкать и посмотреть какие режимы доступны ))



