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;

각 포트의 입출력 상태 및 초기값(S1S000으로 표시)

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)의 기능은 EIMSK0번자리 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)을 이용해 표시.