13. 인터럽트 제어 - 스마트 폰으로 제어하는 아두이노 -
강의 개요 마이크로컨트롤러의 주어진 일들을 미리 지정된 순서에 따라 하나씩 처리 인터럽트 기능 "지금 하고 있는 일보다 먼저 처리해야할 일"이 발생하면, 그 먼저 처리해야 할 일 을 먼저 처리해 주고 나서 하던 일을 계속하도록 하는 기능
13.1 인터럽트의 개념 인터럽트가 발생 마이크로 컨트롤러가 어떤 작업을 진행하고 있다가 갑자기 다른 일이 발생하여 먼저 처리해야 하는 상황이 발생할 경우 현재 수행중인 일을 잠시 중단하고 급한 일을 처리한 후 원래의 일을 다시 이어서 수행 이는 프로그램 된 순서대로 일을 처리 하는 것이 아니라 발생 시기를 예측할 수 없는 경우에 더 효율적
인터럽트의 중요도(Priority) 인터럽트 처리 외부 인터럽트의 종류 "먼저 처리해야할" 우선순위에 따라 결정 현재하고 있는 일보다 중요도가 낮은 일은 무시 인터럽트 처리 인터럽트가 발생 프로세서는 그림과 같이 현재 수행중인 프로그램 중지 상태 레지스터와 PC(Program Counter)등을 스택 잠시 저장 인터럽트 서비스 루틴으로 점프 인터럽트 서비스 루틴을 실행한 후에는 이전의 프로그램으로 복귀하여 정상적인 절차 실행 외부 인터럽트의 종류 폴링(polling)과 인터럽트(interrupt) 2가지
마이크로컨트롤러에서 외부의 입력을 받아들이는 방법 외부입력 인식방법 동작 원리 처리방식 폴링(polling) 사용자가 명령어를 통하여 입력 핀의 값을 계속 조사하여 변화를 알아내는 방식 소프트웨어적 방법 인터럽트(interrupt) MCU 자체가 하드웨어적으로 그 변화를 체크하여 변화가 발생하면 일정한 동작을 하는 방식 하드웨어적 폴링 방식 하드웨어의 지원 없이도 언제든지 가능 하드웨어적으로 지원되는 몇 개의 입력 또는 값의 변화에만 대응 처리가 가능 폴링에 비해 신속하게 대응 가능 특히 실시간 대응이 필요한 경우에는 필수적인 기능 인터럽트는 발생 시기를 예측하기 힘든 사건에 마이크로컨트롤러가 가장 빠르게 대응할 수 있는 방법 비교적 저속으로 동작하는 주변장치의 요청에 고속으로 동작하는 마이컴이 효율적으로 대처하는 중요한 수단
13.2 아두이노 보드의 인터럽트 UNO보드 외부 인터럽트 핀 : 2개 Mega보드 외부 인터럽트 핀 : 6개
아두이노 UNO와 Mega 외부 인터럽트 아두이노 보드 2가지 외부 인터럽트 관련 함수 제공 인터럽트 번호 1 2 3 4 5 UNO보드 핀 번호 Mega보드 핀 번호 21 20 19 18 아두이노 보드 2가지 외부 인터럽트 관련 함수 제공 attachInterrupt(interrupt, function, mode) 외부 인터럽트를 사용하기 위해 사용할 인터럽트와 인터럽트의 발생 방식 등을 설정 detachInterrupt(interrupt) 이미 사용 설정된 외부 인터럽트를 사용 중지
예제 13.1 아두이노 보드의 인터럽트 제어 아두이노 보드의 디지털입출력 핀 2번에 입력이 있으면, 인터럽트 0번을 발생시켜서 8번 핀에 연결되어 있는 아두이노 보드의 LED를 깜박이게 하기 주요개념 초기화할 인터럽트 번호로 0번 인터럽트 사용 아두이노 보드의 디지털입출력 핀 2번을 인터럽트 발생 입력으로 사용 핀 2번에 의하여 인터럽트 이벤트가 발생했을 때 toggle()함수를 호출할 수 있도록 "attachInterrupt(0, toggle, CHANGE);"함수를 사용 아두이노 보드 디지털입출력 핀 2 8 외부 연결 스위치 LED SWITCH모듈 BT0 LED 모듈 LED0
스위치로 외부 인터럽트 발생 회로 구성
예제 13.1의 스케치 int pin = 8; volatile int state = LOW; void setup() { pinMode(pin, OUTPUT); attachInterrupt(0, toggle, CHANGE); } 0번 인터럽트 사용 인터럽트가 호출되면 함수 ‘toggle()’를 호출 void toggle() { state = !state; 함수 호출 때 마다 state 값 반전 (HIGH이면 LOW로, LOW이면 HIHG 반전) void loop() { digitalWrite(pin, state);
예제 13.1의 실행 아두이노 보드의 디지털입출력 핀 2번에 입력 발생 setup 블록의 "attachInterrupt(0, toggle, CHANGE);" 호출을 통해 인터럽트 호출 발생 이 호출의 첫번째 인자는 초기화할 인터럽트 번호로 0번(2번 핀) 인터럽트를 사용하겠다는 의미 다음 인자는 인터럽트 이벤트가 발생했을 때 호출할 함수를 지정 이 함수를 인터럽트 핸들러(interrupt handler)라고 함 toggle() 함수를 호출하도록 하겠다는 의미 마지막 인자는 인터럽트 발생 조건을 지정하는 것 CHAGNE로 설정하였기 때문에 핀 레벨이 변화할 때 마다(high에서 low로 또는 low에서 high로) 인터럽트가 발생
13.3 아두이노 Mega 보드의 인터럽트 HBE-MCU-Multi의 입출력 모듈과 아두이노 Mega보드의 인터럽트 기능 사용
예제 13.2 인터럽트로 LED 점멸시키기 LED가 100ms 마다 우측으로 쉬프트 되면서 ON 아두이노 Mega 보드 버튼 스위치를 누르면 인터럽트가 발생 LED가 멈추었다가 다시 누르면 동작 아두이노 Mega 보드 디지털입출력 핀 2번을 Switch 모듈의 BT0에 연결 디지털입출력 핀의 22, 24, 26, 28, 30, 32, 34, 36을 LED 모듈 LED0~LED0에 연결 Mega 보드 디지털입출력 핀 2 22 24 26 28 30 32 34 36 연결 모듈 BT0 LED0 LED1 LED2 LED3 LED4 LED5 LED6 LED7 SWITCH모듈 LED 모듈
Mega 보드의 인터럽트 발생 회로
예제 13.2의 주요개념 아두이노 Mega 보드의 디지털입출력 핀 2번은 외부 인터럽트 Int0로 사용 외부 인터럽트를 사용하려면 attachInterrupt(interrupt번호, function, mode) 함수 이용하여 인터럽트 설정 "interrupt번호" 부분은 2번 핀 입력을 인터럽트로 사용하기 위하여 "0" 입력 "mode" 부분은 인터럽트의 발생조건 입력 "function"부분은 핀 2번의 외부 입력으로 인하여 인터럽트 발생하였을 때 호출할 함수이름 입력 호출되는 함수 안에 인터럽트 요청에 의하여 수행할 동작을 작성
예제 13.2의 스케치1 byte LED[8] = {22,24,26,28,30,32,34,36}; byte LED_Data = 0x01; volatile byte Time_STOP = 0; LED 모듈 연결 핀을 배열로 선언 LED 모듈에 출력할 초기값 void setup() { byte i; for(i=0; i<8; i++) pinMode(LED[i], OUTPUT); attachInterrupt(0, toggle, RISING); } 인터럽트 서비스 루틴 선언, 인터럽트 0(Pin 2) void LED_display(byte data) { for(i=0; i<8; i++) digitalWrite(LED[i], bitRead(data, i)); LED를 한 bit씩 ON 시키는 함수 void toggle() { if(Time_STOP == 0) Time_STOP = 1; else Time_STOP = 0; 외부 인터럽트가 발생하면 호출될 함수
예제 13.2의 스케치2 void loop() { LED_display(LED_Data); if(Time_STOP == 0) { if(LED_Data == 0x80) LED_Data = 0x01; else LED_Data <<= 1; } Time_STOP가 ‘0’ 이면 on될 LED를 우측으로 쉬프트 delay(100); 0.1초 시간지연
예제 13.3 인터럽트로 스톱워치 만들기 Mega 보드의 디지털입출력과 외부 인터럽트 핀 2개를 출력과 입력으로 선언하고 이 핀들을 스위치 모듈과 Array-FND 모듈에 연결하여 스톱워치를 만들기 일정 시간마다 클럭에 의해 FND에 숫자와 문자가 디스플레이 스위치를 누르면 FND 디스플레이가 초기화 다른 스위치를 누르면 잠시 멈추었다가 다시 이어서 동작 인터럽트 Int0와 Int1 사용 Int0으로 스톱워치의 Stop/Resume 기능 구현 Int1으로 스톱워치의 리셋 기능 구현
스위치 모듈과 Array-FND 모듈
Array FND 모듈 스톱워치 Mega 보드 디지털입출력 핀 2 3 22 24 26 28 30 32 34 36 38 40 42 44 연결 모듈 BT0 BT1 A B C D E F G H C0 C1 C2 C3 SWITCH모듈 Array-FND 모듈
예제 13.3의 주요개념 Array-FND 모듈에서 4개 FND에 "1234"의 숫자 표시 방법 FND 모듈의 데이터 값을 "00000110"로 주어 "1"를 표시하는 값을 주고 com1에 "0"을, 그리고 나머지 com2~4는 "1"의 값을 주면 첫째 7-Segment에만 1 표시 다음으로 데이터에 "01011011"을 주어 "2"의 값을 주고 com2에 "0"과 com1, com3~4에 "1"을 주면 둘째 7-Segment에 2가 표시 이런 순서로 4까지의 숫자를 표시하고 다시 처음으로 돌아가 위의 내용을 반복 약 1m 초 이상의 주기로 반복하면 잔상효과에 의해 "1234"의 숫자가 동시에 표시되는 것처럼 표현 하드웨어적으로 필요한 제어 핀의 수 감소
Arduino 모듈 DIGITAL 핀의 22, 24, 26, 28, 30, 32, 34, 36을 Array FND 모듈의 A~H까지 연결 DIGITAL 핀의 38, 40, 42, 44는 4핀 케이블로 Array FND 모듈의 C0~C3 포트에 연결 Mega 보드 모듈의 인터럽트핀과 Switch 모듈의 버튼 스위치부 신호선 포트에 연결 Mega 보드 모듈의 2번핀과 3번핀을 Switch 모듈의 BT0 및 BT1에 연결
예제 13.3의 스케치1 byte FND[8] = {22, 24, 26, 28, 30, 32, 34, 36}; 세그먼트의 a~g와 dot 핀 지정 byte FND_CON[4] = {38, 40, 42, 44}; 4개의 FND 선택 핀 지정 byte FND_DATA_TBL[ ]={0x3F, 0X06, 0X5B, 0X4F, 0X66, 0X6D, 0X7C, 0X07, 0X7F, 0X67, 0X77, 0X7C, 0X39, 0X5E, 0X79, 0X71, 0X08, 0X80}; 0~9,A~B,_,dot 표현 데이터 volatile byte time_10ms=0, time_100ms=0; volatile byte time_1s=0, time_10s=0; volatile byte Time_STOP = 0; 스톱워치 구현에 사용하는 변수 void setup() { byte z; for(z=0; z<8; z++) pinMode(FND[z], OUTPUT); for(z=0; z<4; z++) pinMode(FND_CON[z], OUTPUT); attachInterrupt(0, blink1, RISING); attachInterrupt(1, blink2, RISING); Int0 => pin 2 Int1 => pin 3 }
예제 13.3의 스케치2 void FND_display(byte data) { byte z; for(z=0; z<8; z++) digitalWrite(FND[z], bitRead(data,z)); } FND_DATA_TBL 배열값을 ArrayFND에 표현하는 함수 void FND_control(byte data) { for(z=0; z<4; z++) { if(z == data) digitalWrite(FND_CON[z], LOW); else digitalWrite(FND_CON[z], HIGH); ArrayFND 중 출력할 FND를 선택하는 함수 void loop() { FND_control(0); FND_display(FND_DATA_TBL[time_10s]); delay(2); C0선택 왼쪽에서 첫번째 FND 선택 2ms 대기 FND_control(1); FND_display(FND_DATA_TBL[time_1s]|0x80); C1선택 왼쪽에서 2번째 FND 선택
예제 13.3의 스케치3 FND_control(2); FND_display(FND_DATA_TBL[time_100ms]); delay(3); C2선택 왼쪽에서 3번째 FND 선택 3ms 대기 FND_control(3); FND_display(FND_DATA_TBL[time_10ms]); C3선택 왼쪽에서 4번째 FND 선택 if(Time_STOP==1) return; time_10ms++; if(time_10ms == 10) { time_10ms = 0; time_100ms++ ; } 인터럽트에 의한 Stop/Resume 처리 여기까지 사용된 딜레이 함수가 약 10ms, time_10ms는 10ms마다 증가됨. if(time_100ms == 10) { time_100ms = 0; time_1s++ ;
예제 13.3의 스케치4 if(time_1s == 10) { time_1s = 0; time_10s++ ; } void blink1() { if(Time_STOP == 0) Time_STOP = 1; else Time_STOP = 0; void blink2() { time_10ms=0; time_100ms=0; time_1s=0; time_10s=0;
연습과제 인터럽트 기능을 이용하여 10분을 측정할 수 있는 스톱워치에서 랩타임 기능을 추가하여 만드시오. 가변저항의 값의 변화가 일정 값을 넘으면 인터럽트가 발생하여 경보가 울리도록 하도록 만드시오. 일정온도 이상이 되면 인터럽트가 발생하여 경보가 울리도록 하도록 만드시오. CDS 값을 읽어 주변의 밝기가 일정 값 이하이면 인터럽트가 발생하여 LED를 점등하도록 만드시오.