Atmega8 Timer0+Timer1 одновременно не пашут.. :(

Вопросы настройки, программирования, прошивки микроконтроллеров и микросхем программируемой логики
Закрыто
Cassegrain
Первый раз сказал Мяу!
Сообщения: 32
Зарегистрирован: Ср мар 03, 2010 16:35:42
Откуда: Tallinn

Atmega8 Timer0+Timer1 одновременно не пашут.. :(

Сообщение Cassegrain »

Дано:
Тестер для кабелей. Логика на базе Атмега8.
16-битный Таймер1 работает с предделителем 1/1024 и считает 10 секунд - время испытаний кабеля.
Есть светодиод статуса - горит, значит "Готов к тесту", моргает когда тест производится, то есть в течение 10 секунд, отсчитываемых Таймером0.
Идея такова:при начале теста запускаю 16-битный таймер с предделителем 1/1024 и тут же запускаю 8-битный Таймер0 с предделителем 1/1024 и на переполнениях последнего инвертирую состояние порта, куда включен светодиод статуса - так он моргает.
На словах всё красиво, на деле не пашет. Таймер1 отсчитывает задержку, всё как положено, а Таймер0 не работает. Выдернул код, которым запускал Таймер0, вкатил в чистый проект, скомпилировал и прошлил в Мегу - всё пашет. Как совмещаю два таймера в кучу - не пашет. Где я туплю? Помогите, други!
Реклама
smac
Мучитель микросхем
Сообщения: 459
Зарегистрирован: Вс июн 01, 2008 12:16:38

Re: Atmega8 Timer0+Timer1 одновременно не пашут.. :(

Сообщение smac »

Cassegrain писал(а):Дано:
Где я туплю? Помогите, други!
Вы действительно тупите! Код-то где? Могу Вас заверить, что таймеры работают вместе без каких-либо проблем, ошибка точно в Вашем коде.
Реклама
Аватара пользователя
MTF
Нашел транзистор. Понюхал.
Сообщения: 179
Зарегистрирован: Чт янв 07, 2010 11:25:12
Откуда: Москва

Сообщение MTF »

smac прав оба таймера должны работать без проблем !!!

надо смотреть код 100% ошибка там

sreg в прерывании сохраняете , если используете r16 в прерывании надо тоже сохранять , в обшем код надо смотреть :shock:
Smirnov
Прорезались зубы
Сообщения: 206
Зарегистрирован: Сб фев 27, 2010 11:58:50
Откуда: Горец: Уральские горы

Сообщение Smirnov »

наверника в начале разрешил прерывание для таймера 0
timsk=0x01; //например, точно биты не знаю
а потом разрешил прерывание для таймера 1
timsk=0x80; //например, точно биты не знаю
в итоге слетела инициализация для таймера 0
:))
пожалуйста проверь все строки с инициализацией :)
Реклама
Эиком - электронные компоненты и радиодетали
Cassegrain
Первый раз сказал Мяу!
Сообщения: 32
Зарегистрирован: Ср мар 03, 2010 16:35:42
Откуда: Tallinn

Сообщение Cassegrain »

Smirnov писал(а):наверника в начале разрешил прерывание для таймера 0
timsk=0x01; //например, точно биты не знаю
а потом разрешил прерывание для таймера 1
timsk=0x80; //например, точно биты не знаю
в итоге слетела инициализация для таймера 0
:))
пожалуйста проверь все строки с инициализацией :)
Первые два бита TIMSК разрешают прерывание по таймерам О и 1 соответственно.
1)Устанавливаю первые два бита ТИМСК
2)Гружу начальные значения в счётные регистры таймеров
3)Запускаю 16-битный Таймер1, предделитель 1/1024
4)Запускаю 8-битный Таймер0,предделитель 1/1024

Щас, я напишу код снова и скину сюда.
Реклама
Cassegrain
Первый раз сказал Мяу!
Сообщения: 32
Зарегистрирован: Ср мар 03, 2010 16:35:42
Откуда: Tallinn

Сообщение Cassegrain »

Cassegrain писал(а):
Smirnov писал(а): Щас, я напишу код снова и скину сюда.
Идея: на портах В и С записаны числа 10101010, на нулевой ножке каждого порта светодиод. Порт В подключен к обработчику прерываний Таймера0, порт С - к обработчику прерываний Таймера1.
Обработчики одинаковые - сдвиг вправо даёт то горящий, то погасший светодиод. Теоретически. Практически не пашет почему-то. АВР Студио симулирует работу, при срабатывании обработчика Таймера0 вместо того чтоб сместить 10101010 направо и дать мне 01010101, я получаю на выходе 00001100 и в дальнейшем по прерыванию от Таймера0 ничего с портом В не происходит.

Код:

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

.include "m8def.inc"


.MACRO outi		
		LDI 	R16,@1 	; This macro copies specific integer to R16
		OUT 	@0,R16 	; and copies R16 content to specific register
.ENDMACRO

.CSEG
			.ORG 	0x0000			; CPU starts from 0x0000, but there are
			RJMP 	Reset			; interrupt vectors, so we jump to
									; beginning of our program - Reset marker

			
;INTERRUPT VECTORS
			;definitions are copied from m8def.inc and therefore corresponding
			; .EQU changed to .ORG and RETI added if no action is needed for 
			;specific interrupt

.ORG	INT0addr		; External Interrupt Request 0
RETI
.ORG	INT1addr		; External Interrupt Request 1
RETI
.ORG	OC2addr			; Timer/Counter2 Compare Match
RETI
.ORG	OVF2addr		; Timer/Counter2 Overflow
RETI
.ORG	ICP1addr		; Timer/Counter1 Capture Event
RETI
.ORG	OC1Aaddr		; Timer/Counter1 Compare Match A
RETI
.ORG	OC1Baddr		; Timer/Counter1 Compare Match B
RETI
.ORG	OVF1addr		; Timer/Counter1 Overflow
RJMP Timer1OV 			;Move to Timer1OV marker code

.ORG	OVF0addr		; Timer/Counter0 Overflow
RJMP Timer0OV
.ORG	SPIaddr			; Serial Transfer Complete
RETI
.ORG	URXCaddr		; USART, Rx Complete
RETI
.ORG	UDREaddr		; USART Data Register Empty
RETI
.ORG	UTXCaddr		; USART, Tx Complete
RETI
.ORG	ADCCaddr		; ADC Conversion Complete
RETI
.ORG	ERDYaddr		; EEPROM Ready
RETI
.ORG	ACIaddr			; Analog Comparator
RETI
.ORG	TWIaddr			; 2-wire Serial Interface
RETI
.ORG	SPMRaddr		; Store Program Memory Ready
RETI
			
			.ORG	INT_VECTORS_SIZE		; END OF INTERRUPT VECTORS TABLE

			;The Program begins here

Reset:		OUTI 	SPL,low(RAMEND) 		; Initialize Stack
			OUTI	SPH,High(RAMEND)					
											
OUTI DDRB,255 ;port B initialization
OUTI DDRC,255 ;port C initialization
OUTI PORTB,0b10101010
OUTI PORTC,0b10101010
		


	LDI	R16,(1<<TOIE0)+(1<<TOIE1) ;Timer1,Timer0 Overflow Interrupt Enable set bit and load to R16
	OUT	TIMSK, R16	 ;Load R16 to TIMSK register
	
	;global interrupts disabled before 16-bit operations

	LDI	R16, High(65535-100)	 ; Here loading initial state of count registers
	OUT	TCNT1H, R16				; High byte
	LDI	R16, Low(65535-100) 	;
	OUT	TCNT1L, R16		        ; And low byte
	SEI				; Global Interrupt enable
 
	LDI	R16,1			; Start Timer1 (without prescaler - 0000 0001 (1Dec)
	OUT	TCCR1B,R16		; or with 1024 prescaler - 0000 0101 (5Dec))
	OUT TCCR0,R16		; Start Timer0 

Main:
	NOP					;Wait for counter overflow, no operation
	RJMP Main


Timer1OV: 	
		
			LDI R17,PORTB ;shift PORTB right - toggle LED
			ROR R17
			OUT PORTB,R17
	        RETI ;return 

Timer0OV:
			LDI R18,PORTC ;shift PORTC right - toggle LED
			ROR R18
			OUT PORTC,R18
			RETI ;return


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

Сообщение Engineer_Keen »

Что-то меня смущают строчки "LDI rX,portX"...

Это вроде получается загрузить в rX константу=адресу порта, а не значение самого порта :idea:

Разве надо не "IN rX,portX" ?

А второй таймер в AVR Studio вообще не работает, сам недавно мучался, пока тут не сказали :(
Последний раз редактировалось Engineer_Keen Ср мар 10, 2010 14:26:48, всего редактировалось 1 раз.
Аватара пользователя
GP1
Поставщик валерьянки для Кота
Сообщения: 2401
Зарегистрирован: Пт май 23, 2008 19:32:22
Откуда: Россия, Волгоград
Контактная информация:

Сообщение GP1 »

На первый взгляд, то что бросилось в глаза:
1.

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

        LDI R17,PORTB ;shift PORTB right - toggle LED
в R17 получишь адрес порта $18, а никак не его значение, и соответственно после команды ROR получишь свои 0b00001100.
2.

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

   LDI   R16, High(65535-100)    ; Here loading initial state of count registers 
   OUT   TCNT1H, R16            ; High byte 
   LDI   R16, Low(65535-100)    ; 
   OUT   TCNT1L, R16              ; And low byte 
для чего этот код? если для начальной установки таймер, то она будет выполнена только однажды.
Чем дальше, тем больше становлюсь занудой...
Изображение
Cassegrain
Первый раз сказал Мяу!
Сообщения: 32
Зарегистрирован: Ср мар 03, 2010 16:35:42
Откуда: Tallinn

Сообщение Cassegrain »

GP1 писал(а):На первый взгляд, то что бросилось в глаза:
1.

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

        LDI R17,PORTB ;shift PORTB right - toggle LED
в R17 получишь адрес порта $18, а никак не его значение, и соответственно после команды ROR получишь свои 0b00001100.
2.

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

   LDI   R16, High(65535-100)    ; Here loading initial state of count registers 
   OUT   TCNT1H, R16            ; High byte 
   LDI   R16, Low(65535-100)    ; 
   OUT   TCNT1L, R16              ; And low byte 
для чего этот код? если для начальной установки таймер, то она будет выполнена только однажды.
1. IN вместо LDI?

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

Сообщение Engineer_Keen »

Если хотите считывать/записывать в порт (как и любую другую периферию), то команды - IN и OUT, а LDI - это загрузка в регистр КОНСТАНТЫ. Читайте HELP по ассемблеру внимательнее.
Аватара пользователя
Pooher
Мучитель микросхем
Сообщения: 491
Зарегистрирован: Вс янв 07, 2007 01:45:48
Откуда: Российская Федерация, будь она неладна...

Сообщение Pooher »

LDI - Load immediate (на память)
IN - Load I/O Location

Понятно объясняю? :)))

Portb - константа из .inc файла, посмотрите её значение, и удивитесь: О! Чудо! гдето я её видел, не в значении ли порта? :)))

ЗЫ: АСМ очень коварный, не любит невнимательности.
Научить нельзя, можно научиться. Пифагор.
Вставь недостающие буквы в слово *у*ня. Если у тебя получилось слово кухня, значит ты интеллигентный человек.
Cassegrain
Первый раз сказал Мяу!
Сообщения: 32
Зарегистрирован: Ср мар 03, 2010 16:35:42
Откуда: Tallinn

Сообщение Cassegrain »

Pooher писал(а):LDI - Load immediate (на память)
IN - Load I/O Location

Понятно объясняю? :)))

Portb - константа из .inc файла, посмотрите её значение, и удивитесь: О! Чудо! гдето я её видел, не в значении ли порта? :)))

ЗЫ: АСМ очень коварный, не любит невнимательности.
Спасибо! Всё заработало!
Стало быть LDI позволяет работать с регистрами, кроме тех, что касаются непосредственно ввода-вывода, т.е PortA-D.

Вот внмательности мне на раздаче в роддоме немного не хватило, так что приходится частенько лбом биться.
Cassegrain
Первый раз сказал Мяу!
Сообщения: 32
Зарегистрирован: Ср мар 03, 2010 16:35:42
Откуда: Tallinn

Сообщение Cassegrain »

Engineer_Keen писал(а):Что-то меня смущают строчки "LDI rX,portX"...

Это вроде получается загрузить в rX константу=адресу порта, а не значение самого порта :idea:

Разве надо не "IN rX,portX" ?

А второй таймер в AVR Studio вообще не работает, сам недавно мучался, пока тут не сказали :(
Прекрасно работают оба таймера. Я думаю не вопрос и третий Таймер2 подключить.
Просто для того чтобы посмотреть как они работают в АВР Студио надо сначала запустить их без предделителя и включив программу исполняться обратить внимание на счётные регистры TCNT(номер таймера). Если значения меняются, то счётчики пашут. У меня было такое, что не пахал счётчик, но я смотрел в него долго и потом он наконец тикнул. Тогда я посмотрел на счётчик циклов процессора и стало ясно, что он не тикал сразу из за установленного мною же предделителя на 1024. То есть пока 1024 цикла не прошло,он не тикал, а я думал, что он не работает, перепроверял процесс инициализации несколько раз, злился даже, пока наконец не допетрило. О как! :))
Аватара пользователя
Engineer_Keen
Друг Кота
Сообщения: 3872
Зарегистрирован: Пт янв 29, 2010 10:27:40
Откуда: Москва

Сообщение Engineer_Keen »

У меня на предделители были по единице, при этом таймер0 тикал, а таймер1 нет. В протеусе все работало, и в железе потом заработало. Возможно авр студия эмулирует все таймеры, но не на всех контроллерах :)))

Кстати LDI работает не со всеми регистрами, а только с р16-р31 :P
Закрыто

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