Таймер ATMega8

Вопросы настройки, программирования, прошивки микроконтроллеров и микросхем программируемой логики
Закрыто
Аватара пользователя
Bigcrash
Открыл глаза
Сообщения: 61
Зарегистрирован: Вс фев 12, 2012 09:32:37

Таймер ATMega8

Сообщение Bigcrash »

Помогите разобраться.
Хочу организовать небольшую задержку перед работой основной программы. Решил использовать таймер, настроенный по переполнению. Вот код

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

.include "m8def.inc"
.cseg
.org 0

.EQU	AD=0
.EQU	exINT1=3				//int1 
.EQU	AIN1=7
.EQU	AIN0=6


rjmp start

;====== обработка прерывания ТС1 по переполнению ========
TIM1_OVF:
	cli
	rjmp main
reti

;======= MACRO =======
	.macro outi
		ldi R16,@1
		out	@0,R16
	.endm

start:


;======= Разрешение прерывания INT1 ====
	outi 	MCUCR,0b00000100	//по любому изменению сигнала
	outi 	GICR,0b10000000		//разрешает внешнее прерывание с int1

;======= Инициализация стека======
    outi 	SPH,high(RamEnd) 
    outi 	SPL,low(RamEnd)  

;======= Настойка аналогового компаратора =============
	outi ACSR,(0<<ACD)|(1<<ACBG)|(0<<ACIE)|(0<<ACIS1)|(0<<ACIS0)
	//		включить/	опора/	прерывание/	по любому изм. сигнала

;====== Настройка таймера ТС1 ========
	outi SFIOR, (1<<PSR10)
	outi TCCR1B, (0<<CS12)|(1<<CS11)|(0<<CS10)
					;частота/8
	outi TIMSK, (1<<TOIE1)		// прерывание по переполнению ТС1
	outi TCNT1H,0
	outi TCNT1L,0

;======= Порты ==========
	cbi DDRD,exINT1		//порт Д на вход для ИНТ1
	sbi	PORTD,exINT1	//подтяжка инта
	outi DDRD,0	;вход ног компаратора
	outi PORTD,0

	outi DDRB,255
	outi PORTB,0
	sei

loop:					//цикл для переполнения таймера
rjmp loop

main:                              //основная программа (моргает диодами)
	sbis ACSR,ACO
	rjmp danger
	rjmp work
rjmp main

work:
	sbi PORTB,0
	sbi PORTB,1
	cbi PORTB,2
rjmp main

danger:
	cbi PORTB,0
	cbi PORTB,1
	sbi PORTB,2
rjmp main
Дак вот, в АВР Студии когда происходит переполнение он нихрена не уходит в обработчик прерывания, а кидается на строчку

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

    outi 	SPL,low(RamEnd)  
В шпротеусе соответственно тоже ничего не работает.

Решил сделать по вумному. Заменил имя обработчика с
ТIM1_OVF на .ORG $010

В студии отлично, стал переходить на обработчик (ШОЗАФИГНЯ АААА), но в шпротеусе стал вылетать Invalid OPCODE на PC=0x0006

Уже моск весь вскипел, помогите люди умные.
Реклама
Аватара пользователя
Engineer_Keen
Друг Кота
Сообщения: 3872
Зарегистрирован: Пт янв 29, 2010 10:27:40
Откуда: Москва

Re: Таймер ATMega8

Сообщение Engineer_Keen »

У каждого источника прерывания задан свой строго определенный адрес. Все эти адреса идут с 0-го адреса и по адрес=количеству этих самых прерываний. И при возникновении прерывания программа перейдет не на метку, "имя которой возможно как-то напоминает имя вектора прерывания", а на этот самый адрес. Поэтому программа перескакивала не на метку TIM1_OVF - которая на самом деле была по адресу прерывания INT0, а на outi SPL,low(RamEnd), которая как-раз идет по адресу 0х0008. А из-за того, что стоит директива ORG, адреса вообще сбились и вместо начала опкода читается какой-то его кусок.

Внимательно читаем даташит, раздел Interrupts.

Кстати сама процедура

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

TIM1_OVF:
   cli
   rjmp main
reti
Вообще один сплошной ЛОЛ. Во-первых, после возникновения прерывания, бит I регистра SREG сбрасывается, следовательно cli смысла не имеет. Во-вторых, rjmp main в случае возникновения (теоретически, см. далее) в количестве раз более чем размер ОЗУ/размер адреса - сорвет стек, т.к. вызов прерывания аналогичен команде CALL, т.е. задвигает текущий адрес в стек, чтобы было куда вернуться после прерывания. А раз всегда выполняется rjmp, адреса из стека обратно не возвращаются. В-третьих, команды после безусловного перехода никогда не выполнятся, если в программе нет перехода на них. В данном случае reti - не выполнится никогда, что также означает, что флаг I никогда не будет восстановлен и прерывания всегда будут выключены. Хотя это можно свалить на набросок кода для изменения его в будущем, когда правильно заработает прерывание...
Реклама
Аватара пользователя
Bigcrash
Открыл глаза
Сообщения: 61
Зарегистрирован: Вс фев 12, 2012 09:32:37

Re: Таймер ATMega8

Сообщение Bigcrash »

Ну чесно говоря, я имя прерывания взял с ДШ
Изображение
В одной из предыдущих програм точно также использовал внешнее прерывание инт1. Задал его имя и писал обработчик, все работало.

А насчет той процедуры это да, но она меня пока мало интересовала. Лишь бы прерывания заработали, но пока не получается. Адрес поправил там c $010 на $008
Аватара пользователя
Bigcrash
Открыл глаза
Сообщения: 61
Зарегистрирован: Вс фев 12, 2012 09:32:37

Re: Таймер ATMega8

Сообщение Bigcrash »

А не подскажите, по какому алгоритму вначале организовать переполнение таймера, а потом, после выхода из обработчика прерывания, попасть в главную программу. Может быть вообще не стоит трогать прерывания, а просто проверять постоянно 2 бит регистра TIFR. Я вначале так пробовал, но почему то команда SBIS с ним работать открывазывается. Пишет какой то бред по out of range...
Последний раз редактировалось Bigcrash Пт апр 13, 2012 14:16:15, всего редактировалось 1 раз.
Реклама
Эиком - электронные компоненты и радиодетали
Аватара пользователя
Engineer_Keen
Друг Кота
Сообщения: 3872
Зарегистрирован: Пт янв 29, 2010 10:27:40
Откуда: Москва

Re: Таймер ATMega8

Сообщение Engineer_Keen »

Bigcrash писал(а):В одной из предыдущих програм точно также использовал внешнее прерывание инт1. Задал его имя и писал обработчик, все работало.
Вам повезло, и метка с которой начиналась программа обработчика прерывания совпала с ее реальным адресом.
Bigcrash писал(а):Адрес поправил там c $010 на $008
И какой результат?
Реклама
Аватара пользователя
Bigcrash
Открыл глаза
Сообщения: 61
Зарегистрирован: Вс фев 12, 2012 09:32:37

Re: Таймер ATMega8

Сообщение Bigcrash »

Engineer_Keen писал(а): И какой результат?
Ну я в начале запихнул всю таблицу векторов прерываний, а потом из нее ссылался на обработчик, вроде опкод не вылаетает, и студия правильно ссылается. Подскажите, почему не получается с TIFR
Реклама
Аватара пользователя
Engineer_Keen
Друг Кота
Сообщения: 3872
Зарегистрирован: Пт янв 29, 2010 10:27:40
Откуда: Москва

Re: Таймер ATMega8

Сообщение Engineer_Keen »

Bigcrash писал(а):А не подскажите, по какому алгоритму вначале организовать переполнение таймера, а потом, после выхода из обработчика прерывания, попасть в главную программу.
Что значит "организовать переполнение таймера"? Оно или само организуется если таймер запущен и его не сбрасывать, или можно бит в управляющем регистре вручную взвести.
В обычной программе, после выполнения прерывания попасть можно только в то место, перед которым случилось это самое прерывание, в этом состоит весь смысл прерывания.
Bigcrash писал(а):Может быть вообще не стоит трогать прерывания, а просто проверять постоянно 2 бит регистра TIFR.
Мысль верная. Просто команды SBIS/SBIC не работают с адресами В/В выше 0x3F, а адрес TIFR - 0x58, поэтому out of range не бред. Неужели не интересно в студии нажать F1 на SBIC и почитать как и с чем оно работает?

Как в случае с макросом OUTI (в теме про АЦП), нужно использовать команды LDS/STS. Примерно так:

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

LDS R16,TIFR
SBRS R16,TOV1
Последний раз редактировалось Engineer_Keen Пт апр 13, 2012 14:28:20, всего редактировалось 1 раз.
Аватара пользователя
Bigcrash
Открыл глаза
Сообщения: 61
Зарегистрирован: Вс фев 12, 2012 09:32:37

Re: Таймер ATMega8

Сообщение Bigcrash »

Это да, я уже понял что это гиблый для этой задачи варинат.
поэтому хотел сделать так проверку переполнения

sbis TIFR,2

но студия начинает писать Operand l out of range: 0x38
Аватара пользователя
Bigcrash
Открыл глаза
Сообщения: 61
Зарегистрирован: Вс фев 12, 2012 09:32:37

Re: Таймер ATMega8

Сообщение Bigcrash »

Все, получилось. Благодарю за помощь.
Закрыто

Вернуться в «Микроконтроллеры и ПЛИС»