본문 바로가기
IoT/아트멜 스튜디오와 아두이노로 배우는 ATmega328 프로그래밍

인터럽트

by javapp 자바앱 2020. 5. 30.
728x90

벡터 이름  = ISR 호출시 이름

인터럽트 처리

인터럽트 발생 -> 벡터 테이블의 해당 프로그램 주소로 이동 -> 프로그램 주소에 기록된 ISR 주소 찾기

-> ISR로 이동 및 처리 -> 인터럽트 발생이전으로 되돌아가 실행

 

 

ISR 호출 조건

* '전역적 인터럽트 활성화' 비트가 세트

* 인터럽트 별로 '개별 인터럽트 활성화' 비트 세트

* 인터럽트에 해당하는 이벤트 발생

 

전역 인터럽트 활성화 sei()

전역 인터럽트 비활성화 cli()

 

 

주의

중첩 인터럽트 금지 : ISR 내 인터럽트 발생 허용 x

최적화 방지 : 최적화 과정 생략하도록 volatile 키워드 사용 

volatile int ..

단일 동작 보장 : 실행중인터럽트 발생 일시 금지 : ATOMIC_BLOCK

 

 


 

외부 인터럽트

–INT0 : PD2 또는 디지털 2번 핀

–INT1 : PD3 또는 디지털 3번 핀

 

//출력은 D11~ D8 D7~D4

//INT0 = D2 INT1 = D3 버튼

ISR(INT0_vect)

{

           if(PIND & 0x04) 0000 0100 //디지털 2번 핀

           {

                      PORTD = 0x0C //*중요  내부 풀업저항 사용 위해 항상 1로 셋팅

                      PORTB = 0x00;

           }else

           {

                      uint8_t on_off = 0;

                      for(int i =0; i<8;i++){

                                 on_off |= 0x01 << i;

                                 PORTD = (on_off << 4) | 0x0C; // 풀업 저항 계속 초기화

                                 PORTB = on_off >> 4; //위치 초기화

                                 _delay_ms(100);

                      }

           }

}

ISR(INT1_vect)

{

           //역 진행

}

void INIT_PORT(void)

{

           DDRB = 0x0F; //led 출력으로 설정ㅇ

           PORTB = 0x00;

          

           DDRD = 0xF0; //led 출력으로 설정

           PORTD = 0x0C; //버튼 PD2, PD3 을 내부 풀업 저항, PD4 ~ PD7 초기화

}//초기화

 

void INIT_INT(void)

{

           EIMSK |= (1 << INT0) | (1 << INT1); //int0 int1 인터럽트 활성화

           EICRA |= (1 << ISC00) | (1 << ISC10); //01 | 01 버튼 상태 변화 감지

           sei();                                                                                   //전역적으로 인터럽트 허용

}

int main(void)

{

           INIT_PORT(); //포트 설정

           INIT_INT(); //int0 을 인터럽트로

          

           while(1){}

}

 


 

EIMSK 레지스터

INT1 INT0

 

EICRA 레지스터:

버튼 상태 변화 감지 / ISC11 ISC10 한쌍 / ISC01 ISC00

) EICRA |= (1 << ISC00) | ( 1<< ISC10); 0 1   0 1


핀 변화 인터럽트

 

PCICR 레지스터 

2 = D, 1 = C, 0 = B

예) 

PCICR |= (1 << PCIE2) | (1<< PCIE0); //인터럽트 활성화

2 = D, 1 = C, 0 = B

 

 

PCMSKn 레지스터                                                                           B2       B1        B0

PCMSK0 = B

PCMSK1 = C

PCMSK2 = D

 

예)

       PCMSK2 |= (1 << PCINT19);                    //PD3  변화 인터럽트 허용

       PCMSK0 |= (1 << PCINT4);                     //PD12 = PB4  변화 인터럽트 허용



핀 변화 인터럽트

 

 

#define F_CPU 16000000L

#include <util/delay.h>

#include <avr/io.h>

#include <avr/sfr_defs.h>

#include <avr/interrupt.h>

 

ISR(PCINT2_vect)

{

       if(PIND & 0x08){//0000 1000 = D3 눌렀을때

               PORTD = 0x08;  //d3 내부 풀업 저항

               PORTB = 0x10;  //d12 내부 풀업 저항

       }else

       {

               uint8_t on_off = 0;

               //....

               PORTD = (on_off << 4) | 0x08;  //LED 켤 때 마다 풀업 저항 셋

               PORTB = on_off >> 4 | 0x10;  //LED 켤 때 마다 풀업 저항 셋

       }

      

}

ISR(PCINT0_vect)

{

      

}

void INIT_PORT(void)

{

       DDRB = 0x0F; //led 출력으로 설정ㅇ

       PORTB = 0x10; //D12 내부풀업저항

      

       DDRD = 0xF0; //led 출력으로 설정

       PORTD = 0x08; //PD3 풀업 저항, 0000 1000 PD4 ~ PD7 초기화

}//초기화

 

void INIT_PCINT(void)

{

       PCICR |= (1 << PCIE2) | (1<< PCIE0); //인터럽트 활성화

       PCMSK2 |= (1 << PCINT19);                    //PD3 변화 인터럽트 허용

       PCMSK0 |= (1 << PCINT4);                     //PD12 변화 인터럽트 허용

       sei();                                                     //전역적으로 인터럽트 허용

}

int main(void)

{

       INIT_PORT(); //포트 설정

       INIT_PCINT(); //int0 인터럽트로

      

       while(1){}

}

 

 

(PORTB) PD12 -> 버튼 -> 저항 -> LED -> DDRD | DDRB

 

D포트 모두 입력으로 선언 DDRD = 0;

PCMSK2PCINT19 1/ 풀업 저항은 포트 값 1

댓글