Проблемы с "TIMER2_OVF". Atmega8 + Avr Studio 4 + assembler.

Обсуждаем контроллеры компании Atmel.
Ответить
Грызет канифоль
Сообщения: 299
Зарегистрирован: Пн май 16, 2011 10:54:32
Откуда: Красноярск

Сообщение Вадиматоричик »

Ситуация в 2-х словах: Есть устройство, которое выводит информацию на семи сегментный индикатор (на 4 разряда). Функция выдачи информации была в основном цикле, но из-за наличия дополнительных функций, индикация работала очень плохо (сегменты сменяли друг друга с различной скоростью или вовсе останавливались на сложных расчетах). Было решено перевести индикацию на прерывания. Путем несложных вычислений было рассчитано, что для нормального показа, все символы должны меняться 96 раз в секунду (24 кадра в секунду - оптимальная для глаза скорость всей картинки * 4 сегмента). Таймеры и прерывания были рассчитаны, путем настройки в автоматическом мастере проектов Code Vision, в последствие эти настройки были скопированы в Avr Studio 4. Цель была достигнута. На радостях сразу же проверил в Proteus 7. Там все работало нормально. Но вот незадача. В жизни все оказалось сложнее. МК никак не реагировал. Думал, что просто какие-то проблемы с соединением. Но нет. Все правильно. После решил просто поморгать светодиодом по этому таймеру (Предположил. что с такой частотой светодиод просто будет слабо гореть). Но бесполезно. МК проявил туже реакцию. Купил еще 1. Но и с ним эффект тоже. Использую Atmega8-16PU в связке с часовым кварцем. Шью Usbasp-ом.
Вот код настройки векторов.

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

;Настройка прерываний.------------------------------------------------------------------------------------------------------------------
.cseg                                                       ;Выбираем память програм.
.org    0                                                   ;Ставим на 0.       
;Перечисляем все возможные вектора прерываний, чтобы в случае сбоя, закрыть все ненужные.                 
rjmp    RESET                                               ;Внешний сброс, сброс при подаче питания, 
                                                            ;сброс при недопустимом снижении питания, 
                                                            ;сброс сторожевым таймером
rjmp    INT00                                               ;Запрос на внешнее прерывание 0.
rjmp    INT10                                               ;Запрос на внешнее прерывание 1.
rjmp    TIMER2_COMP                                         ;Срабатывание компаратора таймера-счетчика 2.
rjmp    TIMER2_OVF                                          ;Переполнение таймера-счетчика 2.
rjmp    TIMER1_CAPT                                         ;Захват фронта таймером-счетчиком 1.
rjmp    TIMER1_COMPA                                        ;Срабатывание компаратора А таймера счетчика 1.
rjmp    TIMER1_COMPB                                        ;Срабатывание компаратора В таймера-счетчика 1.
rjmp    TIMER1_OVF                                          ;Переполнение таймера-счетчика 1.
rjmp    TIMER0_OVF                                          ;Переполнение таймера-счетчика 0.
rjmp    SPI_STC                                             ;Завершение последовательной передачи интерфейсом SPI.
rjmp    USART_RXC                                           ;Завершение приема УСАПП.
rjmp    USART_UDRE                                          ;Регистр данных УСАПП свободен.
rjmp    USART_TXC                                           ;Завершение передачи УСАПП.
rjmp    ADC_ADC                                             ;Завершение преобразования АЦП.
rjmp    EE_RDY                                              ;Готовность EEPROM.
rjmp    ANA_COMP                                            ;Аналоговый компаратор.
rjmp    TWI                                                 ;Двухпроводный Последовательный интерфейс.
rjmp    SPM_RDY                                             ;Готовность записи Памяти программ.

;RESET, TIMER1_COMPA, TIMER2_OVF: - нужные прерывания. Остальные завершаем.
INT00:        
INT10:       
TIMER2_COMP:  
TIMER1_CAPT: 
TIMER1_OVF:   
TIMER0_OVF:   
TIMER1_COMPB: 
USART_RXC:   
USART_UDRE:  
USART_TXC:   
ADC_ADC:      
EE_RDY:      
ANA_COMP:                                            
TWI:      
SPI_STC:
SPM_RDY:              
reti
Настройка таймеров.

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

;Настройка 1-го таймера - раз в секунду и 2-го 96 раз в секунду.
        ldi      Temp,      0x0D
        out      TCCR1B,    Temp 
        ldi      Temp,      0x20
        out      OCR1AL,    Temp 
        ldi      Temp,      0x0A
        out      TCCR2,     Temp 
        ldi      Temp,      0x2a 
        out      OCR2,      Temp 
      
;Настройка прерываний по таймерам.
        ldi      Temp,      0x50                     
		out      TIMSK,     Temp 
Код прерывания по 2-му таймеру.

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

TIMER2_OVF:
in temp,  PIND
com temp
out PORTD, temp
           reti
Все можно сделать, было бы желание!
Реклама
vek
Вымогатель припоя
Аватара пользователя
Сообщения: 563
Зарегистрирован: Чт апр 16, 2009 04:53:41

Сообщение vek »

Че за фигня?

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

 ldi      Temp,      0x0D
 out      TCCR1B,    Temp 
Вообще не хочется читать такое,а тем-более разбирать,где у вас может быть ошибка в написании 16-ричного числа.

Делай что-то типа того:

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

ldi	tmp, (1<<ICNC1)|(1<<ICES1)|(1<<CS11) ;шумоподавитель ICP,ICP по фронту,делитель таймера 8
out		TCCR1B,	tmp
Как видим все абсолютно наглядно,а для особо одаренных впридачу очень подробно комментируем.
Именно так и только так

Для возникновения прерывания нужно 3 условия:
1 Встал нужный флаг в регистре флагов(автоматом ставится при соблюдении условий,в вашем случае - переполнение)
2 Разрешены прерывания локально (TMSK)
3 Разрешены глобально SEI
Чуете? Чего нехватает у вас?
В первый раз меня ударило током - и я подумал что ни черта не соображаю в электричестве. Во второй раз был аккуратнее и меня не ударило - теперь я возомнил из себя крутого микроэлектронщика.
Реклама
Грызет канифоль
Сообщения: 299
Зарегистрирован: Пн май 16, 2011 10:54:32
Откуда: Красноярск

Сообщение Вадиматоричик »

"Вообще не хочется читать такое,а тем-более разбирать,где у вас может быть ошибка в написании 16-ричного числа." - "Таймеры и прерывания были рассчитаны, путем настройки в автоматическом мастере проектов Code Vision". Прошу прощения. Общее разрешение тоже стоит.

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

;Разрешаем прерывания.        
    	sei    
С точки зрения написания кода - все верно. И Proteus это подтверждает. Не могу понять, почему в железе оно отказывается работать.
Все можно сделать, было бы желание!
vek
Вымогатель припоя
Аватара пользователя
Сообщения: 563
Зарегистрирован: Чт апр 16, 2009 04:53:41

Сообщение vek »

2-й таймер работает,а 1-й нет?Или оба прерывания несрабатывают?
Или в основном цикле зависает?Или еще чего?
Попробуй весь основной цикл закомментировать,оставь только прерывания.Что получится?
В первый раз меня ударило током - и я подумал что ни черта не соображаю в электричестве. Во второй раз был аккуратнее и меня не ударило - теперь я возомнил из себя крутого микроэлектронщика.
Реклама
Эиком - электронные компоненты и радиодетали
akl
Друг Кота
Сообщения: 4468
Зарегистрирован: Пт мар 07, 2008 06:54:43
Откуда: Ижевск

Сообщение akl »

Вадиматоричик Вы установили работу Т2 в режиме CTC по сравнению с 0x2A, но не разрешили это прерывание
TCCR2_M8.GIF
TIMSK_AND_16.GIF
Также, неправильно проведена инициализация OCR1A, не сброшены флаги и таймеры запущены до инициализации своих модулей.
Реклама
Грызет канифоль
Сообщения: 299
Зарегистрирован: Пн май 16, 2011 10:54:32
Откуда: Красноярск

Сообщение Вадиматоричик »

vek писал(а):2-й таймер работает,а 1-й нет?Или оба прерывания несрабатывают?
Или в основном цикле зависает?Или еще чего?
Попробуй весь основной цикл закомментировать,оставь только прерывания.Что получится?

Пробовал отключить основной цикл (Сделать его пустым), и отключить все в прерывании по 1-му таймеру. Бесполезно. 1-й таймер работает идеально. А вот 2-й - нет.
Все можно сделать, было бы желание!
Реклама
Грызет канифоль
Сообщения: 299
Зарегистрирован: Пн май 16, 2011 10:54:32
Откуда: Красноярск

Сообщение Вадиматоричик »

akl писал(а):Вадиматоричик Вы установили работу Т2 в режиме CTC по сравнению с 0x2A, но не разрешили это прерывание
TCCR2_M8.GIF
TIMSK_AND_16.GIF
Также, неправильно проведена инициализация OCR1A, не сброшены флаги и таймеры запущены до инициализации своих модулей.
Инициализацию таймеров проводил CV. Я просто скопировал в AVRStudio. Попробую поменять по вашй подсказке. Так как с таймерами я пока очень плохо - использую авто настройщик. Всю остальную периферию сам. В Proteus все четко по алгоритму.
Все можно сделать, было бы желание!
Грызет канифоль
Сообщения: 299
Зарегистрирован: Пн май 16, 2011 10:54:32
Откуда: Красноярск

Сообщение Вадиматоричик »

Подробно изучил датащит. Спасибо за подсказки. Вот что получилось.

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

	
;Настройка 1-го таймера - раз в секунду.------------------------------------------------------------------
ldi Temp, (1«CS12)|(1«WGM12) ;Делитель 256 - одна секунда будет 128. CTC.
out TCCR1B, Temp
ldi Temp, 0x80
out OCR1AL, Temp

;Настройка 2-го таймера.----------------------------------------------------------------------------------
;WGM21 - 1 (Сброс таймера по СТС).
;Частота 32768. Нам нужен сброс 96 раз в секунду.
;Ставим предделитель на 8.
;CS21 - 1 (Предделитель на 8).
ldi Temp, (1«WGM21)|(1«CS21)
out TCCR2, Temp

;32768/8/96=42. 42 (10) = 2А (16).
ldi Temp, 0x0A
out OCR2, Temp
;Настройка прерываний по таймерам.------------------------------------------------------------------------
;OCIE2 - прерывание 2-го таймера по совпадению с регистром OCR2.
;OCIE1A - прерывание 1-го таймера по совподению с A.
ldi Temp, (1«OCIE2)|(1«OCIE1A) ;
out TIMSK, Temp 

sei
Все можно сделать, было бы желание!
akl
Друг Кота
Сообщения: 4468
Зарегистрирован: Пт мар 07, 2008 06:54:43
Откуда: Ижевск

Сообщение akl »

Сделал бы так
Спойлер

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

.include "m8def.inc"
.def	Temp=r22

;Настройка 1-го таймера - раз в секунду.------------------------------------------------------------------
;ldi Temp, (1<CS12)|(1<WGM12) ;Делитель 256 - одна секунда будет 128. CTC.
;out TCCR1B, Temp
	CLR	R21
	OUT	OCR1AH,R21	;запись 16-разрядной периферии таймеров
					; должна проводиться в таком порядке
ldi Temp, 0x80
out OCR1AL, Temp

;Настройка 2-го таймера.----------------------------------------------------------------------------------
;WGM21 - 1 (Сброс таймера по СТС).
;Частота 32768. Нам нужен сброс 96 раз в секунду.
;Ставим предделитель на 8.
;CS21 - 1 (Предделитель на 8).
;ldi Temp, (1<WGM21)|(1<CS21)
;out TCCR2, Temp			; рано!!!!!!!!!!!!!!!

;32768/8/96=42. 42 (10) = 2А (16).
	LDI Temp,32768/8/96	; можно проще записать ldi Temp,42
;ldi Temp, 0x0A
	out OCR2, Temp	; или ldi Temp,32768/8/96
;Настройка прерываний по таймерам.------------------------------------------------------------------------
;OCIE2 - прерывание 2-го таймера по совпадению с регистром OCR2.
;OCIE1A - прерывание 1-го таймера по совподению с A.
ldi Temp, (1<OCIE2)|(1<OCIE1A) ;
out TIMSK, Temp

	SER	R23
	OUT	TIFR,R23

	LDI Temp, (1<CS12)|(1<WGM12) ;Делитель 256 - одна секунда будет 128. CTC.
	OUT	TCCR1B,Temp

	LDI Temp, (1<WGM21)|(1<CS21)
	OUT TCCR2, Temp		; вот теперь запускаем таймеры

sei
Грызет канифоль
Сообщения: 299
Зарегистрирован: Пн май 16, 2011 10:54:32
Откуда: Красноярск

Сообщение Вадиматоричик »

akl писал(а):Сделал бы так
Спойлер

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

.include "m8def.inc"
.def	Temp=r22

;Настройка 1-го таймера - раз в секунду.------------------------------------------------------------------
;ldi Temp, (1<CS12)|(1<WGM12) ;Делитель 256 - одна секунда будет 128. CTC.
;out TCCR1B, Temp
	CLR	R21
	OUT	OCR1AH,R21	;запись 16-разрядной периферии таймеров
					; должна проводиться в таком порядке
ldi Temp, 0x80
out OCR1AL, Temp

;Настройка 2-го таймера.----------------------------------------------------------------------------------
;WGM21 - 1 (Сброс таймера по СТС).
;Частота 32768. Нам нужен сброс 96 раз в секунду.
;Ставим предделитель на 8.
;CS21 - 1 (Предделитель на 8).
;ldi Temp, (1<WGM21)|(1<CS21)
;out TCCR2, Temp			; рано!!!!!!!!!!!!!!!

;32768/8/96=42. 42 (10) = 2А (16).
	LDI Temp,32768/8/96	; можно проще записать ldi Temp,42
;ldi Temp, 0x0A
	out OCR2, Temp	; или ldi Temp,32768/8/96
;Настройка прерываний по таймерам.------------------------------------------------------------------------
;OCIE2 - прерывание 2-го таймера по совпадению с регистром OCR2.
;OCIE1A - прерывание 1-го таймера по совподению с A.
ldi Temp, (1<OCIE2)|(1<OCIE1A) ;
out TIMSK, Temp

	SER	R23
	OUT	TIFR,R23

	LDI Temp, (1<CS12)|(1<WGM12) ;Делитель 256 - одна секунда будет 128. CTC.
	OUT	TCCR1B,Temp

	LDI Temp, (1<WGM21)|(1<CS21)
	OUT TCCR2, Temp		; вот теперь запускаем таймеры

sei
AKL, спасибо!
Все можно сделать, было бы желание!
vek
Вымогатель припоя
Аватара пользователя
Сообщения: 563
Зарегистрирован: Чт апр 16, 2009 04:53:41

Сообщение vek »

Кстати да. В регистры с буферизацией всегда записываешь сначала старший,потом младший.
В первый раз меня ударило током - и я подумал что ни черта не соображаю в электричестве. Во второй раз был аккуратнее и меня не ударило - теперь я возомнил из себя крутого микроэлектронщика.
Ответить

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