Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: ATmega 16 и прерывания
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > AVR
mishara777
Добрый день! Нужна помощь в поиске ошибки,скорее всего в голове. Программировал до этого 2313. Решил перейти на Мегу 16 и сразу грабли.Вот:
CODE

.device Atmega16
.nolist
.include "C:\Program Files\Atmel\AVR Tools\AvrAssembler2\Appnotes\m16def.inc"
.list
;====== Объявления ===========================================
.def temp =r16
;=======Начало программы========================================

jmp init ;RESET
jmp Impuls1 ;внешнее прерывание от INT0
jmp Impuls2 ;внешнее прерывание от INT1
reti
reti
reti
reti
reti
reti
jmp Display ;таймер/счётчик №0 переполнение
reti
reti
reti
reti
reti
reti
reti
reti
reti
reti
reti

;========= СТЕК =================================================
ldi temp,LOW(RAMEND)
out SPL,temp
ldi temp,HIGH(RAMEND)
out SPH,temp

;===========================================================================
Init:
ser temp ;все выхода PB1-PB7_индикаторы
out DDRB,temp
ldi temp,0b11100111 ; PD3@PD4 вход счета импульсов
out DDRD,temp ; PD0-PD2_номер индикатора

ldi temp,0b00000010 ;частота TCNT0 равна CK/8
out TCCR0,temp

ldi temp,0b00001100 ;частота TCNT1 равна CK/256
out TCCR1B,temp ;сбрасывать TC1 при совпадении
ldi temp,0b10110111
out OCR1AH,temp
ldi temp,0b00011011
out OCR1AL,temp

ldi temp,0b11000011
out GICR,temp
ldi temp,0b00001010 ;прерывание INT1 - низкий уровень
out MCUCR,temp


ldi temp,0b00001001 ;разреш.прерывания по переполнению TC0
out TIMSK,temp
sei
;=================================================
CHK:
ldi temp,0b00000001 ;устанавливаем 0 нулевого разряда
out PortD,temp
mov temp,r0
out PortB,temp
sei
;==========================================================
Start:
rjmp Start

Impuls1:
nop
reti

Impuls2:
nop
reti

Display:
nop
reti

При возникновении прерывания переходит на строчку " jmp init ;RESET". Шаманский бубен и ночные пляски у костра не помогли! Программа AVR Studio.
Сергей Борщ
QUOTE (mishara777 @ Apr 18 2011, 12:49) *
Шаманский бубен и ночные пляски у костра не помогли!
Ночью лучше спать. Ваша метка Init находится после кода инициализации указателя стека. Значит указатель стека показывает куда угодно, а не на RAMEND. И первый же reti посылает программу в произвольное место.
P.S. И в следующий раз при публикации кода используйте кнопку на форме ввода сообщения.
mishara777
Прошу прощения за оформление первого топа,сказывается нечастое обращение к форумам!Спасибо ,что быстро ответили ,но вначале (на 2313) я так и поступал.И в этот раз стек переносил из угла в угол,писал и rjmp и jmp - итог один "jmp init"
нечитатель
Цитата(mishara777 @ Apr 18 2011, 13:49) *
Решил перейти
, но сэкономил время на чтении 45 страницы.

Код
.org    INT0addr       ; это не магическая волшебная команда, а точное число. адрес.
        reti

.org    INT1addr       ; и это
        reti

.org ...


Экономить метки орги можно, но нельзя... когда не уверен.
Сергей Борщ
QUOTE (mishara777 @ Apr 18 2011, 13:23) *
И в этот раз стек переносил из угла в угол
Недопонял. Из какого угла? В какой угол?
Ваша программа после включения питания попадает на команду
CODE
jmp init;RESET
Выполнив ее попадает в строки
CODE
Init:
ser temp;все выхода PB1-PB7_индикаторы
А строки
CODE
ldi temp,LOW(RAMEND)
out SPL,temp
ldi temp,HIGH(RAMEND)
out SPH,temp
остаются неохваченными. Перенесите метку Init: в строку перед ldi temp,LOW(RAMEND). И таки да, для векторов очень желательно явно (.org) указывать адрес. Считать команды - велика вероятность ошибиться.
ae_
Плюс к тому, что установка стека не выполняется, ошибка в том, что в mega16 вектора прерываний занимают по 2 адреса, а в tiny2313 - один.
а неиспользуемые прерывания заглушены reti - один адрес, надо добавить до двух - nop, reti или reti, reti или так:
CODE

;...
.org 0
jmp init ;RESET

.org INT0addr
jmp Impuls1 ;внешнее прерывание от INT0

.org INT1addr
jmp Impuls2 ;внешнее прерывание от INT1

.org OVF0addr
jmp Display ;таймер/счётчик №0 переполнение

.org INT_VECTORS_SIZE
init:
;========= СТЕК =================================================
ldi temp,LOW(RAMEND)
out SPL,temp
ldi temp,HIGH(RAMEND)
out SPH,temp


да, уже подсказали...
mishara777
Если я правильно понял , то кусочек программы должен выглядеть так:
CODE
;=======Начало программы========================================
.org 0
jmp init;RESET

.org INT0addr
jmp Impuls1;внешнее прерывание от INT0

.org INT1addr
jmp Impuls2;внешнее прерывание от INT1

.org OVF0addr
jmp Display;таймер/счётчик №0 переполнение

.org INT_VECTORS_SIZE
;Store Program Memory Ready Handler


;===========================================================================
Init:

ser temp ;все выхода PB1-PB7_индикаторы
out DDRB,temp ;
ldi temp,0b11100111 ; PD3@PD4 вход счета импульсов
out DDRD,temp ; PD0-PD2_номер индикатора

ldi temp,0b00000010 ;частота TCNT0 равна CK/8
out TCCR0,temp

ldi temp,0b00001100 ;частота TCNT1 равна CK/256
out TCCR1B,temp ;сбрасывать TC1 при совпадении
ldi temp,0b10110111
out OCR1AH,temp
ldi temp,0b00011011
out OCR1AL,temp

ldi temp,0b11000011
out GICR,temp
ldi temp,0b11111010 ;прерывание INT1 - низкий уровень
out MCUCR,temp


ldi temp,0b00001001 ;разреш.прерывания по переполнению TC0
out TIMSK,temp

ldi DisplayCounter,25
clr ZH

ldi temp,LOW(RAMEND)
out SPL,temp
ldi temp,HIGH(RAMEND)
out SPH,temp
sei
;=================================================
CHK:
ldi temp,0b00000001 ;устанавливаем 0 нулевого разряда
out PortD,temp
mov temp,r0
out PortB,temp
sei
;==========================================================

Честно сказать датащит до дыр стер и 45 страницу тоже,но с аглицким проблема (учили французскому),поэтому и недопонимание прочитанного.Хочется ведь не останавливаться на2313!
ILYAUL
Код
Init:
cli
  ldi  temp,LOW(RAMEND)
  out  SPL,temp
  ldi  temp,HIGH(RAMEND)
  out  SPH,temp
отключить компаратор
далее по тесту
mishara777
Спасибо за терпение! Сделал все ,как написали. Но.... опять "jmp init ;RESET"
Палыч
Цитата(mishara777 @ Apr 18 2011, 15:12) *
Код
.........
  ldi  temp,0b11000011
  out  GICR,temp
Вот тут я, наверное, недопонял... Вы, наверное, не в области BootLoader'a свою программу располагаете? Зачем вектора "двигаете"?
Цитата
IVSEL: Interrupt Vector Select
When the IVSEL bit is cleared (zero), the Interrupt Vectors are placed at the start of the
Flash memory...
IVCE: Interrupt Vector Change Enable

Т.е. IVSEL должен быть нулем (он и так нулевой по сбросу), и IVCE то же (раз IVSEL менять нам не нужно)

Цитата(mishara777 @ Apr 18 2011, 15:12) *
Код
  ldi  temp,0b00001001;разреш.прерывания по переполнению TC0
  out  TIMSK,temp
Здесь разрешаются два(!) прерывания. Обработчика одного из них - нет!
mishara777
Уважаемый ,Палыч! Это
Цитата
Обработчика одного из них - нет
просто часть программы, которую написал с год назад для 2313. Хотел добавить некоторые возможности ,не хватило пинов. Вот и пытаюсь перейти на Мегу16.
Вот это
Цитата
IVSEL: Interrupt Vector Select
When the IVSEL bit is cleared (zero), the Interrupt Vectors are placed at the start of the
Flash memory...
IVCE: Interrupt Vector Change Enable

раз десять читал,понять не смог.Поэтому менял наугад и пробовал "завести " проц.
Палыч
Цитата(mishara777 @ Apr 18 2011, 17:43) *
Это просто часть программы, которую написал с год назад для 2313.
Если прерывания разрешить, а обработчик его не сделать, то результат работы - непредсказуем... От этого следует немедленно избавиться.


Цитата(mishara777 @ Apr 18 2011, 17:43) *
раз десять читал,понять не смог.Поэтому менял наугад и пробовал "завести " проц.
Эти биты для поддержки прерываний в BootLoader'e. В Application их менять не нужно.
mishara777
Спасибо за совет. Сейчас буду исправлять
alag57
Цитата
с аглицким проблема (учили французскому)

Евстифеев А. В. - Микроконтроллеры AVR семейств Tiny и Mega фирмы Atmel
скормить гуглю
все на русском, а так как у вас
Цитата
раз десять читал,понять не смог.Поэтому менял наугад и пробовал "завести " проц

это не дело, надо понимать, что делаешь.
ILYAUL
И пишите вместо 0b01010111 (для примера и от балды)
приблизительно так
Код
;**************************************************
;*;;/Initialization ExtInterrupr;;*              *
;**************************************************
        ldi        temp,1<<INTF2
        out        EIFR,temp
        ldi        temp,1<<INT2; Разрешаем прерывание INT2
        out        EIMSK,temp
        ldi        temp,1<<ISC21|0<<ISC20
        sts        EICRA,temp;+ По спадающему фронту

Так понятнее , чем каждый регистр проверять , что Вы там назначили.
mishara777
Уважаемые форумчане! Спасибо за оперативную помощь! Все получилось! Книгу Евстифеева обязательно найду (просто не знал,что искать).Еще раз СПАСИБО!
pavel-pervomaysk
Используй симулятор, сметриш на счетчик стэка, если он переполняется и после вызова прерывания или подпрограммы не вернулся на свое место, ищим баг.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.