전기전자/Atmega128
[0x04] 외부 인터럽트
jemin0619
2024. 3. 28. 14:40
ISR이란
Interrupt Service Routine의 줄임말
main 함수 내의 프로그램 실행 중 인터럽트가 발생하면 ISR이 동작하며 main 함수 내의 동작을 잠시 미루고 ISR을 실행한다.
외부 인터럽트 레지스터
SREG : 인터럽트의 사용 여부를 저장.
- 최상위 비트가 1이면 enable, 0이면 disable
- sei() = (SREG=0b10000000;)
EIMSK (External Interrupt Mask)
- 인터럽트를 사용할 핀을 1로 해준다. - DDRX로 입력 포트 설정할 때 썼던 값의 bitwise not (~)을 해주면 편하다.
EICRA, EICRB : 인터럽트를 언제 시킬건지 결정
- A는 D0 ~ D3 를 설정
- EICRA = 0b D3 D2 D1 D0 (각 포트마다 2bit씩 사용)
- B는 E4 ~ E7 를 설정
- EICRB = 0b E7 E6 E5 E4 (각 포트마다 2bit씩 사용)
- 10은 상승에지, 11은 하강에지
예제
더보기
1. LED 켜고 끄기
#define F_CPU 16000000
#include <avr/io.h>
#include <avr/interrupt.h>
unsigned char led_on = 0x00;
ISR(INT0_vect){
led_on = ~led_on;
}
int main(void){
DDRA = 0x0F;
DDRD = ~0x01;
EIMSK = 0x01;
EICRA = 0b00000010;
sei();
while(1){
PORTA = led_on;
}
}
2. Array FND 구동시키기
#define F_CPU 16000000
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
int number=0; //숫자 초기값
unsigned char arr[3]={0,};
void parseNum(int num){
arr[0]=arr[1]=0;
int idx=0;
while(num){
arr[idx++]=num%10;
num/=10;
}
}
ISR(INT4_vect){ //가산
number++;
if(number>99) number=0;
}
ISR(INT5_vect){ //감산
number--;
if(number<0) number=99;
}
int main(void){
DDRA = 0x0F; //FND
DDRC = 0x03; //TR
DDRE = ~0b00110000; //SW
EIMSK = 0b00110000;
EICRB = 0b00001111;
sei();
while(1){
parseNum(number);
for(int i=0;i<2;i++){
PORTC = ~(0x01<<i);
PORTA = arr[i];
_delay_ms(5);
}
}
}