// 직렬 포트를 이용한 두더지 잡기 게임
#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=06>=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=08>count; count++)
        {
                LED_OUT=~(1<<count);
          delay(200);    
            srand((unsigned int)g_elapsed_time);  // 난수 발생 함수
            
                if(5==fnd)  // 아무 스위치가 눌려지면 두더지 게임 시작
          { 
            for(count=08>=count; count++) // 시작전 LED 8번 루프
            {
              LED_OUT=~(1<<count);
              sleep(200);
            }
            LED_OUT=0x00;
            FND_OUT=0x00;
            for(count=51<=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=07>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;
}



/* 직렬 포트 통신을 이용한 LED 컨트롤 */

#include <avr/io.h>

#define CPU_CLOCK 16000000  // MCU의 속도
#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
// 통신속의 결과 값을 입력하기 위해 상하위 비트로 구분
//16l은 16+L, 연산시 값이 너무 커져 overflow발생하므로 32비트 연산
//위해 16에 long을 의미하는 l을 붙임

void init_USART1(void);
unsigned char USART_Receive(void);
void uart_send_byte(unsigned char byte);
void uart_send_string(unsigned char *str, unsigned char len);

int main(void)
{
  unsigned char buf[]="Hellow DK128!";
  unsigned int i;
  unsigned char ch;
  
  DDRF=0xff;
  PORTF=0xff;
  
  init_USART1();
  
  while(1)
  {
  ch =((USART_Receive())-48);
  if(ch==0)
  {
  PORTF=0xff;
  }
  else
  {
  PORTF=~(1<<(ch-1));
  uart_send_byte(ch+48);
  }
  asm("NOP");
  }
  return 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));
  }
}

/* 시리얼 통신을 송신 함수 */
void uart_send_byte(unsigned char byte)
{
  while (!(UCSR1A&(1<<UDRE)));  // 전송 버퍼가 비었을 때 까지 대기
  UDR1 = byte;  // 문자 1개씩 전송
}

/* 시리얼 통신을 수신 함수 */
unsigned char USART_Receive(void)
{
  /* 데이터 수신 대기 */
  while(!(UCSR1A&(1<<RXC)))
  {
  
  }
  /* 버퍼에 수신된 데이터를 가져와 리턴 */
  return UDR1;
}

/* 시리얼 통신 포트 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);
}

AVR 8-비트 RISC(Reduced Instruction Set Computer) 구조로 명령어가 간단하며 동작 속도가 빠르고, 1MHz당 약1MIPS(Million Instruction Per Second)의 성능을 보인다.  AVR의 대표적인 특징은 다음과 같다.

 

● 향상된 RISC 구조

- 133개의 강력한 명령어들이 대부분 단일 클럭으로 실행된다

- 32 X 8 범용 동작 레지스터 + 주변 콘트롤 레지스터로 구성

- 16MHz 환경에서 16 MIPS 이상의 성능

- 2 사이클 곱셈기를 칩에 내장

 

● 프로그램과 데이터 메모리

- 128K Byte In-System 프로그램 플래쉬 메모리 (내구성 : 최대 10,000번 쓰고 지울 수 있다.)

칩에 내장된 부트 프로그램으로 In-System 프로그래밍 가능

- 4K Byte EEPROM  (내구성 : 최대 100,000번 쓰고 지울 수 있다.)

- 4K Byte 내장형 SRAM

최대 64K Byte 이상의 외부 메모리 영역을 갖는다.

 

 JTAG (IEEE std. 1149.1 호환인터페이스 제공

- JTAG 인터페이스로 플래쉬, EEPROM, 퓨즈와 락비트를 프로그래밍 가능하다.

 

● 주변 사양

프로그래밍 가능한 53개의 Input / Output

외부 인터럽트 Ext. INT 8

두 개의 8-bit Timer/Counters  두 개의 16-bit Timer/Counters

두 개의 8-bit PWM 채널 / 6개의 16-bit PWM 채널과

- 8 채널, 10bit ADC

두 개의 프로그램 가능한 직렬 USART 제공

마스터 슬레이브 SPI 직렬 인터페이스

칩 내장형 아날로그 비교기

 

● 독특한 마이크로콘트롤러 사양

파워온 리셋 과 프로그램가능한 Brown-out 감지기

- 6가지 슬립모드 : 아이들, ADC 노이즈 감쇄기저전원무전원대기상태연장 대기상태

모든 Pull-up 설정해제

 

 I/O 와 패키지

- 53개의 프로그램 가능한 I/O 라인 ,  64개의 TQFP 64패드 MLF

 

● 동작 전원

- ATmega128L : 2.7V ~ 5.5V          - ATmega128  : 4.5V ~ 5.5V

 

● 동작 속도

- ATmega128L : 0 ~ 8MHz            - ATmega128  : 0 ~ 16MHz

 

 

04. AVR128의 외부구조

 ATmega128의 핀 배치는 아래 [그림4-1] 과 같다.

 


 VCC(21,52)

마이크로프로세서가 동작하도록 공급하는 전원으로 두 가지 타입에 따라 전원의 범위가 다르다.

( ATmega128L : 2.7V ~ 5.5V / ATmega128 : 4.5V ~ 5.5V )

 GND(22,53,63)

신호의 접지 핀으로 사용된다.

 XTAL1, XTAL2(23,24)

수정발진기의 입/출력 핀으로서 크리스털이나 오실레이터를 접속한다.

 RESET(20)

리셋 입력 핀으로서 50ns 이상의 Low level 입력이 지속되면 리셋이 발생한다.

 PORT A/B/C/D/E

반이중 I/O 포트로 내부 풀업 저항된 8비트/양방향/병렬/범용 포트이다. DDRX, PORTX, PINX 의 레지스터를 이용해 제어를 한다.

 PORT F

반이중 I/O 포트로 내부 풀업 저항된 8비트/양방향/병렬/범용 포트이다. A/D컨버터의 입력포트로도 사용된다.

 PORT G

반이중 I/O 포트로 내부 풀업 저항된 5비트/양방향/병렬/범용 포트이다.

 AVCC(64)

A/D 컨버터 및 포트 F의 전원 (ADC를 이용하지 않더라도 외부적으로 VCC에 연결되어야 한다.)

 AGND(63)

AVCC에 대한 전원 접지(반드시 GND와 접속할 것)

 AREF(62)

A/D 컨버터의 기준전압

 PEN(1)

SPI 활성화를 시키는 프로그래밍 인에이블 핀으로서 파워 온 리셋 시 LOW로 유지함으로써 SPI 활성화 상태가 된다일반적인 동작모드에서는 사용하지 않는다.

 

 

05. AVR128의 내부구조

ATmega128의 내부구조는 아래 [그림4-3] 블록도와 같다.

 

● 병렬처리의 최대 성능을 위해서 AVR Harvard 구조를 사용한다.

    - 프로그램 / 데이터에 대해 분리된 메모리와 버스가 사용된다.

   

● 고성능의 ALU는 모든 32개의 범용레지스터와 직접 연결되어 단일 사이클로 동작한다.

 

 

 

 

● ATmega128이 하버드구조와 2단계 파이프라인 처리방식으로 프로그램 명령을 인출하여

실행하는 동작을 [그림4-5] 에 보였다. AVR의 이러한 진보된 설계 기술은 결국 CPU가 시스템

클럭의 1주기에 평균적으로 1개의 명령을 실행하도록 함으로써 클럭 주파수 1MHz 1MIPS

처리속도에 해당하는 매우 높은 성능을 발휘하는 것이 가능하도록 하였다.


 

 [그림4-6]과 같이 1클럭 사이클 동안에 1개의 명령에서 2개의 레지스터 오퍼랜드가 사용되는 연산을 수행하고 그 결과를 다시destination register에 저장하는 처리한다.

 

 

06. AVR128의 메모리구조

 

(1) 프로그램메모리

ATmega128은 내부에 프로그램 메모리로 사용하는 128KB의 플래쉬 메모리를 가지고 있다.

 Flash Memory

- 128Kbyte (64K * 16bit)

- 16bit or 32bit

- Application / Boot Flash section

- Programming Writing 

 SPI 통신방식을 이용한 ISP기능 이용

 JTAG 에뮬레이터 사용

• 병렬 프로그래밍 모드 이용

 

 

(2) 데이터메모리 

ATmega128의 테이터메모리는 내부 데이터 메모리로서의 SRAM, 외부 데이터 메모리 SRAM, 그리고 내부 EEPROM 3가지 종류로 나눌 수 있다.

 

 32 Registers ($00~$1F)

 - 32레지스터는 AVR 모든 시리즈에서의 사용되는               

범용레지스터로서의 역할을 하게 된다.

 

 

 64 I/O Registers ($20~$5F)

각종 I/O 디바이스들을 제어하기 위한 레지스터

- IN / OUP 명령 사용 ($20~$5F  $00~$3F 라고 지정해야 한다.)

- ATmega128 datasheet (p.355~p357참조)

 

 160 Ext I/O Registers ($60~$FF)

- ATmega128에 추가된 각종 I/O 디바이스들을 제어하기 위한 레지스터

- IN / OUP 명령어 대신 LD/LDS/LDP, ST/STS/STD 명령어를 사용해야 한다.(16bit)

- ATmega128 datasheet (p.355~p357참조)

내부 SRAM (0x0100~0x10FF)

- 4Kbyte (4096 * 8bit)

각종 사용자변수 / 스택 영역으로 사용

 

⑤ 외부 SRAM (0x1100~0xFFFF)

사용자가 정해진 4KB보다 더 확장된 데이터메모리를 필요할 때 약 60KB의 외부 데이터 메모리영역으로 이용 가능하다.

 

 EEPROM

- 4Kbyte 내장

불 휘발성

다른 데이터 메모리 어드레스 영역과는 별

개의 영역을 할당 받게 된다.

단일 바이트로 읽고 쓸 수 있다.

 


 

07. AVR128의 외부인터페이스

 

   외부 메모리 인터페이스가 제공되며 외부 SRAM / 플래쉬 / LCD 디스플레이 / ADC 와 같은 외부 메모리 장치에 대한 인터페이스를 구동시키는데 아주 적합하게 되어 있다.

 

 

 

 

^^v

/* 직렬 포트 통신 */

#include <avr/io.h>

#define CPU_CLOCK 16000000  // MCU의 속도
#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
// 통신속의 결과 값을 입력하기 위해 상하위 비트로 구분
//16l은 16+L, 연산시 값이 너무 커져 overflow발생하므로 32비트 연산
//위해 16에 long을 의미하는 l을 붙임

int main(void)
{
  unsigned char buf[]="Hellow DK128!";
  unsigned int i;
  
  init_USART1();
  
  while(1)
  {
  uart_send_string(buf,sizeof(buf));
  }
  return 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));
  }
}

/* 시리얼 통신을 보내는 함수 */
void uart_send_byte(unsigned char byte)
{
  while (!(UCSR1A&(1<<UDRE)));  // 전송 버퍼가 비었을 때 까지 대기
  UDR1 = byte;  // 문자 1개씩 전송
}

/* 시리얼 통신 포트 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);
}



// 두더지 잡기 게임
#include <stdlib.h>
#include "header/io.h"

#define LED_DDR DDRF
#define LED_OUT PORTF
#define KEY PINC
#define FND_DDR DDRE
#define FND_OUT PORTE

#define CPU_CLOCK 16000000
#define TICKS_PER_SEC 1000
#define PRESCALER 128

volatile unsigned int g_elapsed_time; // 시간변수

/* 함수 원형 설정 */
void sleep(unsigned int elapsed_time); // sleep함수
void init_LED(void); // LED포트 초기화 함수 원형
void init_TIMER(int timers); // Timer Counter 설정
void init_TC0(void); // Timer0 초기화 함수 원형
void delay(char *a, int speed); // SW입력 대기 함수 원형

int main()
{
/* 변수 설정 */
char count;
char t_count=0;
char led=1;
char score=0;
char score1=0;
char fnd=0;
int delay_ms;
/* 사용 설정 초기화 */
SREG = SREG|(1<<7); // 전체 인터럽트 활성화
DDRC=0x00;
init_LED(); // LED포트 초기화
init_TC0(); // Timer0 초기화
init_TIMER(OCIE0); // 타이머 설정
OCR0 = 0x7D; // 비교매치 인터럽트 비교값 설정
sei(); // 인터럽트 활성화 함수

/* 프로그램 작성 시작 */
while(1) //  난수 함수 시작점을 다르게하기 위한 무한 루프
{
delay_ms=500;
t_count++;
for(count=0; 8>count; count++)
{
LED_OUT=~(1<<count);
delay(&fnd, delay_ms);
if(5==fnd) // 0+1번 스위치가 눌려지면 두더지 게임 시작
{
for(count=0; 8>=count; count++)
{
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=0;
sleep(1000); // 게임 시작전 0.5초 지연
srand((unsigned int)t_count); // 난수 발생 함수
delay_ms=1000;
break; // 게임 시작을 위해 무한루프 브레이크
}
}
if(5==fnd)
{
fnd=0;
break;
}
}
/* 두더지 게임 시작 */
for(count=0; ;) // 무한 루프
{
for(count=0; count<25; count++) // 25번의 두더지 생성(LED On/off)
{
LED_OUT = ~(led<<rand()%7); // 두더지(LED)의 생성 위치 변경
delay(&fnd, delay_ms); // 1초간 지연하면서 스위치 입력 대기
if(2==fnd) // 두더지를 잡으면 점수 5점씩 올림
{
fnd=0;
score += 5;
if(score==0x0a)
{
score=0x00;
score1+=0x10;
}
}
else if(score1==0xa0||10==fnd) // 6+7번SW or 점수가 100점이 되면 FND,LED on/off 6회반복
{
score=0x00;
score1=0x00;
LED_OUT=0x00;
FND_OUT=0x00;
for(count=0; 6>=count; count++)
{
LED_OUT=~LED_OUT;
FND_OUT=~FND_OUT;
sleep(200);
}
sleep(2000);
FND_OUT=0;
fnd=0;
break; // on/off 6회 반복 끝나면 프로그램 종료!
}
FND_OUT = score+score1; // 점수 표시
LED_OUT = 0xff; // 두더지 숨기(LED off)
sleep(1000); // 1초 지연
}
delay_ms-=200;
if(25<=count) // 100점이면 게임 계속 실행
{ // 100점미만이면 게임 종료
return 0;
}
}
return 1;
}


/* 1초간 스위치 입력 대기 */
void delay(char *a, int speed)
{
g_elapsed_time=0;
while(g_elapsed_time<speed)
{
if(KEY == 0xfc) // 0~1번 SW Start
{
*a=5; // fnd변수에 5대입
break;
}
else if(KEY == 0x3f) // 6~7번 SW clear
{
*a=10; // fnd변수에 10대입
break;
}
else if(LED_OUT == KEY) // LED와 스위치가 같이 같으면 실행
{
*a=2; // fnd변수에 2대입
break;
}
}
}

/* LED포트 초기화 설정 함수 */
void init_LED(void)
{
LED_DDR = 0xFF; // PORTF 출력모드 설정
LED_OUT = 0xFF; // PORTF 초기화
FND_DDR = 0xFF;
FND_OUT = 0x00;
}

/* 타이머 설정 함수 */
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++;
}

+ Recent posts