BASIC4MCU | 질문게시판 | ATmega128 : 7seg, Switch, LED, USART를 이용한 게임기
페이지 정보
작성자 응답없음 작성일2022-12-17 08:55 조회1,869회 댓글0건본문
안녕하세요... ATmega 128으로 게임기를 만들어보고 싶어서 도전했는데 상당히 문제가 많네요..
우선
1. 하이퍼 터미널으로 char를 출력하는데요, 디바이스에 코드를 쓸 때 하이퍼 터미널에 무작위 char가 출력됩니다.
디바이스에 프로그래밍되면 원하는 매뉴얼 코드가 출력되긴 하는데, 쓰기 전까지는 계속 char가 출력돼요..
2. mode=0의 두더지 게임을 실행하면 LED가 켜지지 않습니다. 이게 앞에서 문제가 생기는건지, 아니면 LEDon 함수에서 문제가 있는지 모르겠습니다.
3. 처음에는 Press07 함수를 while(!(swtich & 0x81)); 으로 스위치의 7,0번을 동시에 눌러야 다음으로 넘어갈 수 있도록 만들었었습니다.
0과 7 중 하나만 입력해도 다음으로 넘어가서 수정했었는데, 기존의 함수를 썼을 때 뭐가 문제였던걸까요?
긴 코드에... 코딩 초보의 허접한 코드 죄송합니다.
ATmega 128으로 넘어오니 자료형이 너무 헷갈리네요.
====================================================================================================
#define F_CPU 16000000UL
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include <stdlib.h>
#include <math.h>
uint8_t FND_TABLE[] = {0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F}; //0 to 9
int data1=0; // 7seg의 왼쪽 2개의 LED 데이터 & SW1의 점수
int data2=0; // 7seg의 오른쪽 2개의 LED 데이터 & SW2의 점수
int Init7seg=1; // 메뉴창에서 1이 되는, 7seg의 제어를 위한 변수
int mode=0; // Init7seg=0일 때 7seg의 게임 선택을 위한 변수
int Selected=0; // Game 선택 완료되면 1이 되는 변수, Game이 끝나면 0이 된다.
unsigned int RandTime;
unsigned char LEDnum;
int Score1=0;
int Score2=0;
//------------------------main------------------
void main (void)
{
cli();
// Port 설명
DDRD=0x00; // SW1 (Player1)
DDRE=0x00; // SW2 (Player2)
DDRB=0xFF; // 8 LED
DDRC=0xFF; // 7seg LED control connector
DDRA=0xFF; // 7seg LED data connector
DDRG=0xFF; // USART
Init_Manual(); // 하이퍼 터미널 창으로 설명서 출력
TIMSK=0x01; // Timer0에 대한 인터럽터 설정
Init_Timer0(); // 1초에 한번씩 인터럽터 실행 (7seg 출력 함수가 1초마다 반복되게 하기 위함)
sei();
//main routine
while(1)
{
menu();
Press07();
WhichGame();
Loading();
Press07();
StartGame();
_delay_ms(5000); // 게임이 끝나고 5초 후에 다시 while문이 시작된다.
}
}
//-------------------Init_Timer0----------------------
void Init_Timer0(void)
{
TCCR0=0x02;
TCNT0=0x38; // 1s 마다 인터럽트 발생
}
//-------------1s 마다 발생하는 인터럽트 서비스 루틴 : 7seg------------------
ISR(TIMER0_OVF_vect)
{
// 7seg LED의 제어
if(Init7seg==1) seg_Hello(); // 메뉴창:7seg_Hello
else seg(); // 메뉴창 아닐때에는 7seg함수를 따른다.
TCNT0=0x83;
}
//-----------------Init_Manual------PORTG :USART---------------------
int Init_Manual(void)
{
uart0_init(38400); // baudrate = 38400
DDRG=0xFF;
char* manual1="Manual:\n1. Press0,7 if you want to play games\n ";
while (*manual1) uart_putch(*manual1++);
return 0;
}
//--------------------uart0 송신 설정-------------------------
void uart0_init(unsigned long BaudRate)
{
UCSR0A = 0x00;
UCSR0B = 0x18; // transmitter, receiver enabling
UCSR0C = 0x06; // character size = 8bit
// Setting BaudRate
UBRR0H=0x00;
UBRR0L=(F_CPU/BaudRate/16 - 1);
}
void uart_putch(char ch)
{
if (ch == '\n') uart_putch('\r'); // 개행문자 처리
while(!(UCSR0A & 0x20)); // 스트림 버퍼가 비어 있는지 체크
UDR0=ch; // 데이터 보냄
}
//---------------------7seg Hello-----------------------
void seg_Hello(void)
{
PORTA = 0b01110110; // 넷째자리에 H가 표시됨.
PORTC = ~0x01;
_delay_ms(5);
PORTA =0b01111001; // 셋째자리에 E가 표시됨.
PORTC = ~0x02;
_delay_ms(5);
PORTA = 0b00110110; // 둘째자리에 ll이 표시됨.
PORTC = ~0x04;
_delay_ms(5);
PORTA = 0b00111111; // 첫째자리에 O가 표시됨.
PORTC = ~0x08;
_delay_ms(5);
}
//------------------seg----------PortA; for data / PortC; for control--------
void seg(void)
{
unsigned int data=data2+data1*100;
unsigned char int_digit4 = (data%10000)/1000; // 넷째자리(1000의 자리) 수 계산
unsigned char int_digit3 = (data%1000)/100; // 셋째자리(100의 자리) 수 계산
unsigned char int_digit2 = (data%100)/10; // 둘째자리(10의 자리) 수 계산
unsigned char int_digit1 = (data%10)/1; // 첫째자리(1의 자리) 수 계산
PORTA = FND_TABLE[int_digit4]; // 넷째자리 숫자가 표시됨.
PORTC = ~0x01;
_delay_ms(5);
if(Selected==0)
{
PORTA = FND_TABLE[int_digit3]; // 게임 선택 전: 셋째자리 숫자가 표시됨.
PORTC = ~0x02;
_delay_ms(5);
}
else
{
PORTA = FND_TABLE[int_digit3]|0x80; // 게임 선택 후 : 점수판으로, 셋째자리 숫자와 점이 표시됨.
PORTC = ~0x02;
_delay_ms(5);
}
PORTA = FND_TABLE[int_digit2]; // 둘째자리 숫자가 표시됨.
PORTC = ~0x04;
_delay_ms(5);
PORTA = FND_TABLE[int_digit1]; // 첫째자리 숫자가 표시됨.
PORTC = ~0x08;
_delay_ms(5);
}
//------------------- Press07----------------------------
void Press07(void)
{
while(!(PIND&0x80)); //sw1의 7,0번 비트가 1이 되어야 다음으로 넘어감.
}
//---------------------WhichGame----------------------
void WhichGame(void)
{
Init7seg=0; // Menu화면에서 넘어감. Hello가 뜨지 않고 7seg함수로 7seg LED가 제어된다.
while(!(PIND&0x80)) // 0,7을 동시에 누르기 전까지는 WhichGame함수가 끝나지 않는다.
{
if (PIND & 0x01){mode++; mode=((mode)%2);} // sw1의 0번 스위치로 mode를 바꾼다.
data2=mode; // data2를 업데이트하여 7seg의 우측 2개 LED에 몇 번 mode인지 뜬다.
}
}
//-----------------Loading-------------------
void Loading(void)
{
cli(); // 인터럽터가 실행되지 않아 7seg에 아무것도 출력되지 않는다.
data1=0;
data2=0;
Selected=1;
Press07(); // sw1에서 07을 눌러 7seg를 다시 출력한다.
sei();
}
//----------------StartGame----------------------
void StartGame(void)
{
if(mode==0) Game1();
else Game2();
}
//-------------------Game1----------------
void Game1(void)
{
int i=0;
for (i; 30; i++) // 30회 LED를 On시키면 게임이 끝난다.
{
Random();
int t=0;
for (t; 500+RandTime; t++) {_delay_ms(1);} //_delay_ms (RandTime); 이 되지 않아 사용
LEDon();
GetScore();
}
}
//----------------Random--------------------
void Random(void)
{
LEDnum=(char)(rand()%8);
RandTime=rand()%4000; // LED가 켜지는 시간범위: 0.5s~4.5s가 되도록한다.
}
//-------LEDon--------PortB for LED--------------
void LEDon(void)
{
PORTB=(char)(pow(2,LEDnum)+0.001); // LEDnum에 해당하는 비트의 LED가 켜짐
cli(); // ISR로 인해 버튼의 스위치 입력이 무시될 것 같아 인터럽트 중지
}
//---------------GetScore-------------------------
void GetScore(void)
{
int i=0;
while(i==1)
{
if (PIND==LEDnum)
{
Score1++;
data1=Score1;
PORTB=0x00; //LED를 끈다.
i=1; //while의 조건문이 충족되어, GetScore 함수가 끝난다.
}
else if (PINE==LEDnum)
{
Score2++;
data2=Score2;
PORTB=0x00;
i=1;
}
}
sei(); // 득점하면 7seg에 점수가 업데이트 되며 켜진다. 짧은 순간 꺼지는 것이므로 큰 영향이 없을 것 같다.
}
//-----------------Game2------------------------
void Game2(void)
{
int n=0;
int m=0;
int time=0;
int t1=0;
int t2=0;
cli(); // 7seg을 제어하기 위해 ISR가 실행되지 않도록한다.
Count3(); // 7seg에서 3초 카운트다운한다. count3 함수가 끝나면 cli()로 인해 인터럽터가 실행되지 않아 7seg에 아무것도 출력되지 않는다.
PORTA=0;
while((n&m)==1) // n과 m이 1이 될때까지 반복한다. (sw의 입력이 있었다면 (sw1)n, (sw2)m이 set된다)
{
time++;
_delay_ms(1000); // 1초가 지날때마다 time이 1씩 추가된다.
// record time
if (PIND==0x01)
{t1=time; data1=t1; n=1;}
if (PINE==0x01)
{t2=time; data2=t2; m=1;}
}
sei(); // 끝나고 data1, data2가 업데이트 되면서 7 seg에 각자가 몇초에 버튼을 눌렀는지 뜨게 된다.
}
//-----------------------Count3---------------------
void Count3(void)
{
int i=0;
for (i; 3;i++)
{
PORTA = FND_TABLE[3-i]; // 첫째자리에 3,2,1가 차례대로 표시됨. & cli();를 사용하여 인터럽트 루틴이 실행되지 않는다.
PORTC = ~0x08;
_delay_ms(1000);
}
}
//--------------------------Menu------------------------
void menu(void)
{
mode=0;
data1=0;
data2=0;
Init7seg=1; // 모두 초기 설정으로 돌아간다.
Selected=0;
Score1=0;
Score2=0;
}
댓글 0
조회수 1,869등록된 댓글이 없습니다.