Embedded/마이크로프로세서
ATMEGA128 포토인터럽트 제어 실험
장영현
2023. 6. 1. 01:33
728x90
- 포토인터럽트
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#define I 7
unsigned char seg[] = {0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8, 0x80, 0x90, 0x88, 0x83, 0xC6, 0xA1, 0xC6, 0x86, 0x8E};
volatile int count = 0;
ISR (INT0_vect) {
count++;
if(count == 26) count = 0;
}
void Initial_set(void){
DDRF = 0xFF;
PORTF = 0xC0;
DDRB |= 1<<DDB1 | 1<<DDB0;
PORTB &= ~(1<<PD1) & ~(1<<PD1);
DDRD &= ~(1<<DDD0);
PORTD |= 1<<PD0;
EIMSK |= 1<<INT0;
EICRA |= 3<<ISC00;
SREG |= 1<<I;
}
void main(void) {
Initial_set();
while(1){
PORTF = seg[count/10];
PORTB = 0x0D;
_delay_ms(5);
PORTF = seg[count%10];
PORTB = 0x0E;
_delay_ms(5);
}
}
- 코드설명
DDRF = 0xFF;
PORTF = 0xC0;
DDRB |= 1<<DDB1 | 1<<DDB0;
PORTB &= ~(1<<PD1) & ~(1<<PD1);
DDRD &= ~(1<<DDD0);
PORTD |= 1<<PD0;
각 포트의 입출력 상태 및 초기값(S1과 S0에 00으로 표시)
Bit | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
DDRF | DDA7 | DDA6 | DDA5 | DDA4 | DDA3 | DDA2 | DDA1 | DDA0 |
1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | |
PORTF | PA7 | PA6 | PA5 | PA4 | PA3 | PA2 | PA1 | PA0 |
1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 |
Bit | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
DDRB | DDB7 | DDB6 | DDB5 | DDB4 | DDB3 | DDB2 | DDB1 | DDB0 |
DDB7 | DDB6 | DDB5 | DDB4 | DDB3 | DDB2 | 1 | 1 | |
PORTB | PB7 | PB6 | PB5 | PB4 | PB3 | PB2 | PB1 | PB0 |
PB7 | PB6 | PB5 | PB4 | PB3 | PB2 | 0 | 0 |
Bit | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
DDRD | DDD7 | DDD6 | DDD5 | DDD4 | DDD3 | DDD2 | DDD1 | DDD0 |
DDA7 | DDA6 | DDA5 | DDA4 | DDA3 | DDD2 | DDD1 | 0 | |
PORTD | PD7 | PD6 | PD5 | PD4 | PD3 | PD2 | PD1 | PD0 |
PD7 | PD6 | PD5 | PD4 | PD3 | PD2 | PD1 | 1 |
외부 인터럽트와 관련된 레지스터의 조건
Bit | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
EIMSK | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 |
EICRB | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 |
SREG | 1 | X | X | X | X | X | X | X |
volatile int count = 0;
- 변수를 선언할 때 앞에 volatile을 붙이면 컴파일러는 해당 변수를 최적화에서 제외하여 항상 메모리에 접근하도록 만든다. volatile로 선언한 변수는 사용할 때 항상 메모리에 접근한다. 즉, 이 변수는 언제든지 값이 바뀔 수 있으니까 항상 메모리에 접근하라고 컴파일러에게 알려주는 것으로 사용.
ISR (INT0_vect) {
count++;
if(count == 26) count = 0;
}
해당 인터럽트 서비스 루틴(interrupt service routine)의 기능은 EIMSK의 0번자리 Bit에 연결된 포토인터럽터가 상승 인터럽트로 동작 시 ISP의 함수가 작동한다.
EIMSK |= 1<<INT0;
EICRA |= 3<<ISC00;
SREG |= 1<<I;
- EIMSK : 0번 자리에 연결된 소자가 인터럽트를 사용할 수 있게 설정.
- EICRA : 0번 자리에 연결된 포토인터럽터가 상승에지에서 인터럽트가 동작되도록 설정.
- SREG : I번째 자리에 1(HIGH)을 입력하여 외부 인터럽트를 설정.
PORTF = seg[count/10];
PORTB = 0x0D;
_delay_ms(5);
PORTF = seg[count%10];
PORTB = 0x0E;
_delay_ms(5);
- PORTF = 포토인터럽터가 작동될 때마다 전역변수인 COUNT의 값을 증가시켜 십의자리는 count/10, 일의자리는 count%10를 하여 세그먼트의 숫자를 표시.
- PORTB = S1의 자리는 PORTB = 0x0D(0b00001101)로, S0의 자리는 PORTB = 0x0E(0b00001110)을 이용해 표시.