인터럽트 처리
인터럽트 발생 -> 벡터 테이블의 해당 프로그램 주소로 이동 -> 프로그램 주소에 기록된 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); //인터럽트 활성화
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;
PCMSK2의 PCINT19을 1로 / 풀업 저항은 포트 값 1
'IoT > 아트멜 스튜디오와 아두이노로 배우는 ATmega328 프로그래밍' 카테고리의 다른 글
오버플로 / 비교일치 인터럽트 (0) | 2020.06.09 |
---|---|
ATmega328 가변저항 / 난수 생성 (0) | 2020.06.08 |
LED & button (0) | 2020.05.24 |
시리얼 통신 / UART 통신 (0) | 2020.05.21 |
UART 라이브러리 만들기 (0) | 2020.05.08 |
댓글