Страница 1 из 1
Atmega8 Timer0+Timer1 одновременно не пашут.. :(
Добавлено: Вт мар 09, 2010 22:32:00
Cassegrain
Дано:
Тестер для кабелей. Логика на базе Атмега8.
16-битный Таймер1 работает с предделителем 1/1024 и считает 10 секунд - время испытаний кабеля.
Есть светодиод статуса - горит, значит "Готов к тесту", моргает когда тест производится, то есть в течение 10 секунд, отсчитываемых Таймером0.
Идея такова:при начале теста запускаю 16-битный таймер с предделителем 1/1024 и тут же запускаю 8-битный Таймер0 с предделителем 1/1024 и на переполнениях последнего инвертирую состояние порта, куда включен светодиод статуса - так он моргает.
На словах всё красиво, на деле не пашет. Таймер1 отсчитывает задержку, всё как положено, а Таймер0 не работает. Выдернул код, которым запускал Таймер0, вкатил в чистый проект, скомпилировал и прошлил в Мегу - всё пашет. Как совмещаю два таймера в кучу - не пашет. Где я туплю? Помогите, други!
Re: Atmega8 Timer0+Timer1 одновременно не пашут.. :(
Добавлено: Ср мар 10, 2010 02:16:01
smac
Cassegrain писал(а):Дано:
Где я туплю? Помогите, други!
Вы действительно тупите! Код-то где? Могу Вас заверить, что таймеры работают вместе без каких-либо проблем, ошибка точно в Вашем коде.
Добавлено: Ср мар 10, 2010 10:50:44
MTF
smac прав оба таймера должны работать без проблем !!!
надо смотреть код 100% ошибка там
sreg в прерывании сохраняете , если используете r16 в прерывании надо тоже сохранять , в обшем код надо смотреть

Добавлено: Ср мар 10, 2010 11:32:32
Smirnov
наверника в начале разрешил прерывание для таймера 0
timsk=0x01; //например, точно биты не знаю
а потом разрешил прерывание для таймера 1
timsk=0x80; //например, точно биты не знаю
в итоге слетела инициализация для таймера 0
пожалуйста проверь все строки с инициализацией

Добавлено: Ср мар 10, 2010 11:58:48
Cassegrain
Smirnov писал(а):наверника в начале разрешил прерывание для таймера 0
timsk=0x01; //например, точно биты не знаю
а потом разрешил прерывание для таймера 1
timsk=0x80; //например, точно биты не знаю
в итоге слетела инициализация для таймера 0
пожалуйста проверь все строки с инициализацией

Первые два бита TIMSК разрешают прерывание по таймерам О и 1 соответственно.
1)Устанавливаю первые два бита ТИМСК
2)Гружу начальные значения в счётные регистры таймеров
3)Запускаю 16-битный Таймер1, предделитель 1/1024
4)Запускаю 8-битный Таймер0,предделитель 1/1024
Щас, я напишу код снова и скину сюда.
Добавлено: Ср мар 10, 2010 14:10:45
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
Добавлено: Ср мар 10, 2010 14:24:16
Engineer_Keen
Что-то меня смущают строчки "LDI rX,portX"...
Это вроде получается загрузить в rX константу=адресу порта, а не значение самого порта
Разве надо не "IN rX,portX" ?
А второй таймер в AVR Studio вообще не работает, сам недавно мучался, пока тут не сказали

Добавлено: Ср мар 10, 2010 14:24:30
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
для чего этот код? если для начальной установки таймер, то она будет выполнена только однажды.
Добавлено: Ср мар 10, 2010 14:41:19
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. Это из другого кода выдрано, там надо было так, я так и поместил как было - мне не важна сейчас точность задержки, важно отладить работу таймеров вообще.
Добавлено: Ср мар 10, 2010 14:48:37
Engineer_Keen
Если хотите считывать/записывать в порт (как и любую другую периферию), то команды - IN и OUT, а LDI - это загрузка в регистр КОНСТАНТЫ. Читайте HELP по ассемблеру внимательнее.
Добавлено: Ср мар 10, 2010 15:00:18
Pooher
LDI - Load immediate (на память)
IN - Load I/O Location
Понятно объясняю?
Portb - константа из .inc файла, посмотрите её значение, и удивитесь: О! Чудо! гдето я её видел, не в значении ли порта?
ЗЫ: АСМ очень коварный, не любит невнимательности.
Добавлено: Ср мар 10, 2010 15:31:25
Cassegrain
Pooher писал(а):LDI - Load immediate (на память)
IN - Load I/O Location
Понятно объясняю?
Portb - константа из .inc файла, посмотрите её значение, и удивитесь: О! Чудо! гдето я её видел, не в значении ли порта?
ЗЫ: АСМ очень коварный, не любит невнимательности.
Спасибо! Всё заработало!
Стало быть LDI позволяет работать с регистрами, кроме тех, что касаются непосредственно ввода-вывода, т.е PortA-D.
Вот внмательности мне на раздаче в роддоме немного не хватило, так что приходится частенько лбом биться.
Добавлено: Ср мар 10, 2010 15:36:12
Cassegrain
Engineer_Keen писал(а):Что-то меня смущают строчки "LDI rX,portX"...
Это вроде получается загрузить в rX константу=адресу порта, а не значение самого порта
Разве надо не "IN rX,portX" ?
А второй таймер в AVR Studio вообще не работает, сам недавно мучался, пока тут не сказали

Прекрасно работают оба таймера. Я думаю не вопрос и третий Таймер2 подключить.
Просто для того чтобы посмотреть как они работают в АВР Студио надо сначала запустить их без предделителя и включив программу исполняться обратить внимание на счётные регистры TCNT(номер таймера). Если значения меняются, то счётчики пашут. У меня было такое, что не пахал счётчик, но я смотрел в него долго и потом он наконец тикнул. Тогда я посмотрел на счётчик циклов процессора и стало ясно, что он не тикал сразу из за установленного мною же предделителя на 1024. То есть пока 1024 цикла не прошло,он не тикал, а я думал, что он не работает, перепроверял процесс инициализации несколько раз, злился даже, пока наконец не допетрило. О как!

Добавлено: Ср мар 10, 2010 15:42:21
Engineer_Keen
У меня на предделители были по единице, при этом таймер0 тикал, а таймер1 нет. В протеусе все работало, и в железе потом заработало. Возможно авр студия эмулирует все таймеры, но не на всех контроллерах
Кстати LDI работает не со всеми регистрами, а только с р16-р31
