본문 바로가기
대한상공회의소 스마트팩토리 교육/IoT 디바이스 개발

[IoT 디바이스 개발] AVR(ATmega128A)«수업-12» : 아날로그 비교기 / 인터럽트

by 나는영하 2022. 2. 15.

※ 주의사항 

본 블로그는 수업 내용을 바탕으로 제가 이해한 부분을 정리한 블로그입니다.
본 내용을 참고로만 보시고, 틀린 부분이 있다면 지적 부탁드립니다!

감사합니다😁

 

안녕하세요!!

오늘은 아래와 같은 내용을 확인해보겠습니다.

 

아날로그 비교기

ACSR 레지스터

인터럽트

SREG 레지스터

EIMSK 레지스터

EICRA(EICRB) 레지스터

EIFR 레지스터


1. 아날로그 비교기

아날로그 비교기는 두 핀으로 입력되는 아날로그 전압을 비교하여 비교 결과를 디지털로 출력한다.

- AIN0(PE2, 양)핀과 AIN1(PE3, 음)핀 사용

- AIN0 > AIN1 이면 1, 이외의 경우이면 0을 출력한다.

- AIN0 대신 내부 1.23V 전압 사용 가능 (ACSR 레지스터의 ACBG 비트 세트)

※ ADC를 위한 핀은 PF의 0~7에 해당되고 아날로그 비교기를 위한 핀은 PE2, PE3에 해당된다. 

 

1-1.  ACSR 레지스터

ACSR 레지스터 구조

1) ACD : 아날로그 비교기 비활성화

- 0 : 활성화, 1 : 비활성화 / Default 값은 0으로서 기본적으로 활성화 된 상태이다.

2) ACBG : 내부 기준 전압 사용 설정

- 1로 설정하면 양의 입력(AIN0)으로 1.23V의 내부 밴드갭 전압을 선택할 수 있다.

3) ACO : 비교기 결과가 기록되는 비트

- 해당 비트가 1로 세트되면 AIN0이 AIN1보다 값이 더 크다는 것을 의미한다.

4) ACI : 인터럽트 플래그 비트

5) ACIE : 인터럽트 허용 비트

6) ACIC : 입력 캡처 트리거 비트 (14장 참조)

7) ACISn (1번, 0번 비트) : 인터럽트 발생 시점 설정 비트

- 00 : 비교 결과값의 상승 또는 하강 에지에서 인터럽트 발생

- 10 : 비교 결과값의 하강 에지에서 인터럽트 발생

- 11 : 비교 결과값의 상승 에지에서 인터럽트 발생

 

1-2.  아날로그 비교기 예제

실습 사진(좌) / 실습 코드(중) / 실습 결과(우)

- UART 통신을 하는 부분이나 ADC 입력 값을 받아서 PUTTY를 통해 출력하는 부분은 기존과 동일하기때문에 생략하겠습니다!! 😁

 

1) LED 및 가변 저항, 수위 센서 회로 결선

- PORTA : LED

- PORTE - 2, 3 : 물 수위 센서, 가변 저항 결선 (아날로그 비교기용)

- PORTF - 2, 3 : 물 수위 센서, 가변 저항 결선 (ADC용)

 

2) 코드 설명

- Line 46 ~ 49 : 가변 저항의 데이터 값을 받아서 PuTTy를 통해 출력

- Line 50 ~ 53 : 물 수위 센서의 데이터 값을 받아서 PuTTy를 통해 출력

- Line 55 ~ 56 : 아날로그 비교기에 데이터가 기록이 되면(AC0가 1로 세트 되면) If문 실행

 

테스트 할 당시에 가변저항의 값만을 돌려서 테스트를 해 보았는데 이상하게 PUTTY에서는 물 수위센서의 값이 변경되었다고 떴습니다..ㅠ 가변 저항은 PORTF의 3번 핀, 물 수위 센서는 PORTF의 2번 핀에 연결되어 있는지를 몇번이고 확인해서 결선에는 문제가 없습니다. 아마도 다중 ADC 입출력과 관련해서 입력 레지스터(?) 쪽에 대한 오류라 생각이 되는데 추후에 관련 내용을 확인해 보아야 할 것 같습니다. (혹시나 다중 ADC 입출력과 관련해서 주의할 점을 알고 계신분은 댓글 부탁드립니다!!!!) 😥

 


2. 인터럽트

(※ 아두이노 명령어 : attachInterrupt() 에 해당되는 부분)

2-1.  인터럽트란?

- 인터럽트란 마이크컨트롤러가 즉시 특정 작업을 처리하도록 요구하는 비정상적인 사건을 지칭하는 것이다.

1) ATmega128A의 인터럽트

- 35개의 인터럽트 사용 가능

ATmega128A의 35개 인터럽트 우선순위

- 인터럽트 벡터 : 인터럽트가 발생했을때 처리가 옮겨질 해당 ISR의 메모리 주소

- 인터럽트 벡터 테이블 : 35개의 인터럽트에 대한 인터럽트 벡터를 모아놓은 테이블

플래시 메모리의 0x0000번지에서 0x0044번지 까지 기록되어 있음

- 인터럽트 처리 순서 : 인터럽트 발생 → 인터럽트 벡터 테이블의 해당 벡터가 저장된 위치로 이동 → 인터럽트 벡터 값에 해당하는 ISR로 이동 → ISR 처리 → 인터럽트 처리 이전에 수행하던 전의 코드로 되돌아감

※ ISR(Interrupt Service Routine)
- 인터럽트가 발생하였을때 처리 루틴
- 하드웨어에 의해 호출 (코드 상에는 ISR을 호출하는 부분이 없음)
- 반환값이 없고 매개변수의 데이터 형이 없는 함수 
모든 ISR은 동일한 이름을 가지며 인터럽트 벡터 이름으로 매개변수를 구분한다.

 

2-2.  인터럽트 사용시 주의사항

1) 중첩된 인터럽트

- 인터럽트 처리 루틴을 실행하는 동안에는 다른 인터럽트가 발생하지 않는다.

- ISR은 가능한 짧게 작성하고 바로 반환하도록 프로그래밍을 한다.

2) 인터럽트 우선순위

- ATmega128A의 35 개인터럽트 표에서 번호가 낮은 인터럽트 일수록 우선순위가 더 높다.

3) 최적화 방지 ★

- 컴파일러는 가능한 작고 빠른 실행 파일을 만들어내기 위해 최적화를 수행한다.

- 인터럽트에 사용되는 변수는 전역적인 변수로 인터럽트를 호출할때마다 항상 초기값을 가지게 된다.

- 따라서 변수를 선언할때 'volatile'을 앞에 붙혀주어야 한다.

ex) unsigned char value = 0; → volatile unsingned char value = 0;

 


 

3. 인터럽트 관련 레지스터

3-1.  SREG 레지스터

상태 레지스터(Status Register)에서 인터럽트에 관련된 비트는 7번 비트 하나뿐이다.

SREG 레지스터 구조

1) I 비트 (7번 비트) : Global Interrupt Enable

- 전역적인 인터럽트 발생을 허용한다. (Default 값은 0으로서 전역적인 인터럽트 비활성화)

- 상태레지스터의 I비트를 활성화 하기위해 직접 해당 레지스터의 비트에 1을 세트해도 되지만, sei() 함수로 세트를 하고 cli()함수로 클리어도 가능하다. (사용자의 기호에 맞게 사용)

 

3-2.  EIMSK 레지스터 (외부 인터럽트 사용시)

- 외부 인터럽트는 ATmega128A의 35개 인터럽트 중에서 RESET을 제외하고 우선순위가 제일 높은 인터럽트이다.

- INT0 ~ INT3은 PD0 ~ PD3포트를 사용하고, INT4 ~ INT7은 PE4 ~ PE7포트를 사용한다.

 

EIMSK 레지스터 구조

- EMISK레지스터는 외부 인터럽트의 발생을 허용하는 역할을 한다.

즉, 해당 외부 인터럽트를 활성화 하기 위해서는 본 레지스터의 해당 비트가 세트되어야 한다.

 

3-3.  EICRA(EICRB) 레지스터 (외부 인터럽트 사용시)

- EICRA 레지스터는 INT0 ~ INT3까지의 외부 인터럽트 발생 시점을 결정하는 레지스터이다.

(INT4 ~ INT7은 EICRB 레지스터에서 담당한다.)

EICRA 레지스터

1) ISCn0, ISCn1 비트의 값에 따른 인터럽트 제어 동작

- 00 : INTn핀의 입력값이 LOW 일때 인터럽트 요청을 발생한다.

- 10 : INTn핀의 입력값이 하강 에지(Falling Edge) 일때 인터럽트 요청을 발생한다.

- 11 : INTn핀의 입력값이 상승 에지(Rising Edge) 일때 인터럽트 요청을 발생한다.

 

3-4.  EIFR 레지스터

- 인터럽트 요청이 발생되면 세트되는 레지스터

EIFR 레지스터 구조


4. 인터럽트 관련 실습

4-1.  내부 풀업저항 스위치 1개를 사용하여 LED 점등 및 소등

1) 회로 결선

- PORTA : LED

- PORTD : PUSH BUTTON (내부 풀업 저항 적용)

 

2) 코드 설명

- Line 76 : 인터럽트를 사용하기 위한 헤더파일

- Line 83 : ISR에서 사용되는 변수로서 volatile을 붙힌것이 KeyPoint!!

- Line 86 ~ 89 : 외부 인터럽트 0(INT0)의 ISR에 해당되는 부분

- Line 93 ~ 97 : LED 및 스위치 관련 PORT 설정 부분 (스위치는 내부 풀업저항을 사용하는 내용이 포함)

- Line 101 ~ 104 : 인터럽트 관련 설정부

(외부 인터럽트 0번 활성화, 하강 엣지에서 인터럽트 발생, 전역 인터럽트 활성화)

- main 함수 및 반복문 : ISR의 리턴 값에 따라 LED의 동작을 제어하는 함수부

 

4-2.  풀다운 저항 스위치 2개를 사용하여 LED 점등 및 소등

- PD0(INT0)핀과 PD1(INT1)핀에 풀다운 저항을 연결하고, 포트A에 8개 LED 연결

- PD0을 누르는 경우 LED를 끄고, PD1을 누르는 경우 LED를 켜는 인터럽트 서비스 루틴 작성

1) 회로 결선

- PORTA : LED 

- PORTD : PUSH BUTTON (외부 풀다운 저항 사용)

 

2) 코드 설명

- Line 142 ~ 145 : 외부 인터럽트 0(INT0)의 ISR 부분

- Line 147 ~ 150 : 외부 인터럽트 1(INT1)의 ISR 부분

- Line 154 ~ 157 : LED 및 스위치 관련 PORT 설정 부분

(이번에는 외부 풀다운 저항을 적용했기 때문에 내부 풀업저항 관련 코드 삭제)

- Line 160 ~ 165 : 인터럽트 관련 설정부 (INT0)

- Line 166 ~ 171 : 인터럽트 관련 설정부 (INT1)

(본 코드에는 설정부를 각각 주었는데 한꺼번에 주어도 상관이 없는지??)

- Line 178 ~ 187 : ISR 리턴 값에 따라 LED 동작 제어 부분

 

4-3. 풀다운 저항 스위치 1개를 사용하여 특정 LED 동작 제어

- PD0(INT0)핀에 풀다운 저항을 연결하고, 포트A에 8개 LED 연결

- LED는 0.5초 간격으로 한개씩 점등되고 소등되는 동작 수행

- PD0를 누르면 LED가 점등되는 순서를 반대가 되도록 인터럽트 서비스 루틴 작성

※ 아래의 코드는 미완성된 코드로 요구사항대로 동작하지 않음을 사전에 공지드립니다..😒

1) 회로 결선

- PORTA : LED 8개

- PORTD - 0 : PUSH BUTTON (외부 풀다운 저항 사용)

 

2) 코드 설명 및 문제점 발생

- 비트 시프트 패턴에서 원형 시프트 연산 함수를 인용한 프로그래밍

- 수업에선 메인 함수문이 진행되는 중에 인터럽트를 발생시키면 바로 인터럽트가 수행된다고 하였는데 본 코드대로 동작을 수행하였을때는 인터럽트가 바로 발생하지 않는 느낌이 들었습니다.

(버튼을 눌러도 delay 때문에 인터럽트가 수행되지 않는 느낌(?), 인터럽트는 delay 중에도 발생한다고 들었지만...)

- 본 예제는 좀 더 공부가 필요할 것 같습니다.. 🤣😥

댓글