Внешние прерывания не работают Atmega8

Обсуждаем контроллеры компании Atmel.
Ответить
pimple2006
Первый раз сказал Мяу!
Сообщения: 20
Зарегистрирован: Ср фев 08, 2012 22:58:32
Откуда: Лебедянь

Внешние прерывания не работают Atmega8

Сообщение pimple2006 »

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

.include "C:\avrassembler\include\m8def.inc"

.def Temp=R16
.def Temp1=R17
.def Temp2=R18
.def Temp3=R19
.def start=R20


.cseg
.org 0

rjmp RESET ; Reset Handler
rjmp EXT_INT0 ; IRQ0 Handler
rjmp EXT_INT1 ; IRQ1 Handler
rjmp TIM2_COMP ; Timer2 Compare Handler
rjmp TIM2_OVF ; Timer2 Overflow Handler
rjmp TIM1_CAPT ; Timer1 Capture Handler
rjmp TIM1_COMPA ; Timer1 CompareA Handler
rjmp TIM1_COMPB ; Timer1 CompareB Handler
rjmp TIM1_OVF ; Timer1 Overflow Handler
rjmp TIM0_OVF ; Timer0 Overflow Handler
rjmp SPI_STC ; SPI Transfer Complete Handler
rjmp USART_RXC ; USART RX Complete Handler
rjmp USART_UDRE ; UDR Empty Handler
rjmp USART_TXC ; USART TX Complete Handler
rjmp EE_RDY ; EEPROM Ready Handler
rjmp ANA_COMP ; Analog Comparator Handler
rjmp TWSI ; Two-wire Serial Interface Handler
rjmp SPM_RDY ; Store Program Memory Ready Handler

;RESET: ; Reset Handler
EXT_INT0: ; IRQ0 Handler
;EXT_INT1: ; IRQ1 Handler
TIM2_COMP: ; Timer2 Compare Handler
TIM2_OVF: ; Timer2 Overflow Handler
TIM1_CAPT: ; Timer1 Capture Handler
TIM1_COMPA: ; Timer1 CompareA Handler
TIM1_COMPB: ; Timer1 CompareB Handler
TIM1_OVF: ; Timer1 Overflow Handler
TIM0_OVF: ; Timer0 Overflow Handler
SPI_STC: ; SPI Transfer Complete Handler
USART_RXC: ; USART RX Complete Handler
USART_UDRE: ; UDR Empty Handler
USART_TXC: ; USART TX Complete Handler
EE_RDY:
ANA_COMP:
TWSI:
SPM_RDY:

reti

RESET:
ldi Temp,high(RAMEND); Main program start
out SPH,r16 ; Set Stack Pointer to top of RAM
ldi r16,low(RAMEND)
out SPL,r16

ldi Temp1,0b00000000
out GICR,Temp1

ldi Temp1,0b00000000
out MCUCR,Temp1

ldi Temp1,0b10000000 ;присвоение константы
out DDRD,Temp1 ;вывод

sei ;

main:
rjmp main

EXT_INT1:
ldi Temp2,0b10000000
out PortD,Temp2
reti


Ребят здравствуйте,объясните плз что надо настраивать для работы внешних прерываний,вектор прерываний выдрал из даташите
Аватара пользователя
НАПАЛМ
Это не хвост, это антенна
Сообщения: 1314
Зарегистрирован: Пт ноя 27, 2009 19:47:13
Откуда: Казань

Re: Внешние прерывания не работают Atmega8

Сообщение НАПАЛМ »

Таблицу векторов прерываний вынесите в отдельный файл и сделайте всё по-нормальному.
Пример:
Спойлер

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

// Таблица прерываний вынесена для удобства.
;=== BEGIN "ivectors.inc" ==============

; Тут располагается "таблица векторов на обработчики прерываний" - важнейшая вещь!
; Если про нее забыть, то можно огрести такие неразрешимые глюки, что просто капец. Так что не забываем...
; (Вынесено из общего кода в отдельный файл - для облегчения портирования программы на другой камень...)
;
; КАК СДЕЛАТЬ:
; Скопировать секцию "INTERRUPT VECTORS" из HAL-файла Микроконтроллера (например, "tn85def.inc"),
; Заменить все ".equ" на ".org"... и дописать ко всем точкам входа команду RETI.
; (Это на тот случай, если Прерывание случайно вылезет - чтобы вернуть управление туда, откуда прервалось.)


; ***** INTERRUPT VECTORS ************************************************
; Используем HAL Микроконтроллера "ATmega88PA"

 .org   INT0addr   ; External Interrupt Request 0
reti
 .org   INT1addr   ; External Interrupt Request 1
reti
 .org   PCI0addr   ; Pin Change Interrupt Request 0
reti
 .org   PCI1addr   ; Pin Change Interrupt Request 0
reti
 .org   PCI2addr   ; Pin Change Interrupt Request 1
reti
 .org   WDTaddr       ; Watchdog Time-out Interrupt (Не стоило злить собаку...)
reti
 .org   OC2Aaddr   ; Timer/Counter2 Compare Match A
reti
 .org   OC2Baddr   ; Timer/Counter2 Compare Match A
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
reti
 .org   OC0Aaddr   ; TimerCounter0 Compare Match A
reti
 .org   OC0Baddr   ; TimerCounter0 Compare Match B
reti
 .org   OVF0addr   ; Timer/Couner0 Overflow
reti
 .org   SPIaddr           ; SPI Serial Transfer Complete
reti

 .org   URXCaddr   ; USART Rx Complete
RJMP   RX_OK
        
 .org   UDREaddr   ; USART, Data Register Empty
RJMP   UD_OK

 .org   UTXCaddr   ; USART Tx Complete (Передача завершена, можно плясать лезгинку)
RJMP   TX_OK

 .org   ADCCaddr   ; ADC Conversion Complete
reti
 .org   ERDYaddr   ; EEPROM Ready
reti
 .org   ACIaddr           ; Analog Comparator
reti
 .org   TWIaddr           ; Two-wire Serial Interface
reti
 .org   SPMRaddr   ; Store Program Memory Read
reti

.org   INT_VECTORS_SIZE   ; size in words <<Конец таблицы прерываний>>


;=== END "ivectors.inc" ================

Вместо reti в этом файле по мере надобности добавляйте rjmp метка_на_обработчик_прерывания.
Из обработчика выходите только по reti.
pimple2006
Первый раз сказал Мяу!
Сообщения: 20
Зарегистрирован: Ср фев 08, 2012 22:58:32
Откуда: Лебедянь

Re: Внешние прерывания не работают Atmega8

Сообщение pimple2006 »

НАПАЛМ писал(а):Таблицу векторов прерываний вынесите в отдельный файл и сделайте всё по-нормальному.
Пример:
Спойлер

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

// Таблица прерываний вынесена для удобства.
;=== BEGIN "ivectors.inc" ==============

; Тут располагается "таблица векторов на обработчики прерываний" - важнейшая вещь!
; Если про нее забыть, то можно огрести такие неразрешимые глюки, что просто капец. Так что не забываем...
; (Вынесено из общего кода в отдельный файл - для облегчения портирования программы на другой камень...)
;
; КАК СДЕЛАТЬ:
; Скопировать секцию "INTERRUPT VECTORS" из HAL-файла Микроконтроллера (например, "tn85def.inc"),
; Заменить все ".equ" на ".org"... и дописать ко всем точкам входа команду RETI.
; (Это на тот случай, если Прерывание случайно вылезет - чтобы вернуть управление туда, откуда прервалось.)

; ***** INTERRUPT VECTORS ************************************************
; Используем HAL Микроконтроллера "ATmega88PA"

 .org   INT0addr   ; External Interrupt Request 0
reti
 .org   INT1addr   ; External Interrupt Request 1
reti
 .org   PCI0addr   ; Pin Change Interrupt Request 0
reti
 .org   PCI1addr   ; Pin Change Interrupt Request 0
reti
 .org   PCI2addr   ; Pin Change Interrupt Request 1
reti
 .org   WDTaddr       ; Watchdog Time-out Interrupt (Не стоило злить собаку...)
reti
 .org   OC2Aaddr   ; Timer/Counter2 Compare Match A
reti
 .org   OC2Baddr   ; Timer/Counter2 Compare Match A
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
reti
 .org   OC0Aaddr   ; TimerCounter0 Compare Match A
reti
 .org   OC0Baddr   ; TimerCounter0 Compare Match B
reti
 .org   OVF0addr   ; Timer/Couner0 Overflow
reti
 .org   SPIaddr           ; SPI Serial Transfer Complete
reti

 .org   URXCaddr   ; USART Rx Complete
RJMP   RX_OK
        
 .org   UDREaddr   ; USART, Data Register Empty
RJMP   UD_OK

 .org   UTXCaddr   ; USART Tx Complete (Передача завершена, можно плясать лезгинку)
RJMP   TX_OK

 .org   ADCCaddr   ; ADC Conversion Complete
reti
 .org   ERDYaddr   ; EEPROM Ready
reti
 .org   ACIaddr           ; Analog Comparator
reti
 .org   TWIaddr           ; Two-wire Serial Interface
reti
 .org   SPMRaddr   ; Store Program Memory Read
reti

.org   INT_VECTORS_SIZE   ; size in words <<Конец таблицы прерываний>>


;=== END "ivectors.inc" ================

Вместо reti в этом файле по мере надобности добавляйте rjmp метка_на_обработчик_прерывания.
Из обработчика выходите только по reti.


после некоторых махинаций имею

vectors.inc

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

.equ   RESET   = 0x0000   ; reset

.org RESET
rjmp proga

.org INT0addr ;External Interrupt Request 0
rjmp obrab
.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
reti
.org OVF0addr ; Timer/Counter0 Overflow
reti
.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 ; size in words


test.asm

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

.include "C:\avrassembler\include\m8def.inc"
.include "C:\vectors.inc"

.def Temp=R16
.def Temp1=R17
.def Temp2=R18


.cseg
.org 0x0013

proga:
ldi Temp,high(RAMEND); Main program start
out SPH,r16 ; Set Stack Pointer to top of RAM
ldi r16,low(RAMEND)
out SPL,r16

ldi Temp1,0b01000000
out GICR,Temp1

ldi Temp1,0b00000000
out MCUCR,Temp1

ldi Temp1,0b10000000 ;присвоение константы
out DDRD,Temp1 ;вывод

sei ;

main:
rjmp main

reti

obrab:
ldi Temp2,0b10000000
out PortD,Temp2
reti


все ли правильно?
Аватара пользователя
НАПАЛМ
Это не хвост, это антенна
Сообщения: 1314
Зарегистрирован: Пт ноя 27, 2009 19:47:13
Откуда: Казань

Re: Внешние прерывания не работают Atmega8

Сообщение НАПАЛМ »

Судя по симуляции в AVR Studio 4, всё работает, переход на обработчик прерывания происходит.
sheffline_85
Нашел транзистор. Понюхал.
Сообщения: 176
Зарегистрирован: Ср дек 08, 2010 11:05:59
Откуда: Ростов-на-Дону
Контактная информация:

Re: Внешние прерывания не работают Atmega8

Сообщение sheffline_85 »

Не стал создавать новую тему, суть проблемы та же самая по сути.
Пытаюсь освоить самостоятельно создание частотника, застрял на процессе обработки внешнего прерывания INT0 и INT1, суть - при нажатии кнопки на PD2 частота уменьшается, а при нажатии кнопки на PD3 увеличивается синуса.
Листинг программы -

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

volatile unsigned int freq_int = 1250;
#include <mega8.h>
 
int sin[128]={127,134,140,146,152,158,164,170,176,182,187,193,198,203,208,213,217,222,226,230,233,
236,240,242,245,247,249,251,252,253,254,254,254,254,254,253,252,251,249,247,245,242,
240,236,233,230,226,222,217,213,208,203,198,193,187,182,176,170,164,158,152,146,140,
134,127,121,115,109,103,97,91,85,79,73,68,62,57,52,47,42,38,33,29,25,22,19,15,13,10,
8,6,4,3,2,1,1,0,1,1,2,3,4,6,8,10,13,15,19,22,25,29,33,38,42,47,52,57,62,68,73,79,85,
91,97,103,109,115,121};

int i;

interrupt [TIM1_COMPA] void timer1_compa_isr(void) {
OCR2=sin[i];
i++;
if (i>127) i=0;
}

interrupt [EXT_INT0] void ext_int0_isr(void)
{
freq_int += 25;
  }
 
interrupt [EXT_INT1] void ext_int1_isr(void)
{
freq_int -= 25;
}   
     
void main(void)
{
PORTB=0x00;
DDRB=0x08;
PORTD=0x0C;
DDRD=0x00;
TCCR1A=0x00;
TCCR1B=0x09;
TCNT1=0x00;
ICR1=0x00;
OCR1AH=(unsigned char)(freq_int >> 8);
OCR1AL=(unsigned char)freq_int;
OCR1BH=0x00;
OCR1BL=0x00;
ASSR=0x00;
TCCR2=0x69;
TCNT2=0x00;
OCR2=0x00;

GICR|=0xC0;
MCUCR=0x00;
GIFR=0xC0;

TIMSK=0x10;
#asm("sei")
while (1)
      {
     

      };
}


Частота меняется вручную, заданием значения функции freq_int.
Пишу в CodevisionAVR (не предлагать WinAVR пожалуйста, сейчас речь идет не о религии, а о работоспособности в принципе), меняться по прерыванию не желает. (по протеусу)

Думал вначале функция не обрабатывается, запихнул код в дебагер AVRStudio и обнаружил неприятный факт, на сконфигурированных выводах порта D на вход с подтяжкой стоит всегда "1", в независимости от состояния прерываний INT0/INT1, не знаю, может просто фича проги, не вникал.
Естественно при этом регистр OCR1A не меняется

В чем может быть проблема?

Пожалуйста не надо писать бессмыслицы в стиле "все православную WinAVR юзают", пиши на асме. Так можно бесконечно метаться, нужна реальная помощь, в МК новичок.

Проблема я так понимаю в том, что прерывание не происходит.

заранее спасибо!

Читал хелп CodeVisionAVR на тему внешних прерываний, там достаточно сконфигурировать регистры
GICR|
MCUCR
GIFR
и указать векторы, что собственно сделал, в WinAVR надо еще подрубать библиотеку прерываний, судя по гуглу.
Аватара пользователя
Pink-Pank
Опытный кот
Сообщения: 721
Зарегистрирован: Ср июн 11, 2014 09:43:13
Откуда: США
Контактная информация:

Re: Внешние прерывания не работают Atmega8

Сообщение Pink-Pank »

Прерывания у Вас правильно настроены (Если, конечно, хотите срабатывания по низкому уровню). Я не вижу у Вас в коде объявления всех используемых переменных. Могу сразу подсказать, что переменные, которые используются в прерываниях обязательно должны быть объявлены с модификатором volatile - иначе возможна неправильная работа программы.
Думал вначале функция не обрабатывается, запихнул код в дебагер AVRStudio и обнаружил неприятный факт, на сконфигурированных выводах порта D на вход с подтяжкой стоит всегда "1", в независимости от состояния прерываний INT0/INT1, не знаю, может просто фича проги, не вникал.
Естественно при этом регистр OCR1A не меняется

В студии нужные состояния входов и флагов задаются вручную. Состояния флагов внешних прерываний на входы не влияют (если это не предусмотрено программой), а вот состояния входов - наоборот, влияют на состояния флагов.
Успехов!
Fucking static initialization order fiasco
sheffline_85
Нашел транзистор. Понюхал.
Сообщения: 176
Зарегистрирован: Ср дек 08, 2010 11:05:59
Откуда: Ростов-на-Дону
Контактная информация:

Re: Внешние прерывания не работают Atmega8

Сообщение sheffline_85 »

Я не вижу у Вас в коде объявления всех используемых переменных.

в самом начале листинга

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

volatile unsigned int freq_int = 1250;

или нужно где-то еще прописывать?
Аватара пользователя
Pink-Pank
Опытный кот
Сообщения: 721
Зарегистрирован: Ср июн 11, 2014 09:43:13
Откуда: США
Контактная информация:

Re: Внешние прерывания не работают Atmega8

Сообщение Pink-Pank »

А, все, увидел.

Переменная i тоже должна быть volatile

А каким образом Вы меняете частоту?

Переменная Frequency_че_то_там у вас меняется, но у Вас нет ни одной строчки, которая зависела бы от этой переменной

Наверное, вот это:

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

OCR1AH=(unsigned char)(freq_int >> 8);
OCR1AL=(unsigned char)freq_int;


нужно засунуть в цикл while(1):

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

while (1)
{
OCR1AH=(unsigned char)(freq_int >> 8);
OCR1AL=(unsigned char)freq_int;
};
Fucking static initialization order fiasco
sheffline_85
Нашел транзистор. Понюхал.
Сообщения: 176
Зарегистрирован: Ср дек 08, 2010 11:05:59
Откуда: Ростов-на-Дону
Контактная информация:

Re: Внешние прерывания не работают Atmega8

Сообщение sheffline_85 »

переменная freq_int пишется напрямую в регистр OCR1A, частота синусоиды=частота кварца/разрядность синуса*freq_int.
freq_int по сути это число тактов до сброса таймера TCCR1.
т.е. изменяя значение справа от = я реально меняю значение регистра OCR1A и как следствие частоту синуса.
Аватара пользователя
Pink-Pank
Опытный кот
Сообщения: 721
Зарегистрирован: Ср июн 11, 2014 09:43:13
Откуда: США
Контактная информация:

Re: Внешние прерывания не работают Atmega8

Сообщение Pink-Pank »

В цикл засуньте все эти вычисления. ;)
А то у Вас 1 раз вычисляется и на том все заканчивается. ;)
Fucking static initialization order fiasco
sheffline_85
Нашел транзистор. Понюхал.
Сообщения: 176
Зарегистрирован: Ср дек 08, 2010 11:05:59
Откуда: Ростов-на-Дону
Контактная информация:

Re: Внешние прерывания не работают Atmega8

Сообщение sheffline_85 »

Pink-Pank писал(а):В цикл засуньте все эти вычисления. ;)
А то у Вас 1 раз вычисляется и на том все заканчивается. ;)

и как я дурья башка до этого раньше не допер, спасибо огромное, заработало :beer: :beer: :beer:
Он же по сути да, один раз произвел вычисление и дальше по прерыванию возвращается в пустое тело бесконечного цикла?
Разобрался, на ступенечку стал мудрее, спасибо вам огромное :) :beer:
Ответить

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