Таймеры/счётчики в AVR

Обсуждаем контроллеры компании Atmel.
Аватара пользователя
Ivanoff-iv
Друг Кота
Сообщения: 7077
Зарегистрирован: Пт ноя 11, 2016 05:48:09
Откуда: Сердце Пармы

Re: Таймеры/счётчики в AVR

Сообщение Ivanoff-iv »

да.
Для тех, кто не учил магию мир полон физики :)
Безграмотно вопрошающим про силовую или высоковольтную электронику я не отвечаю, а то ещё посадят за участие в (само)убиении оболтуса...
Реклама
Mixail_BM
Открыл глаза
Сообщения: 50
Зарегистрирован: Пн июл 28, 2014 20:23:22

Re: Таймеры/счётчики в AVR

Сообщение Mixail_BM »

Даже не знаю в какую тему писать но по смыслу сюда. Ни у кого не бывало, что прерывание срабатывает не как положено, например на 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;
Реклама
Аватара пользователя
Z_h_e
Собутыльник Кота
Сообщения: 2708
Зарегистрирован: Сб май 14, 2011 21:16:04
Откуда: г. Чайковский

Re: Таймеры/счётчики в AVR

Сообщение Z_h_e »

Потому что тайме будет считать до 65535 и затем обнулится и начнет считать с начала, с нуля, а не с 29535.
Изображение
Добро всегда побеждает зло. Поэтому кто победил - тот и добрый.
dgrett
Вымогатель припоя
Сообщения: 615
Зарегистрирован: Вс дек 28, 2014 21:54:05

Re: Таймеры/счётчики в AVR

Сообщение dgrett »

У таймера1 есть режим СТС.
Я всё-всё узнAю и стану профессором.
Реклама
Эиком - электронные компоненты и радиодетали
АСУ
Друг Кота
Сообщения: 3342
Зарегистрирован: Ср янв 02, 2013 08:37:35

Re: Таймеры/счётчики в AVR

Сообщение АСУ »

Всё верно… используете таймер 16 разрядный, а в формуле 255 вместо 65535… потому так и получается.
Реклама
Mixail_BM
Открыл глаза
Сообщения: 50
Зарегистрирован: Пн июл 28, 2014 20:23:22

Re: Таймеры/счётчики в AVR

Сообщение Mixail_BM »

Всем спасибо кто ответил. Походу камешек сдох - прописал так:
TCNT1 =29535;
USART_Transmit(contr);
USART_Transmit(TCNT1H);
USART_Transmit(TCNT1L);
так он переменную правильно передает - а значение регистра равно 0.
То есть он просто напросто его не записывает.
перезапись, стирание, сброс настроек - не работает.
придется попаять.
PS
1.Z_h_e - раньше работало и не сбивалось, было все четко.
2.dgrett - СТС - не мое.
3.АСУ - насчет 255 - это относится к таймеру 8 битному, на нем тоже самое.
Реклама
АСУ
Друг Кота
Сообщения: 3342
Зарегистрирован: Ср янв 02, 2013 08:37:35

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

Сообщение Z_h_e »

Mixail_BM писал(а):1.Z_h_e - раньше работало и не сбивалось, было все четко.
ну тогда ладно

Добавлено after 5 minutes 56 seconds:
Mixail_BM писал(а):USART_Transmit(TCNT1H);
USART_Transmit(TCNT1L);
Из серии раньше работало. Еще поглядите как нужно правильно считывать значение 16битного счетчика в разделе "Accessing 16-bit Registers"
Изображение
Добро всегда побеждает зло. Поэтому кто победил - тот и добрый.
Mixail_BM
Открыл глаза
Сообщения: 50
Зарегистрирован: Пн июл 28, 2014 20:23:22

Re: Таймеры/счётчики в AVR

Сообщение Mixail_BM »

[uquote="Z_h_e",url="/forum/viewtopic.php?p=3498165#p3498165"]Потому что тайме будет считать до 65535 и затем обнулится и начнет считать с начала, с нуля, а не с 29535.[/uquote]

Прошу прощенья, вы были правы. Надо вводить при каждом прерывании. Но он, зараза так хорошо работал.
Нашел на одном сайте, что TCNT1 =29535; надо вводить в самом начале прерывания, первой строчкой. Теперь все отрабатывает
Vlad_RK
Мучитель микросхем
Сообщения: 412
Зарегистрирован: Чт июл 11, 2013 12:37:39

Re: Таймеры/счётчики в AVR

Сообщение Vlad_RK »

Всем привет.
Я тут пытаюсь разобраться с 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
Когда счетчик TCNT досчитывает до заданного значения, вывод OC1A устанавливается в "1".

После срабатывания счетчика, запрещаю его работу:

Код: Выделить всё

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,temp
Подскажите, как правильно сбрасывать пин PD5 (OC1A)?

cbi PortD,5 - результата не дает.
cbi PinD,5 - пин порта сбрасывается. По крайней мере, в AVRStudio...

Следующий код сбрасывает вывод PD5 в ноль:

Код: Выделить всё

		in		temp,TCCR1A
		cbr		temp,0b11000000	;Обнулить биты COM1A1 и COM1A0
		out		TCCR1A,temp
Еще можно принудительно изменить состояние вывода OC1A путем записи "1" в FOC1A регистра TCCR1A, но тогда надо перенастраивать этот TCCR1A... Что-то у меня с этим ничего не получилось. Перенастраивал по-всякому, пин PD5 не сбрасывается.
akl
Друг Кота
Сообщения: 4445
Зарегистрирован: Пт мар 07, 2008 06:54:43
Откуда: Ижевск

Re: Таймеры/счётчики в AVR

Сообщение akl »

Не хватает SBI DDRD,5. Тогда и CBI PORTD,5 заработает, когда уберете COM1A1, COM1A0.
Последний раз редактировалось akl Ср ноя 07, 2018 17:53:21, всего редактировалось 1 раз.
Vlad_RK
Мучитель микросхем
Сообщения: 412
Зарегистрирован: Чт июл 11, 2013 12:37:39

Re: Таймеры/счётчики в AVR

Сообщение Vlad_RK »

[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 тогда не очень-то и старая была. Странно.
akl
Друг Кота
Сообщения: 4445
Зарегистрирован: Пт мар 07, 2008 06:54:43
Откуда: Ижевск

Re: Таймеры/счётчики в AVR

Сообщение akl »

Вам кодом был показан вариант сброса PD5/OC1A ATmega16.
Старые камни или новые не суть. Главное, чтобы была объявлена возможность
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.
У mega16(a) такого режима нет.
Vlad_RK
Мучитель микросхем
Сообщения: 412
Зарегистрирован: Чт июл 11, 2013 12:37:39

Re: Таймеры/счётчики в AVR

Сообщение Vlad_RK »

[uquote="akl",url="/forum/viewtopic.php?p=3500203#p3500203"]Вам кодом был показан вариант сброса PD5/OC1A ATmega16.
Спойлер

Код: Выделить всё

  .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
[/uquote]Как я понял, пин PD5 вы очищаете так же, как и я - обнулением TCCR1A (+очистка OCF1A), что и требовалось подтвердить. Правда, зачем-то вы используете для этого ZH. У вас в нем всегда 0 что ли? :)

Код: Выделить всё

ldi      temp,$01
out      OCR1AH,temp
ldi      temp,$FF
out      OCR1AL,temp
   OUT   TCCR1A,ZH ;длительность 1 на PD5  30 тактов
Здесь нет явной записи ZH, т.е. в нем может быть все, что угодно. И что означает "длительность 1 на PD5 30 тактов"? А, наверное, длительность лог. единицы на пине PD5 30 тактов...

Код: Выделить всё

WAIT:
   SEI
   SLEEP

;   OUT   TCCR1A,ZH ;длительность 1 на PD5 14 тактов
   NOP
   RJMP   START
.EXIT
А тут что означает "длительность 1 на PD5 14 тактов"? Ок, тут тоже тогда понятно.

И много лишнего в этом коде - запрещение аналогового компаратора, режим сна, прерывания. Спасибо, конечно, но я всего этого не просил. :)
Я стараюсь более понятно писать, чтобы можно было понять свою же программу спустя годы. И уж тем более, если придется кому-то свой код показать.
Я вот МК не занимался более 10 лет и сейчас, просматривая свои программы начала 2000-х, очень самому себе благодарен за понятные комментарии, оставленные тогда к разным участкам кода. :))
У каждого своя манера писать код, и легче написать свой, чем разобраться в чужом.

А стек я вот так назначаю (в конце SRAM):

Код: Выделить всё

		ldi		temp,high(RAMEND)	;назначить стек
		out		SPH,temp
		ldi		temp,low(RAMEND)
		out		SPL,temp
Vlad_RK
Мучитель микросхем
Сообщения: 412
Зарегистрирован: Чт июл 11, 2013 12:37:39

Re: Таймеры/счётчики в AVR

Сообщение Vlad_RK »

Не пойму, почему T/C1 по-разному считает.
Спойлер

Код: Выделить всё

		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
Здесь у меня бесконечный цикл. В начале 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 МГц)
А если предделитель не использовать, то считает одинаково.
akl
Друг Кота
Сообщения: 4445
Зарегистрирован: Пт мар 07, 2008 06:54:43
Откуда: Ижевск

Re: Таймеры/счётчики в AVR

Сообщение akl »

Почувствуйте разницу. :)
Спойлер

Код: Выделить всё

	.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

Vlad_RK
Мучитель микросхем
Сообщения: 412
Зарегистрирован: Чт июл 11, 2013 12:37:39

Re: Таймеры/счётчики в AVR

Сообщение Vlad_RK »

Немножко не то, что мне нужно.
Я буду "вручную" обнулять счетчик, а в "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

...
Добавлено 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 показывает разное прошедшее время.
Спойлер

Код: Выделить всё

;Временная задержка (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
Добавлено 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 мкс такие?

Вот полная моя программа:
Спойлер

Код: Выделить всё

.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	Cycle
akl
Друг Кота
Сообщения: 4445
Зарегистрирован: Пт мар 07, 2008 06:54:43
Откуда: Ижевск

Re: Таймеры/счётчики в AVR

Сообщение akl »

Запустил программу на своей студии 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 скачиваний
Vlad_RK
Мучитель микросхем
Сообщения: 412
Зарегистрирован: Чт июл 11, 2013 12:37:39

Re: Таймеры/счётчики в AVR

Сообщение Vlad_RK »

Да задержка это такое, на глаз, особой роли точность не играет.
Просто я пытаюсь понять, как работает этот 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
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, попробую еще в ней.
Аватара пользователя
SIM31
Это не хвост, это антенна
Сообщения: 1363
Зарегистрирован: Чт апр 04, 2013 22:22:57
Откуда: Белгород, РФ

Re: Таймеры/счётчики в AVR

Сообщение SIM31 »

Да можно же в конфигураторе Codevision AVR мышкой пощелкать и посмотреть какие режимы доступны ))
Ответить

Вернуться в «AVR»