2011년5월27일_ATmega128 내부EEPROM기록 오류 수정, 게임진행화면 이쁘게, 1세트 ~ 10세트까지 점수를 합산(점수기록시 /5, 표시시 *5), dec_to_ascii() 앞에 0없애기, DK-128 적외선 센서불량으로 보드교체
1: /***************************************************************************
2:
3: 파일명: main.c
4: ATmega128.h - I/O정의
5:
6: 작성자: 1.출처: 내 머리
7: 2.작성: [내장형 하드웨어]과정 김수만
8:
9: 목적: 두더지게임
10:
11: 사용방식:
12:
13: 사용파일: stdlib.h - 랜덤함수
14:
15: 제한사항:
16:
17: 오류처리:
18:
19: 이력사항: 1.2011년 5월 23일...최초 작성.
20: 2.2011년 5월 24일...주석 정리.
21: 함수의 배치 순서 정리.
22: 문자열 전송함수 개선 - \n만 하면 되도록
23: 3.2011년 5월 26일...시작화면, 메뉴, 통신속도최대로 115200bps
24: 4.2011년 5월 27일...EEPROM RANK기록 오류 수정. (1위까지 잘 표시)
25: 게임진행화면 이쁘게
26: 1세트~10세트까지 만들고 점수 합산 저장.
27: (점수기록시 그대로, 표시시 *5)
28: dec_to_ascii() - 앞에 '0'표시 없애기.
29:
30: ****************************************************************************/
EEPROM에 기록할 순위데이터 오류 수정 |
game_over( ) 함수의,
1: for(ucLoop = 10 ; 1 < ucLoop ; --ucLoop) // 10번지부터 1번지까지 교체 (i - 1)
2: {
3: //EEPROM의 데이터 정렬
4: }
예전 소스는 위와 같이 10번지부터 1번지까지만 교체되어 1위인 0번지의 데이터가 정렬되지 않았다.
그래서 조건식에 1 대신 0을 넣어 0번지까지 정렬되도록 하였다.
1: //점수를 정렬하며 EEPROM에 기록 1위~10위까지
2: eeprom_write(10, ucScoreSum); //제일 밑에 총점을 넣고
3:
4: for(ucLoop = 10 ; 0 < ucLoop ; --ucLoop)
5: {
6: if(eeprom_read(ucLoop) > eeprom_read(ucLoop - 1)) //바로 위에 수치와 비교하여,
7: {
8: ucTemp = eeprom_read(ucLoop - 1); //교체
9: eeprom_write(ucLoop - 1, eeprom_read(ucLoop));
10: eeprom_write(ucLoop, ucTemp);
11: }
12: }
그나저나 블록단위 쓰기를 해야 하는데 바이트단위 읽고 수정 쓰기를 하니 수명이 많이 걱정된다.
어려운 것도 아닌데 왜 이렇게 잘 되지 않는가?
game_score( ) 함수의,
1: //1위 부터 10위까지 출력
2: for(ucLoop = 0 ; 10 > ucLoop ; ++ucLoop)
3: {
4: uart_send_string_suman("\t\t\t");
5:
6: ucTemp = eeprom_read(ucLoop);
7: printf_suman("%d. %d점\n", ucLoop + 1, ucTemp * 5, 0);
8: }
순위데이터 출력하는 부분은 참고용으로 올린다.
그런데 이상하게 수정했는데 전원OFF후 재투입 시 1위 부터 0으로 초기화된다.
이상해! 이상해!
게임진행화면 이쁘게 꾸미기 |
1: void game_display_LED_SW(unsigned char cNum)
2: {
3: char aBuf[][18] = {"○○○○ ○○○○",
4: "○○○○ ○○○●",
5: "○○○○ ○○●○",
6: "○○○○ ○●○○",
7: "○○○○ ●○○○",
8: "○○○● ○○○○",
9: "○○●○ ○○○○",
10: "○●○○ ○○○○",
11: "●○○○ ○○○○"};
12:
13: uart_send_string_suman(aBuf + cNum);
14:
15: return ;
16: }
2차원 배열을 선언하여 화면에 표시할 그림을 저장하였으나, 이 영역은 SRAM이다.
SRAM은 변수가 놓이는 부분인데 여기선 상수를 넣어 조금 아깝다.
그래서 FLASH영역에 선언하는 것을 찾아 보았으나,
#include <avr/pgmspace.h>
pgmspace.h를 인클루드(?)해야 하고 함수를 써서 엑세스하는 것이 조금 복잡해서 관두었다.
아마 FLASH는 SRAM과 다르게 16비트라 조금 복잡한 것 같다. 후에 필요하면 필사적으로 찾을 것이나 지금은 필요없다.
그러니 SRAM영역에 넣고 쓰자.
main( )의 표시하는 부분은,
1: //횟수와 점수를 출력.
2: ucLED = log_2(ucLED);
3: ucTemp = log_2(gKey);
4: printf_suman("%d.\t", ucLoop, 0, 0);
5: game_display_LED_SW(ucLED); //LED - 0~8까지의 값을 받아 ○○○○○○○●출력
6:
7: uart_send_string_suman("\n\t");
8:
9: if(0 != gSensor && 0 < ucBomb) //센서 감지되고 폭탄갯수가 충분하면,
10: {
11: uart_send_string_suman("▲▲▲Boom▲▲▲\a\a"); //뽀개진거 출력.
12: PORT_BELL = 0x00; //BELL ON
13: sleep(20); //50ms
14: PORT_BELL = 0xFF; //BELL OFF
15: sleep(20); //50ms
16: PORT_BELL = 0x00; //BELL ON
17: sleep(20); //50ms
18: PORT_BELL = 0xFF; //BELL OFF
19: }
20: else //일반상태
21: {
22: game_display_LED_SW(ucTemp); //KEY - 0~8까지의 값을 받아 ○○○○○○○●출력
23: }
점수 합산 |
1: //점수 출력.
2: printf_suman("\t\t\t점수: %d점\n", ucScore * 5, 0, 0);
3: sleep(2000); //2초 대기.
4:
5: ucScoreSum = ucScoreSum + ucScore; //점수 합산
6: ucLED = 0xFF; //점수 출력 전 초기화
7:
8: if(100 == (ucScore * 5)) //만약 모두 맞추었다면
9: { }
2행에 printf_suman( ) 함수의 인자로 문자열과 점수의 5배한 값을 넘겨주고 있다. (0은 더미값)
5행에 점수를 합하여 저장한다.
그 다음 게임 종료 시 점수합을 출력하기 위해 game_over( ) 함수의 인자로 넘겨준다.
1: if(8 > ucScore)
2: {
3: game_over(ucScoreSum); // GAME OVER메세지와 EEPROM에 총점 기록.
4:
5:
6: break; // 메뉴로
7: }
점수가 8보다 작을 때니 실제 점수가 40점미만일 때 종료하면서 점수의 합을 넘겨준다.
dec_to_ascii( ) – 출력되는 숫자 앞에 ‘0’없애기 |
1: //정수를 문자로 바꾸는 함수. (0~255까지만 취급함.)
2: void dec_to_ascii(unsigned char cNum, char *p)
3: {
4: unsigned char ucLoop = 3;
5:
6: *(p + ucLoop) = '\0'; //문자열끝.
7:
8: for(; 0 < ucLoop ; --ucLoop)
9: {
10: *(p + ucLoop - 1) = (cNum % 10) + '0'; //일자리부터 백자리까지 저장 후 문자로 변환.
11: cNum = cNum / 10; //일자리부터 10단위로 잘라냄.
12: }
13:
14: //숫자 앞에 0을 없애는 부분.
15: for(ucLoop = 0 ; 2 > ucLoop ; ++ucLoop)
16: {
17: if('0' == *(p + ucLoop)) //현재 자리가 '0'이면,
18: {
19: if(0 == ucLoop) //첫 번째 자리에는,
20: {
21: *(p + ucLoop) = ' '; //공백문자로 만들어 버림.
22: }
23: else if((0 != ucLoop) && (2 != ucLoop) && (' ' == *(p + ucLoop - 1)))
24: { //첫 번째와 마지막자리를 제외한 자리에는,
25: *(p + ucLoop) = ' '; //공백문자로 만들어 버림.
26: }
27: else //마지막자리는,
28: {
29: *(p + ucLoop) = '0'; //'0'으로 만들어 버림.
30: }
31: }
32: }
33:
34: return ;
35: }
숫자 앞에 ‘0’을 없애는 부분이 복잡한 이유는 비밀입니다. 하하하
'내장형하드웨어 > 일일보고서' 카테고리의 다른 글
2011년5월31일_ATmega128 내부EEPROM 하드웨어적 오류와 회피법, HexaView 프로젝트 (0) | 2011.06.01 |
---|---|
2011년5월30일_두더지잡기게임 프로젝트 보고서 (0) | 2011.05.30 |
2011년5월26일_두더지게임(시작화면, 메뉴, ATmega128 내부EEPROM에 순위데이터저장) (0) | 2011.05.27 |
2011년5월25일_두더지게임 업그레이드 기획 (시작화면, 메뉴, 문자그림, 보너스두더지), ATmega128 내부EEPROM에 순위데이터저장 (0) | 2011.05.26 |
2011년5월24일_두더지게임2 소스코드의 주석을 보기 좋게 정리함 (0) | 2011.05.25 |