// 직렬 포트를 이용한 두더지 잡기 게임
#include "header/io.h" // 직접 만든 헤더파일
#define LED_DDR DDRF
#define LED_OUT PORTF
#define KEY_IN PINC
#define FND_DDR DDRE
#define FND_OUT PORTE
//================================================================//
// 인터럽트 & 통신 속도 설정 //
//================================================================//
#define CPU_CLOCK 16000000 // MCU의 속도
#define TICKS_PER_SEC 1000
#define PRESCALER 128
#define BAUD_RATE 4800 // 통신 속도
#define BAUD_RATE_L (CPU_CLOCK/(16l*BAUD_RATE))-1
#define BAUD_RATE_H ((CPU_CLOCK/(16l*BAUD_RATE))-1)>>8
//================================================================//
// 전역 변수 설정 //
//================================================================//
volatile unsigned int g_elapsed_time; // 시간변수
unsigned char stron[]="\r\n<<<<<<<<<<<<< Power ON >>>>>>>>>>>>\r\n";
unsigned char strnosw[]="[Did not PUSH switch!]\r\n";
unsigned char endscore[]="My End Game Score : [";
unsigned char endstage[]="]Stage ";
unsigned char strnum[]=".Games : ";
unsigned char strclear[]="**** Congratulates. Next Game. ****\r\n";
unsigned char fnd=0;
unsigned char key_value=0;
unsigned char LED_Match=0xff;
unsigned char KEY_Match=0xff;
unsigned char count;
unsigned int delay_ms;
char stage=1;
char key=0;
char one=0;
char ten=0;
//================================================================//
// 함수 원형 설정 //
//================================================================//
void init_PORT(void); // 포트 초기화
void init_TIMER(int timers); // Timer Counter 설정
void init_TC0(void); // Timer0 초기화
void init_USART1(void); // 직렬 통신 포트 1번 설정
void GAME_SET(char set); // 게임 시작 / 종료 문장
void GAME_COUNT(void); // 게임 카운터
char bit_match(char cnum); // 비트 검사
void sleep(unsigned int elapsed_time); // sleep함수
void delay(unsigned int speed); // SW입력 대기
void SW_loop(void); // SW 무한 루프
void uart_send_byte(unsigned char byte);// 한 문자 전송
void uart_send_string(unsigned char *str, unsigned char len); // 문자열 전송
//================================================================//
// 메인 프로그램 //
//================================================================//
int main(void)
{
/* 변수 설정 */
char score=0;
char score1=0;
unsigned char led=1;
/* 사용 설정 초기화 */
SREG = SREG|(1<<7); // 전체 인터럽트 활성화
init_PORT(); // 포트 초기화
init_TC0(); // Timer0 초기화
init_TIMER(OCIE0); // 타이머 설정
OCR0 = 0x7D; // 비교매치 인터럽트 비교값 설정
sei(); // 인터럽트 활성화 함수
init_USART1(); // 직렬 통신 포트 1번 설정
/****************************************/
/* 프로그램 작성 시작 */
/****************************************/
/* 두더지 게임 시작 */
uart_send_string(stron, sizeof(stron)); // Power on 전송
GAME_SET(1); // 시작전 대기 & 5초 카운터
while(1) // 무한 루프
{
score=0x00;
score1=0x00;
for(count=0; count<25; count++) // 25번 두더지 생성(LED On/off)
{
key=5;
fnd=0;
one+=1;
if(9<one)
{
one=0;
ten+=1;
}
LED_OUT = ~(led<<rand()%8); // 두더지(LED) 랜덤 위치 생성
delay(delay_ms); // 1초간 지연하면서 스위치 입력 대기
if((2 != fnd) && (3 != fnd))// SW를 누르지 않을 경우 전송
{
SW_loop();
uart_send_string(strnosw, sizeof(strnosw));
}
if(2==fnd) // 두더지를 잡으면 점수 5점씩 올림
{
score += 5;
if(score==0x0a) // FND가 10점이되면 실행
{
score=0x00;
score1+=0x10;
}
}
if(score1>=0xa0||10==fnd) // 7+8번SW or 점수가 100점이 되면 FND,LED on/off 6회반복
{
LED_OUT=0x00;
FND_OUT=0x00;
sleep(500);
for(count=0; 6>=count; count++)
{
LED_OUT=~LED_OUT;
FND_OUT=~FND_OUT;
sleep(200);
}
sleep(2000);
FND_OUT=0;
stage++;
break; // on/off 6회 반복 끝나면 두더지 생성 금지!
}
FND_OUT = score+score1; // 점수 표시
LED_OUT = 0xff; // 두더지 숨기(LED off)
sleep(1000); // 1초 지연
}
if((25<=count)||(100>=delay_ms)) // 두더지(LED)가 25번 생성안되면 게임 종료(100점미만)
{
uart_send_string(endscore, sizeof(endscore));
uart_send_byte(stage+48);
uart_send_string(endstage, sizeof(endstage));
uart_send_byte((score1>>4)+48);
uart_send_byte(score+48);
GAME_SET(0); // 게임 종료 메시지 전송!!
GAME_SET(1); // 게임 대기
}
uart_send_string(strclear, sizeof(strclear)); // 축하 메시지 전송
delay_ms=delay_ms-200; // 100점이면 게임 계속 실행(속도 점점 빨라짐)
}
return 1;
}
//================================================================//
// 여 러 함 수 들 모 아 놓 은 곳 //
//================================================================//
/* 게임 스타트 & 일시정지 함수 */
void GAME_SET(char set)
{
key=0;
fnd=0;
one=0;
ten=0;
LED_OUT=0xff;
delay_ms=1000;
if(set == 1)
{
while(1) // 난수 함수 시작점을 다르게하기 위한 무한 루프
{
for(count=0; 8>count; count++)
{
LED_OUT=~(1<<count);
delay(200);
srand((unsigned int)g_elapsed_time); // 난수 발생 함수
if(5==fnd) // 아무 스위치가 눌려지면 두더지 게임 시작
{
for(count=0; 8>=count; count++) // 시작전 LED 8번 루프
{
LED_OUT=~(1<<count);
sleep(200);
}
LED_OUT=0x00;
FND_OUT=0x00;
for(count=5; 1<=count; count--) // 게임 시작 카운트 5~0
{
LED_OUT=0xff;
sleep(500);
LED_OUT=0x00;
FND_OUT=count+(count<<4);
sleep(500);
}
LED_OUT=0xff;
FND_OUT=0x00;
sleep(2000); // 게임 시작전 2초 지연
break; // 게임 시작을 위해 무한루프 브레이크
}
}
if(5==fnd) // 스위치값 초기화
{
fnd=0;
break;
}
}
unsigned char strs[] = "******** [";
uart_send_string(strs, sizeof(strs));
uart_send_byte(stage+48);
unsigned char strst[] = "]Stage Game Start *******\r\n";
uart_send_string(strst, sizeof(strst));
}
else
{
unsigned char str1[] = "\r\n************ Game Over ***********\r\n";
uart_send_string(str1, sizeof(str1));
}
asm("NOP");
}
/* 스위치 입력 대기 딜레이 */
void delay(unsigned int speed)
{
unsigned char str1[]="[LED : ";
unsigned char str2[]="]_[Switch : ";
unsigned char str3[]="] OK\r\n";
unsigned char str4[]="] Fail\r\n";
unsigned char keys;
unsigned char leds;
g_elapsed_time=0;
while(g_elapsed_time<speed)
{
LED_Match = LED_OUT&LED_Match;
KEY_Match = KEY_IN&KEY_Match;
if((key==0) && (0xff != KEY_Match)) // 아무키 누르면 시작
{
fnd=5; // fnd변수에 5대입
break;
}
if((key==5)&&(LED_Match == KEY_Match)) // LED와 스위치가 같으면 실행
{
leds=bit_match(~LED_Match);
SW_loop(); // 스위치 땔때까지 대기
if(fnd==10) // 7+8번 SW 눌러지면 브레이크
{
break;
}
fnd=2; // fnd변수에 2대입
uart_send_string(str1, sizeof(str1));
uart_send_byte((leds)+49);
uart_send_string(str2, sizeof(str2));
uart_send_byte((leds)+49);
uart_send_string(str3, sizeof(str3));
sleep(20);
break;
}
else if((key==5)&&(LED_Match != KEY_Match)&&(0xff != KEY_Match))
{
leds=bit_match(~LED_Match);
keys=bit_match(~KEY_Match);
SW_loop(); // 스위치 땔때까지 대기
if(fnd==10) // 7+8번 SW 눌러지면 브레이크
{
break;
}
fnd=3; // fnd변수에 3대입
uart_send_string(str1, sizeof(str1));
uart_send_byte((leds)+49);
uart_send_string(str2, sizeof(str2));
uart_send_byte((keys)+49);
uart_send_string(str4, sizeof(str4));
sleep(20);
break;
}
}
}
/* 스위치 누르고 있을 경우 무한 루프 */
void SW_loop(void)
{
while(1)
{
if(0xff == KEY_IN) // 무한 루프 브레이크
{
uart_send_byte(ten+48); // 10의 자리 통신 전송
uart_send_byte(one+48); // 1의 자리 통신 전송
uart_send_string(strnum, sizeof(strnum)); // 게임 글자 통신 전송
break;
}
if(KEY_IN == 0x3f) // 7+8번 SW : 다음탄으로 넘김
{
fnd=10; // fnd변수에 10대입
break;
}
}
}
/* bit 검사 */
char bit_match(char cnum)
{
char cnt;
char temp;
for(cnt=0; 7>cnt; cnt++)
{
temp=(cnum&(1<<cnt))/(1<<cnt);
if(1==temp)
{
return cnt;
}
}
return cnt;
}
/* 직렬 포트 통신 송신 함수 */
void uart_send_byte(unsigned char byte)
{
while (!(UCSR1A&(1<<UDRE))); // 전송 버퍼가 비었을 때 까지 대기
UDR1 = byte; // 문자 1개씩 전송
}
/* 전체 문자를 전송하기 위한 함수 */
void uart_send_string(unsigned char *str, unsigned char len)
{
int i;
for(i=0; i<len; i++)
{
if(! str[i]) // 문자열 전송을 끝냄
{
break;
}
uart_send_byte(*(str+i));
}
}
/* 직렬 통신 포트 1번 설정 함수 */
void init_USART1(void)
{
UBRR1L = (unsigned char)BAUD_RATE_L;
UBRR1H = (unsigned char)BAUD_RATE_H;
UCSR1C = (0<<UPM1)|(0<<UPM0)|(0<<USBS)|(1<<UCSZ1)|(1<<UCSZ0);
UCSR1B = (1<<TXEN)|(1<<RXEN)|(0<<UCSZ2);
}
/* LED포트 초기화 설정 함수 */
void init_PORT(void)
{
LED_DDR = 0xFF; // PORTF 출력 설정
LED_OUT = 0xFF; // PORTF 초기화
FND_DDR = 0xFF; // PORTE 츨력 설정
FND_OUT = 0x00; // PORTE 초기
DDRC = 0x00; // PORTC 입력 설정 (SW)
}
/* 타이머 설정 함수 */
void init_TIMER(int timers)
{
TIMSK=(1<<timers);
}
/* Timer0 초기화 설정 함수 */
void init_TC0(void)
{
//TCCR0 = 0x0D; // TCCR0 CTC모드 설정 / 분주비 설정
TCCR0 = 1<<2|0<<1|0<<0; // 이런식으로 설정도 가능함
}
/* 딜레이 함수 */
void sleep(unsigned int elapsed_time)
{
g_elapsed_time=0;
while(g_elapsed_time<elapsed_time)
{
}
}
/* 시그널 함수 */
/* 비교매치 인터럽트 */
void __vector_15(void)
{
g_elapsed_time++;
LED_Match=0xff;
KEY_Match=0xff;
}
#include "header/io.h" // 직접 만든 헤더파일
#define LED_DDR DDRF
#define LED_OUT PORTF
#define KEY_IN PINC
#define FND_DDR DDRE
#define FND_OUT PORTE
//================================================================//
// 인터럽트 & 통신 속도 설정 //
//================================================================//
#define CPU_CLOCK 16000000 // MCU의 속도
#define TICKS_PER_SEC 1000
#define PRESCALER 128
#define BAUD_RATE 4800 // 통신 속도
#define BAUD_RATE_L (CPU_CLOCK/(16l*BAUD_RATE))-1
#define BAUD_RATE_H ((CPU_CLOCK/(16l*BAUD_RATE))-1)>>8
//================================================================//
// 전역 변수 설정 //
//================================================================//
volatile unsigned int g_elapsed_time; // 시간변수
unsigned char stron[]="\r\n<<<<<<<<<<<<< Power ON >>>>>>>>>>>>\r\n";
unsigned char strnosw[]="[Did not PUSH switch!]\r\n";
unsigned char endscore[]="My End Game Score : [";
unsigned char endstage[]="]Stage ";
unsigned char strnum[]=".Games : ";
unsigned char strclear[]="**** Congratulates. Next Game. ****\r\n";
unsigned char fnd=0;
unsigned char key_value=0;
unsigned char LED_Match=0xff;
unsigned char KEY_Match=0xff;
unsigned char count;
unsigned int delay_ms;
char stage=1;
char key=0;
char one=0;
char ten=0;
//================================================================//
// 함수 원형 설정 //
//================================================================//
void init_PORT(void); // 포트 초기화
void init_TIMER(int timers); // Timer Counter 설정
void init_TC0(void); // Timer0 초기화
void init_USART1(void); // 직렬 통신 포트 1번 설정
void GAME_SET(char set); // 게임 시작 / 종료 문장
void GAME_COUNT(void); // 게임 카운터
char bit_match(char cnum); // 비트 검사
void sleep(unsigned int elapsed_time); // sleep함수
void delay(unsigned int speed); // SW입력 대기
void SW_loop(void); // SW 무한 루프
void uart_send_byte(unsigned char byte);// 한 문자 전송
void uart_send_string(unsigned char *str, unsigned char len); // 문자열 전송
//================================================================//
// 메인 프로그램 //
//================================================================//
int main(void)
{
/* 변수 설정 */
char score=0;
char score1=0;
unsigned char led=1;
/* 사용 설정 초기화 */
SREG = SREG|(1<<7); // 전체 인터럽트 활성화
init_PORT(); // 포트 초기화
init_TC0(); // Timer0 초기화
init_TIMER(OCIE0); // 타이머 설정
OCR0 = 0x7D; // 비교매치 인터럽트 비교값 설정
sei(); // 인터럽트 활성화 함수
init_USART1(); // 직렬 통신 포트 1번 설정
/****************************************/
/* 프로그램 작성 시작 */
/****************************************/
/* 두더지 게임 시작 */
uart_send_string(stron, sizeof(stron)); // Power on 전송
GAME_SET(1); // 시작전 대기 & 5초 카운터
while(1) // 무한 루프
{
score=0x00;
score1=0x00;
for(count=0; count<25; count++) // 25번 두더지 생성(LED On/off)
{
key=5;
fnd=0;
one+=1;
if(9<one)
{
one=0;
ten+=1;
}
LED_OUT = ~(led<<rand()%8); // 두더지(LED) 랜덤 위치 생성
delay(delay_ms); // 1초간 지연하면서 스위치 입력 대기
if((2 != fnd) && (3 != fnd))// SW를 누르지 않을 경우 전송
{
SW_loop();
uart_send_string(strnosw, sizeof(strnosw));
}
if(2==fnd) // 두더지를 잡으면 점수 5점씩 올림
{
score += 5;
if(score==0x0a) // FND가 10점이되면 실행
{
score=0x00;
score1+=0x10;
}
}
if(score1>=0xa0||10==fnd) // 7+8번SW or 점수가 100점이 되면 FND,LED on/off 6회반복
{
LED_OUT=0x00;
FND_OUT=0x00;
sleep(500);
for(count=0; 6>=count; count++)
{
LED_OUT=~LED_OUT;
FND_OUT=~FND_OUT;
sleep(200);
}
sleep(2000);
FND_OUT=0;
stage++;
break; // on/off 6회 반복 끝나면 두더지 생성 금지!
}
FND_OUT = score+score1; // 점수 표시
LED_OUT = 0xff; // 두더지 숨기(LED off)
sleep(1000); // 1초 지연
}
if((25<=count)||(100>=delay_ms)) // 두더지(LED)가 25번 생성안되면 게임 종료(100점미만)
{
uart_send_string(endscore, sizeof(endscore));
uart_send_byte(stage+48);
uart_send_string(endstage, sizeof(endstage));
uart_send_byte((score1>>4)+48);
uart_send_byte(score+48);
GAME_SET(0); // 게임 종료 메시지 전송!!
GAME_SET(1); // 게임 대기
}
uart_send_string(strclear, sizeof(strclear)); // 축하 메시지 전송
delay_ms=delay_ms-200; // 100점이면 게임 계속 실행(속도 점점 빨라짐)
}
return 1;
}
//================================================================//
// 여 러 함 수 들 모 아 놓 은 곳 //
//================================================================//
/* 게임 스타트 & 일시정지 함수 */
void GAME_SET(char set)
{
key=0;
fnd=0;
one=0;
ten=0;
LED_OUT=0xff;
delay_ms=1000;
if(set == 1)
{
while(1) // 난수 함수 시작점을 다르게하기 위한 무한 루프
{
for(count=0; 8>count; count++)
{
LED_OUT=~(1<<count);
delay(200);
srand((unsigned int)g_elapsed_time); // 난수 발생 함수
if(5==fnd) // 아무 스위치가 눌려지면 두더지 게임 시작
{
for(count=0; 8>=count; count++) // 시작전 LED 8번 루프
{
LED_OUT=~(1<<count);
sleep(200);
}
LED_OUT=0x00;
FND_OUT=0x00;
for(count=5; 1<=count; count--) // 게임 시작 카운트 5~0
{
LED_OUT=0xff;
sleep(500);
LED_OUT=0x00;
FND_OUT=count+(count<<4);
sleep(500);
}
LED_OUT=0xff;
FND_OUT=0x00;
sleep(2000); // 게임 시작전 2초 지연
break; // 게임 시작을 위해 무한루프 브레이크
}
}
if(5==fnd) // 스위치값 초기화
{
fnd=0;
break;
}
}
unsigned char strs[] = "******** [";
uart_send_string(strs, sizeof(strs));
uart_send_byte(stage+48);
unsigned char strst[] = "]Stage Game Start *******\r\n";
uart_send_string(strst, sizeof(strst));
}
else
{
unsigned char str1[] = "\r\n************ Game Over ***********\r\n";
uart_send_string(str1, sizeof(str1));
}
asm("NOP");
}
/* 스위치 입력 대기 딜레이 */
void delay(unsigned int speed)
{
unsigned char str1[]="[LED : ";
unsigned char str2[]="]_[Switch : ";
unsigned char str3[]="] OK\r\n";
unsigned char str4[]="] Fail\r\n";
unsigned char keys;
unsigned char leds;
g_elapsed_time=0;
while(g_elapsed_time<speed)
{
LED_Match = LED_OUT&LED_Match;
KEY_Match = KEY_IN&KEY_Match;
if((key==0) && (0xff != KEY_Match)) // 아무키 누르면 시작
{
fnd=5; // fnd변수에 5대입
break;
}
if((key==5)&&(LED_Match == KEY_Match)) // LED와 스위치가 같으면 실행
{
leds=bit_match(~LED_Match);
SW_loop(); // 스위치 땔때까지 대기
if(fnd==10) // 7+8번 SW 눌러지면 브레이크
{
break;
}
fnd=2; // fnd변수에 2대입
uart_send_string(str1, sizeof(str1));
uart_send_byte((leds)+49);
uart_send_string(str2, sizeof(str2));
uart_send_byte((leds)+49);
uart_send_string(str3, sizeof(str3));
sleep(20);
break;
}
else if((key==5)&&(LED_Match != KEY_Match)&&(0xff != KEY_Match))
{
leds=bit_match(~LED_Match);
keys=bit_match(~KEY_Match);
SW_loop(); // 스위치 땔때까지 대기
if(fnd==10) // 7+8번 SW 눌러지면 브레이크
{
break;
}
fnd=3; // fnd변수에 3대입
uart_send_string(str1, sizeof(str1));
uart_send_byte((leds)+49);
uart_send_string(str2, sizeof(str2));
uart_send_byte((keys)+49);
uart_send_string(str4, sizeof(str4));
sleep(20);
break;
}
}
}
/* 스위치 누르고 있을 경우 무한 루프 */
void SW_loop(void)
{
while(1)
{
if(0xff == KEY_IN) // 무한 루프 브레이크
{
uart_send_byte(ten+48); // 10의 자리 통신 전송
uart_send_byte(one+48); // 1의 자리 통신 전송
uart_send_string(strnum, sizeof(strnum)); // 게임 글자 통신 전송
break;
}
if(KEY_IN == 0x3f) // 7+8번 SW : 다음탄으로 넘김
{
fnd=10; // fnd변수에 10대입
break;
}
}
}
/* bit 검사 */
char bit_match(char cnum)
{
char cnt;
char temp;
for(cnt=0; 7>cnt; cnt++)
{
temp=(cnum&(1<<cnt))/(1<<cnt);
if(1==temp)
{
return cnt;
}
}
return cnt;
}
/* 직렬 포트 통신 송신 함수 */
void uart_send_byte(unsigned char byte)
{
while (!(UCSR1A&(1<<UDRE))); // 전송 버퍼가 비었을 때 까지 대기
UDR1 = byte; // 문자 1개씩 전송
}
/* 전체 문자를 전송하기 위한 함수 */
void uart_send_string(unsigned char *str, unsigned char len)
{
int i;
for(i=0; i<len; i++)
{
if(! str[i]) // 문자열 전송을 끝냄
{
break;
}
uart_send_byte(*(str+i));
}
}
/* 직렬 통신 포트 1번 설정 함수 */
void init_USART1(void)
{
UBRR1L = (unsigned char)BAUD_RATE_L;
UBRR1H = (unsigned char)BAUD_RATE_H;
UCSR1C = (0<<UPM1)|(0<<UPM0)|(0<<USBS)|(1<<UCSZ1)|(1<<UCSZ0);
UCSR1B = (1<<TXEN)|(1<<RXEN)|(0<<UCSZ2);
}
/* LED포트 초기화 설정 함수 */
void init_PORT(void)
{
LED_DDR = 0xFF; // PORTF 출력 설정
LED_OUT = 0xFF; // PORTF 초기화
FND_DDR = 0xFF; // PORTE 츨력 설정
FND_OUT = 0x00; // PORTE 초기
DDRC = 0x00; // PORTC 입력 설정 (SW)
}
/* 타이머 설정 함수 */
void init_TIMER(int timers)
{
TIMSK=(1<<timers);
}
/* Timer0 초기화 설정 함수 */
void init_TC0(void)
{
//TCCR0 = 0x0D; // TCCR0 CTC모드 설정 / 분주비 설정
TCCR0 = 1<<2|0<<1|0<<0; // 이런식으로 설정도 가능함
}
/* 딜레이 함수 */
void sleep(unsigned int elapsed_time)
{
g_elapsed_time=0;
while(g_elapsed_time<elapsed_time)
{
}
}
/* 시그널 함수 */
/* 비교매치 인터럽트 */
void __vector_15(void)
{
g_elapsed_time++;
LED_Match=0xff;
KEY_Match=0xff;
}