Перейти к содержанию

    

T/C1 (ATmega16) по-разному считает

Не пойму, почему 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 МГц). AVRStudio 4.06.
А если предделитель не использовать, то считает одинаково раз за разом.

		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

 

Изменено пользователем James D.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вероятно, потому, что пределитель - обычный двоичный счётчик, состояние которого не определено в момент записи в регистр TCCR1B. Для сброса счетчика пределителя в ноль используется регистр 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

 

Изменено пользователем James D.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

 

Изменено пользователем James D.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Заметил, что время, через которое срабатывает счетчик не гуляет бессистемно, а все время увеличивается от прогона к прогону. Сначала счетчик срабатывает через 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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Включите ему прерывание и в нем отслеживайте. Ваша временная задержка тоже тратит время

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Из вашего программного кода ничего не понятно. Зачем Вам таймер, если вы его не используете!!! Абсолютная бессмыслица. Как правильно уже было сказано ILYAUL, такие вещи делаются через прерывания. И дебагу от AVRStudio доверять не стоит. Есть такой прибор осциллограф называется)))

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
38 minutes ago, Сергей said:

Зачем Вам таймер, если вы его не используете!!!

Счетчик использую - он выдает "1" на PD5 в конце своего счета.

Конечно, будет работать не в таком бесконечном цикле, это просто для проверки.

AVRStudio 4.06 врет в отношении этой программки - в нем работает, а в железе - нет.

Пробовал я AVR Studio 5.1, Atmel Studio 6.2 и Atmel Studio 7.0 (какие же они тяжелые в работе), заметил, что в них как-то странно этот пин PD5 себя ведет - практически всегда выдает лог. "1" и только на короткое время выдает "0" (хотя в программе я сделал меандр). Так вот, в железе, схема ведет себя именно так. Теперь буду отлаживать в одной из этих новых студий.

Изменено пользователем James D.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Для публикации сообщений создайте учётную запись или авторизуйтесь

Вы должны быть пользователем, чтобы оставить комментарий

Создать учетную запись

Зарегистрируйте новую учётную запись в нашем сообществе. Это очень просто!

Регистрация нового пользователя

Войти

Уже есть аккаунт? Войти в систему.

Войти