외부 인터럽트



인터럽트란?


 MCU에서 입력을 받아들이는 방법에는 두가지가 있는데, 하나는 사용자가 명령어를 사용하여 입력핀의 값을 계속 또는 주기적으로 읽어서 변화를 알아내는 폴링(polling)방식이고, 다른 하나는 MCU 자체가 하드웨어적으로 그 변화를 체크하여 변화 시에만 일정한 동작을 하는 인터럽트(interrupt)방식이다.  


아래 그림은 인터럽트의 개념도를 그림으로 나타냈다.

인터럽트는 외부 또는 내부에서 인터럽트 소스(즉 원인)에 의하여 MCU에게 인터럽트신호가 전달되면 MCU는 미리 정해진 작업(인터럽트 서비스 루틴)을 실행한다. 인터럽트가 발생했을때 MCU는 지금까지 하던 프로그램을 일단 중지시키고 사용자에의해 정해진 인터럽트 서비스 루틴을 실행하게 되며, 그 루틴의 실행이 종료되면 다시 원래 실행하던 프로그램으로 돌아가 하던일을 계속하게 된다.

그리고 인터럽트 벡터 테이블이라는것이 존재한다.

인터럽트 벡터 테이블은 각각의 인터럽트 핸들러의 시작 번지를  모아 놓은 것이라고 정의한다.



그렇다면 폴링방식과 인터럽트방식의 차이점은 무엇일까?

폴링 방식에서는 입력핀의 변화를 확인하기위하여 입력핀의 값을 계속 읽을 필요가 있지만 인터럽트 방식에서는 하드웨어적인 변화가 있으면 자동적으로MCU에게 신호가 전달되는 방식이기 때문에 직접 입력핀의 값을 읽을 필요가 없다. 또한 폴링방식은 모든 경우의 입력 또는 값의 변화에 대응하여 처리가 가능하지만 인터럽트 방식은 하드웨어적으로 지원되는 몇개의 입력 또는 값의 변화에만 대응처리가 가능하며 처리속도는 일반적인 경우에 인터럽트 방식이 폴링방식보다 더 빠르다.

 

다시 정리한다면

인터럽트를 발생시킬 수 있도록 만들어진 것(외부 입력 핀, 타이머, 시리얼 포트 등) - 인터럽트 소스(interrupt source)

인터럽트 발생시 분기장소 즉 시작위치를 기록해 놓은 특정번지들의 내용 - 인터럽트 벡터 테이블(interrupt vector table)

인터럽트가 발생 하였을 때 그 인터럽트를 처리하는 프로그램 - 인터럽트 서비스 루틴(interrupt service routine)

라고 한다.




MP3 Player in C.hwp


앞으로의 목표는 가사 파일을 파일로 불러와 읽어서 처리할것이다.

그리고 멈추는 기능도 만들수 있을것 같다.


#include 
#include 
#include 
#include 
#include  
#include 
#include  
#include 


#pragma warning(disable:4996)
#pragma comment(lib, "winmm.lib")
typedef struct _finddata_t  FILE_SEARCH;
void ls();
void cd(char *command);
void all(char* path);
void cls();
char *replaceAll(char *s, const char *olds, const char *news);
void mp3_player(); 
void command_chaeck();
void lyrics();
char temp[400][512];
char strBuffer[_MAX_PATH] = { 0 };
char *pstrBuffer = NULL;
int wav_file_cnt = 0;
int now_file_num = 0;
int play_time[] = {13,16,19,23};
char play_lyrics[500][100] = {"[나연] 모두 나를 가지고 매일 가만 안 두죠","[모모] 내가 너무 예쁘죠 나 때문에 다 힘들죠","[나연] 어딜 걷고 있어도 빨간 바닥인거죠","[사나] Red carpet 같은 기분 모두 날 쳐다 보죠 Oh"};
TCHAR file_name[512] = { 0, };
TCHAR file_set[512] = { 0, };

void main() {

	char command[100];
	const char exit[] = "exit ";
	const char cols[] = "ls ";
	const char cocd[] = "cd ";
	const char coall[] = "all";
	const char cocls[] = "cls";
	const char mp3[] = "mp3";
	char *path=NULL;

	while (1) {
		pstrBuffer = getcwd(strBuffer, _MAX_PATH);
		printf("all입력후 원하시는 절대경로를 입력해주시면 됩니다. (all C:\\) \n\n");
		printf("%s :", pstrBuffer);
		fgets(command, sizeof(command), stdin);
		if (strncmp(command, exit, 4) == 0) break;
		else if (strncmp(command, cols, 2) == 0) ls();
		else if (strncmp(command, cocd, 2) == 0) {
			if (strncmp(command, cocd, 3) == 0)	cd(command);
			else printf("cd : cd is not command!!\n");
		}
		else if (strncmp(command, coall, 3) == 0) {
	
				path = strtok(command, " ");
				while (path != NULL) {
					path = strtok(NULL, "");
					if (path != NULL) break;
				}
				path[strlen(path) - 1] = '\0';
		
			all(path);
			printf("Wav File List!!!!\n\n\n");
			for (int i = 0; i < wav_file_cnt; i++) {
				puts(temp[i]);
			}
		}
		else if (strncmp(command, cocls, 3) == 0) cls();
		else if (strncmp(command, mp3, 3) == 0) {
			if (wav_file_cnt == 0) {
				printf("all을 실행해주세요\n");
			}
			else {
				mp3_player();
			}
		}
		
	}


}
void ls() {
	long h_file;
	FILE_SEARCH file_search;
	char search_Path[100] = ".\\*.*";
	char txt[] = "";
	char *test = NULL;
	int i = 0;
	if ((h_file = _findfirst(search_Path, &file_search)) == -1L) {
		printf("No files in current directory!\n");
		exit(1);
	}
	do {
		if (strstr(file_search.name, txt)) {
			//strcpy(test, file_search.name);
			//i = isFileOrDir(file_search.name);
			if (file_search.attrib == 16) {
				SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 4);
				puts(file_search.name);
				SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 7);
			}
			else {
				puts(file_search.name);
			}
			
		}

	} while (_findnext(h_file, &file_search) == 0);
}
void cd(char *command) {
	char cut[] = " ";
	char end[] = "";
	char new_command[100];
	char cd_command[100];
	char *command_cut = NULL;

	strcpy(new_command, command);
	new_command[strlen(new_command) - 1] = '\0';
	command_cut = strtok(command, cut);

	while (command_cut != NULL) {
		command_cut = strtok(NULL, end);
		if (command_cut != NULL) break;
	}

	pstrBuffer = getcwd(strBuffer, _MAX_PATH);
	strcpy(cd_command, pstrBuffer);
	strcat(cd_command, "\\");
	strcat(cd_command, command_cut);

	command_cut[strlen(command_cut) - 1] = '\0';


	char *ch = replaceAll(cd_command, "\\", "\\\\");
	strcpy(cd_command, ch);



	int error_check = chdir((char*)cd_command);
	if (error_check == -1) {
		printf("%s : %s is not a folder or .\n", new_command, command_cut);
		return;
	}
}
void all(char *path) {
	long h_file;
	FILE_SEARCH file_search;

	
	char search_Path[512];
	strcpy(search_Path, path);

	char search_command[512];
	strcpy(search_command, search_Path);
	strcat(search_command, "*.*");
	
	char temp_[512];
	char old_Path[512];
	strcpy(old_Path, search_Path);

	char txt[] = "";
	char *test = NULL;
	int i = 0;

 	if ((h_file = _findfirst(search_command, &file_search)) == -1L) {
		//printf("No files in current directory!\n");
		return;
	}
	do {

		if (strstr(file_search.name, txt)) {
			if (strstr(file_search.name, ".wav")) {
				strcpy(temp_, search_Path);
				strcat(temp_, file_search.name);
				strcpy(temp[wav_file_cnt],temp_);
				wav_file_cnt++;
			}
			if ((strcmp(file_search.name, ".") == 0) || (strcmp(file_search.name, "..") == 0)) {
				continue;
			}
			else if (file_search.attrib == 16 || file_search.attrib == 17) {

				SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 4);
				puts(file_search.name);
				SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 7);

				int error_check = chdir(search_Path);
				if (error_check == -1) {
					printf("error\n");
					return;
				}

				strcat(search_Path, file_search.name);
				strcat(search_Path, "\\");
				all(search_Path);
 				strcpy(search_Path, old_Path);
			}
			else {
				puts(file_search.name);
			}
			
		}

	} while (_findnext(h_file, &file_search) == 0);
	int error_check = chdir(pstrBuffer);
	if (error_check == -1) {
		printf("error\n");
		return;
	}
	
}
void cls() {
	system("cls");
}
char *replaceAll(char *s, const char *olds, const char *news) {
	char *result;
	char *sr;
	size_t i, count = 0;
	size_t oldlen = strlen(olds); if (oldlen < 1) return s;
	size_t newlen = strlen(news);

	if (newlen != oldlen) {
		for (i = 0; s[i] != '\0';) {
			if (memcmp(&s[i], olds, oldlen) == 0) count++, i += oldlen;
			else i++;
		}
	}
	else i = strlen(s);


	result = (char *)malloc(i + 1 + count * (newlen - oldlen));
	if (result == NULL) return NULL;


	sr = result;
	while (*s) {
		if (memcmp(s, olds, oldlen) == 0) {
			memcpy(sr, news, newlen);
			sr += newlen;
			s += oldlen;
		}
		else *sr++ = *s++;
	}
	*sr = '\0';
	result[strlen(result) - 1] = '\0';
	return result;
}
void command_chaeck() {
	int key_command;
	while (!kbhit());
	key_command = getch();
	do {
		key_command = getch();
	} while (key_command == 244);
	switch (key_command)
	{
	case 77: {
		now_file_num++;
		if (now_file_num == wav_file_cnt) now_file_num = wav_file_cnt - 1;
		break;
	}
	case 75: {
		if (now_file_num == 0) break;
		now_file_num--;
		break;
	}
	default:
		break;
	}


}
void mp3_player() {
	int max_size = 0; 
	while (1) {
 		MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, temp[now_file_num], strlen(temp[now_file_num]), file_name, 512);
		if (strlen(file_name) > max_size) {
			max_size = strlen(file_name);
		}
		file_name[(max_size-(max_size - strlen(temp[now_file_num])))] = '\0';
		printf("<- 이전노래, -> 다음노래 \n");
		printf("현재 실행되는 노래의 이름: %s\n", temp[now_file_num]);
		PlaySound((LPCWSTR)file_name, NULL, SND_FILENAME | SND_ASYNC | SND_LOOP);
		_beginthread(lyrics, 0, 0);
		command_chaeck();
		system("cls");
	}
}
void lyrics() {
	int time = 0;
	int now = 0;
	while (1) {
		Sleep(1000);
		time++;
		if (play_time[now] < time) {
			printf("%s\n", play_lyrics[now]);
			now++;
		}

	}
}


T E T R I S.hwp

Source.c

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include "head.h"
#pragma warning (disable:4996)


int STATUS_Y_GOAL; //GOAL 정보표시위치Y 좌표 저장 
int STATUS_Y_LEVEL; //LEVEL 정보표시위치Y 좌표 저장
int STATUS_Y_SCORE; //SCORE 정보표시위치Y 좌표 저장
typedef enum { NOCURSOR, SOLIDCURSOR, NORMALCURSOR } CURSOR_TYPE; //커서숨기는 함수에 사용되는 열거형 

int new_block_on;
int main_cpy[MAP_Y][MAP_X];
int main_org[MAP_Y][MAP_X];
int b_x = (MAP_X / 2) - 1; //블럭의 x좌표
int b_y = 0; //블럭의 y좌표
int temp[4][4];
int key = 0;
int crash_num = 0;
int game_speed = 1000;
int level=0; 
int re_line = 0;
int old_score=0;
int now_score=0;
int best_score=0;
int map_check = 0;
int block_high = 0;
int hard_down = 0;

void check_crash(int x, int y);
void key_ent();
void move_block(int key);
void map_reset();
void gotoxy(int x, int y);
void map();
char start();
void new_block();
void block_turn(int block[4][4]);
void setcursortype(CURSOR_TYPE c);
void auto_down_blcok(void *p);
void line_check();
void game_over();
void score_map();
void drop_block(void);

void main() {
	char choice;
	setcursortype(NOCURSOR);
	choice = start();
	if (choice == '1') {
		map_reset();
		_beginthread(auto_down_blcok, 0, 0);
		score_map();
		while (1) {
			key_ent();
		}
	}
	else {
		exit(1);
	}
	return;
}

//자동으로 내려가는 부분
void auto_down_blcok(void *p) {
	Sleep(1000);
	while (1) {
		if (map_check != 1 && hard_down == 0) {
			check_crash(b_x, b_y + 1);
			if (crash_num == 0) {
				move_block(DOWN);
				map();
			}
			else {
				for (int i = 0; i < 4; i++)
					for (int j = 0; j < 4; j++)
						if (main_org[b_y + i][b_x +j] == ACTIVE_BLOCK) main_org[b_y + i][b_x+j] = INACTIVE_BLOCK;
				new_block();
			}
			Sleep(game_speed);
		}
		game_over();
	}
}

//커서 없애는 함수
void setcursortype(CURSOR_TYPE c) { //커서숨기는 함수 
	CONSOLE_CURSOR_INFO CurInfo;

	switch (c) {
	case NOCURSOR:
		CurInfo.dwSize = 1;
		CurInfo.bVisible = FALSE;
		break;
	case SOLIDCURSOR:
		CurInfo.dwSize = 100;
		CurInfo.bVisible = TRUE;
		break;
	case NORMALCURSOR:
		CurInfo.dwSize = 20;
		CurInfo.bVisible = TRUE;
		break;
	}
	SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &CurInfo);
}

//키 입력받는 함수
void key_ent() {
	key = 0;
	if (kbhit()) {

		key = getch();

		if (key == 224) {

			do {
				key = getch();
			} while (key == 244);

			switch (key)
			{
			case DOWN: {
				check_crash(b_x, b_y + 1);
				if (crash_num == 0) move_block(DOWN);
				map();
				break;
			}
			case RIGHT: {
				check_crash(b_x + 1, b_y);
				if (crash_num == 0) move_block(RIGHT);
				map();
				break;
			}
			case LEFT: {
				check_crash(b_x - 1, b_y);
				if (crash_num == 0) move_block(LEFT);
				map();
				break;
			}
			case UP: {
				block_turn(temp);
				map();
				break;
			}
			default:
				break;
			}
		}
		else {
			switch (key)
			{
			case SPACE: {
				move_block(SPACE);
				map();
				break;
			}
			default:
				break;
			}

		}
		fflush(stdin);
	}
}

//초기화면
char start() {
	printf("                                                                           \n\n\n"); Sleep(50);
	printf("                                                ■■■                         \n"); Sleep(50);
	printf("       ■■■■■                ■■■■■    ■    ■             ■■       \n"); Sleep(50);
	printf("           ■      ■■■■          ■        ■■■      ■     ■    ■     \n"); Sleep(50);
	printf("           ■      ■                ■        ■■        ■    ■            \n"); Sleep(50);
	printf("           ■      ■■■■          ■        ■  ■      ■     ■           \n"); Sleep(50);
	printf("           ■      ■                ■        ■    ■    ■       ■■       \n"); Sleep(50);
	printf("                   ■■■■          ■        ■      ■  ■           ■     \n"); Sleep(50);
	printf("                                                           ■            ■    \n"); Sleep(50);
	printf("                                                                  ■    ■     \n"); Sleep(50);
	printf("                                                                    ■■       \n"); Sleep(50);
	printf("                             1. START                                          \n"); Sleep(50);
	printf("                             2. EXIT                                           \n"); Sleep(50);
	printf("                                                                               \n");
	char num = getch();
	system("cls");
	return num;
}

//점수출력
void score_map() {
	int y = 3;
	gotoxy(STATUS_X_ADJ, STATUS_Y_LEVEL = y); printf(" LEVEL : %5d", level);
	gotoxy(STATUS_X_ADJ, STATUS_Y_GOAL = y + 1); printf(" GOAL  : %5d", 10 - re_line);
	gotoxy(STATUS_X_ADJ, y + 2); printf("+-  N E X T  -+ ");
	gotoxy(STATUS_X_ADJ, y + 3); printf("|             | ");
	gotoxy(STATUS_X_ADJ, y + 4); printf("|             | "); //수정
	gotoxy(STATUS_X_ADJ, y + 5); printf("|             | ");
	gotoxy(STATUS_X_ADJ, y + 6); printf("|             | ");
	gotoxy(STATUS_X_ADJ, y + 7); printf("+-- -  -  - --+ ");
	gotoxy(STATUS_X_ADJ, y + 8); printf(" YOUR SCORE :");
	gotoxy(STATUS_X_ADJ, STATUS_Y_SCORE = y + 9); printf("        %6d", now_score);
	gotoxy(STATUS_X_ADJ, y + 10); printf(" LAST SCORE :");
	gotoxy(STATUS_X_ADJ, y + 11); printf("        %6d", old_score);
	gotoxy(STATUS_X_ADJ, y + 12); printf(" BEST SCORE :");
	gotoxy(STATUS_X_ADJ, y + 13); printf("        %6d", best_score);
	gotoxy(STATUS_X_ADJ, y + 15); printf("http://jmy0904.tistory.com");
}

//맵을 그려주는 함수
void map() {
	map_check = 1;
	for (int j = 1; j0) { 
				temp_++;
			}
		}
	}
	if (temp_ != 0) crash_num = 1;
	else { crash_num = 0; }
	line_check();
}

//블럭 이동함수
void move_block(int key) {
	
	switch (key)
	{
	case DOWN: { //아래
 		for (int i = 0; i < 4; i++) {
			for (int j = 0; j < 4; j++) {
				if (temp[i][j] == -2) {
					main_org[b_y + i][b_x + j] = EMPTY;
				}
			}
		}
		for (int i = 0; i < 4; i++) {
			for (int j = 0; j < 4; j++) {
				if (temp[i][j] == -2)
					main_org[b_y + i + 1][b_x + j] = ACTIVE_BLOCK; //함수로 줄이기
			}
		}
		b_y++;
		break;
	}
	case RIGHT: { //오른쪽
		for (int i = 0; i < 4; i++) {
			for (int j = 0; j < 4; j++) {
				if (temp[i][j] == -2 && temp[i][j] != WALL) {
					main_org[b_y + i][b_x + j] = EMPTY;
				}
			}
		}
		for (int i = 0; i < 4; i++) {
			for (int j = 0; j < 4; j++) {
				if (temp[i][j] == -2)
					main_org[b_y + i][b_x + j + 1] = ACTIVE_BLOCK;
			}
		}
		b_x++;
		break;
	}
	case LEFT: { //왼쪽
		for (int i = 0; i < 4; i++) {
			for (int j = 0; j < 4; j++) {
				if (temp[i][j] == -2) {
					main_org[b_y + i][b_x + j] = EMPTY;
				}
			}
		}
		for (int i = 0; i < 4; i++) {
			for (int j = 0; j < 4; j++) {
				if (temp[i][j] == -2)
					main_org[b_y + i][b_x + j - 1] = ACTIVE_BLOCK;
			}
		}
		b_x--;
		break;
	}
	case UP: { //턴
		block_turn(temp);
		break;
	}
	/*case SPACE: {
		hard_down = 1;
		drop_block();
		
	}*/
	default:
		break;
	}
	game_over();
		
}

//블럭 회전 함수
void block_turn(int block[4][4]) {
	int arr[4][4];
	int n1, n2;
	n1 = 0;

	for (int i = 0; i < 4; i++) {
		n2 = 0;
		for (int j = 3; j > -1; j--) {
			arr[n1][n2] = block[j][i];
			n2++;
		}
		n1++;
	}
	//check_crash_turn(b_x+1, b_y+1, *arr);
	if (crash_num == 0) {
		for (int i = 0; i < 4; i++) {
			for (int j = 0; j < 4; j++) {
				if (temp[i][j] == -2) {
					main_org[b_y + i][b_x + j] = EMPTY;
				}
			}
		}
		for (int i = 0; i < 4; i++)
			for (int j = 0; j < 4; j++)
				temp[i][j] = arr[i][j];
		for (int i = 0; i < 4; i++) {
			for (int j = 0; j < 4; j++) {
				if (temp[i][j] == -2)
					main_org[b_y + i][b_x + j] = ACTIVE_BLOCK;
			}
		}
	}
}

//한줄이 다 채워졌는지를 체크후 제거
void line_check() {
	int block = 0;
	for (int i = MAP_Y - 2; i > 3;) {
		block = 0;
		for (int x = 1; x < MAP_X - 1; x++)
			if (main_org[i][x]>0) block++;
		if (block == MAP_X - 2) {
			for (int k = i; k > 1; k--) { //윗줄을 한칸씩 모두 내림(윗줄이 천장이 아닌 경우에만) 
				for (int l = 1; l < MAP_X - 1; l++) {
					if (main_org[k - 1][l] != CEILLING) main_org[k][l] = main_org[k - 1][l];
					if (main_org[k - 1][l] == CEILLING) main_org[k][l] = EMPTY;
				}
			}
			if (re_line == 10) {
				level++; 
				game_speed -= 100;
				re_line = 0;
			}
			now_score += 500;
			re_line++;
			gotoxy(STATUS_X_ADJ, STATUS_Y_LEVEL); printf(" LEVEL : %5d", level);
			gotoxy(STATUS_X_ADJ, STATUS_Y_GOAL); printf(" GOAL  : %5d", 10 - re_line);
			gotoxy(STATUS_X_ADJ, STATUS_Y_SCORE); printf("        %6d", now_score);
		}
		else i--;
	}
}

//게임오버 함수
void game_over() {
	for (int i = 1; i < MAP_X - 1;i++)
		if (main_org[3][i]==INACTIVE_BLOCK) {
			system("cls");
			printf("Game_Over\n");
			exit(1);
		}
}

/*void drop_block(void) {
	while (crash_num == 0) {
		check_crash(b_x, b_y + 1);
		move_block(DOWN);
	}
	hard_down = 0;
}*/

Head.h
#pragma once

#define RIGHT 77
#define LEFT 75
#define UP 72
#define DOWN 80
#define SPACE 32
#define MAP_X 11
#define MAP_Y 23
#define MAIN_X 3
#define MAIN_Y 1

#define ACTIVE_BLOCK -2 //현재 이동중인 블럭
#define CEILLING -1 //블럭이 이동할수 있는 위치는 0이나 음의 정수로 표현
#define EMPTY 0 
#define WALL 1     //블럭이 이동할수 없는 위치는 양의 정수로 표현
#define INACTIVE_BLOCK 2
#define STATUS_X_ADJ MAIN_X+MAP_X+1 //게임정보표시 위치조정 


+ Recent posts