2011년5월30일_두더지잡기게임 프로젝트 보고서
PDF파일 다운로드
미리보기 |
동영상 |
소스코드 |
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: ****************************************************************************/
31: #include "./../../ATmega128.h"
32: #include <stdlib.h>
33: #include <avr/pgmspace.h>
34:
35: //포트 정의
36: #define DDR_LED DDRF
37: #define PORT_LED PORTF
38: #define DDR_FND DDRE
39: #define PORT_FND PORTE
40: #define DDR_KEY DDRC
41: #define PIN_KEY PINC
42: #define PORT_KEY PORTC
43: #define DDR_SENSOR DDRD
44: #define PIN_SENSOR PIND
45: #define DDR_BELL DDRB
46: #define PORT_BELL PORTB
47:
48: //통신관련
49: #define CPU_CLOCK 16000000
50: #define BAUD_RATE 115200 // 통신시 이용할 속도
51: #define BAUD_RATE_L (CPU_CLOCK / (8l * BAUD_RATE)) - 1
52: #define BAUD_RATE_H ((CPU_CLOCK / (8l * BAUD_RATE)) - 1) >> 8
53: /* 통신속도의 결과 값을 입력하기 위해 상하위 비트로 구분
54: 16l은 16 + L이며, 연산 시 값이 너무 커져 overflow가 발생하므로 32비트 연산을
55: 위해 16에 Long을 의미하는 l을 붙인다.*/
56:
57: //타이머관련
58: #define TICKS_PER_SEC 1000 // Ticks per sec = 1,000
59: #define PRESCALER 64 // Prescaler = 64
60:
61:
62: //ISR선언
63: void __vector_15 (void) __attribute__ ((signal, used, externally_visible));
64: void init_port(void);
65: void init_TC0(void);
66: void init_USART1(void);
67: void sleep(unsigned int);
68: void uart_send_byte(unsigned char);
69: void uart_send_string(unsigned char *, unsigned int);
70: void uart_send_string_suman(char *);
71: unsigned char USART_Receive(void);
72: unsigned char eeprom_read(unsigned int uiAddress);
73: void eeprom_write(unsigned int uiAddress, unsigned char ucData);
74: unsigned char hex_to_dec(unsigned char);
75: void printf_suman(char *, unsigned char, unsigned char, unsigned char);
76: void dec_to_ascii(unsigned char, char *);
77: char log_2(unsigned char);
78: void ToggleNumber(unsigned char *);
79: //game메뉴
80: void game_start(unsigned int);
81: unsigned int game_option(void);
82: void game_rank(void);
83: void game_score(void);
84: void game_exit(void);
85: void game_over(unsigned char);
86: void game_display_LED_SW(unsigned char);
87:
88:
89: /*------------------------------ 전역 변수 ---------------------------------- */
90: volatile unsigned int g_elapsed_time = 0; // 시간 변수
91: volatile unsigned char gKey = 0; // 키입력값 저장 버퍼
92: volatile unsigned char gSensor = 0; // 적외선 센서
93: /*------------------------------ 전역 변수 ---------------------------------- */
94:
95:
96:
97: /* >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 프로그램 시작 <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< */
98: int main(void)
99: {
100: unsigned int uiDiff = 1000; //난이도 (1000 = EASY, 750 = NORMAL, 500 = HARD)
101: unsigned char ucTemp = 0; //임시 저장공간
102: unsigned char ucLoop = 0; //루프 제어변수
103: const char aMole[4][3][50] = {{" と─つ \n",
104: " │⊙⊙│ と─つ と─つ と─つ \n",
105: "─┴──┴──┴──┴──┴──┴──┴──┴─\n"},
106:
107: { " と─つ \n",
108: " と─つ │⊙⊙│ と─つ と─つ \n",
109: "─┴──┴──┴──┴──┴──┴──┴──┴─\n"},
110:
111: { " と─つ \n",
112: " と─つ と─つ │⊙⊙│ と─つ \n",
113: "─┴──┴──┴──┴──┴──┴──┴──┴─\n"},
114:
115: { " と─つ \n",
116: " と─つ と─つ と─つ │⊙⊙│ \n",
117: "─┴──┴──┴──┴──┴──┴──┴──┴─\n"}};
118:
119:
120: init_port(); // LED, FND, KEY에 해당하는 포트만 초기화
121: init_USART1(); // UART1 초기화
122: init_TC0(); // 타이머/카운터0 초기화
123: sei(); // 인터럽트 활성화
124:
125:
126: while(1)
127: {
128: uart_send_string_suman("\n\n");
129: uart_send_string_suman("\t\t\tMole-catching game\n\n\n");
130:
131:
132: ucTemp = rand() % 4;
133:
134: for(ucLoop = 0 ; 3 > ucLoop ; ++ucLoop)
135: {
136: uart_send_string_suman("\t\t");
137: uart_send_string_suman((char*)(aMole[ucTemp] + ucLoop));
138: }
139:
140: uart_send_string_suman("\n\n\n\n\n");
141:
142: uart_send_string_suman("\t\t\t\t");
143: uart_send_string_suman("1. START\n");
144: uart_send_string_suman("\t\t\t\t");
145: uart_send_string_suman("2. OPTION\n");
146: uart_send_string_suman("\t\t\t\t");
147: uart_send_string_suman("3. RANK\n");
148: uart_send_string_suman("\t\t\t\t");
149: uart_send_string_suman("4. EXIT\n");
150:
151: gKey = 0; //키값 초기화
152: sleep(500);
153: //메뉴선택버튼을 눌렀을 때.
154: switch(gKey)
155: {
156: //1번 스위치 누름.
157: case 0x01:
158: game_start(uiDiff); //난이도를 넣고 시작.
159: break;
160:
161: //2번 스위치 누름.
162: case 0x02:
163: uiDiff = game_option(); //난이도를 선택하여 받아오는 함수 호출.
164: break;
165:
166: //3번 스위치 누름.
167: case 0x04:
168: game_rank(); //순위출력
169: break;
170:
171: //4번 스위치 누름.
172: case 0x08:
173: game_exit(); //종료.
174: break;
175:
176: default:
177: break;
178: }
179:
180:
181: uart_send_byte(0x0C); //다음 페이지
182: }
183:
184: return 1; //종료
185: }
186:
187: /*****************************************************************************
188:
189: 타이머/카운터0 비교매치 인터럽트 서비스 루틴
190:
191: *****************************************************************************/
192: void __vector_15(void)
193: {
194: ++g_elapsed_time; // 시간변수 1증가
195: gKey = gKey | ~PIN_KEY; // 키입력값을 반전하여 저장.
196: gSensor = gSensor | ((~PIN_SENSOR) & 0x80); // 센서신호를 저장.
197: }
198:
199: //ms단위 시간지연함수 (전역변수 사용.)
200: void sleep(unsigned int elapsed_time)
201: {
202: g_elapsed_time = 0; // 시간 변수 초기화
203: while(elapsed_time > g_elapsed_time); // 참이 될 때까지 대기.
204:
205: return ;
206: }
207:
208:
209: /******************************************************************************
210:
211: 두더지 게임 시작!
212:
213: *******************************************************************************/
214: void game_start(unsigned int uiDiff)
215: {
216: unsigned char ucLED = 0; //LED
217: unsigned char ucScore = 0; //점수
218: unsigned char ucScoreSum = 0; //점수합
219: unsigned char ucLoop = 0; //루프제어변수
220: unsigned char ucTemp = 0; //임시 중간계산결과저장?
221: unsigned char ucGameLv = 0; //단계
222: unsigned char ucBomb = 3; //폭탄. 처음에는 3개로 시작.
223:
224: /* srand()에 seed값을 시작할 때마다 다르게 넣어주기 위해
225: PC에선 내부RTC의 시간을 이용하나 AVR은 RTC가 없기 때문에
226: 언제 누를지 알 수 없는 KEY와 항상 변화하고 있는 TCNT0의 값을
227: 이용한다. */
228: srand(TCNT0); //시드값을 넣어줌.
229: sleep(100); //100ms대기
230:
231: while(1) //무한루프
232: {
233: ++ucGameLv;
234: if(10 < ucGameLv)
235: {
236: game_over(ucScoreSum); //게임 끝 메세지와 함께 기록.
237: break;
238: }
239:
240: uart_send_byte(0x0C); //다음 페이지
241: printf_suman("%d세트 시작...폭탄 갯수는 %d개 남았습니다.", ucGameLv, ucBomb, 0);
242:
243: //5에서 0까지 카운트 다운! (두더지1-2)
244: for(ucLoop = 5 ; 0 < ucLoop ; --ucLoop)
245: {
246: uart_send_byte(ucLoop + '0'); //54321 (카운트다운)
247: //숫자를 문자로 바꾸어 전송.
248: PORT_FND = ucLoop | 0xF0; //5초 부터 1초까지
249: //10단위자리는 blank
250: sleep(200); //카운트다운하며 대기.
251: }
252:
253: PORT_FND = 0x00; //FND초기화
254: uart_send_string_suman("\n\n");
255:
256: for(ucLoop = 1 ; 20 >= ucLoop ; ++ucLoop)
257: {
258: gKey = 0; //키값 리셋
259: //1 ~ 7까지 난수를 발생하여 그 수 만큼 좌로 시프트
260: ucLED = 1 << (rand() % 8);
261: PORT_LED = ~ucLED; //반전하여 출력
262: sleep(uiDiff - (ucGameLv * 25)); //난이도에 따라 지연시간이 달라짐.
263: //EASY = 1000ms ~ 750ms(10세트)
264: //NORMAL= 750ms ~ 500ms
265: //HARD = 500ms ~ 250ms
266:
267: //횟수와 점수를 출력.
268: ucLED = log_2(ucLED);
269: ucTemp = log_2(gKey);
270: printf_suman("%d.\t", ucLoop, 0, 0);
271: game_display_LED_SW(ucLED); //LED - 0~8까지의 값을 받아 ○○○○○○○●출력
272:
273: uart_send_string_suman("\n\t");
274:
275: if(0 != gSensor && 0 < ucBomb) //센서 감지되고 폭탄갯수가 충분하면,
276: {
277: uart_send_string_suman("▲▲▲Boom▲▲▲\a\a"); //뽀개진거 출력.
278: PORT_BELL = 0x00; //BELL ON
279: sleep(20); //50ms
280: PORT_BELL = 0xFF; //BELL OFF
281: sleep(20); //50ms
282: PORT_BELL = 0x00; //BELL ON
283: sleep(20); //50ms
284: PORT_BELL = 0xFF; //BELL OFF
285: }
286: else //일반상태
287: {
288: game_display_LED_SW(ucTemp); //KEY - 0~8까지의 값을 받아 ○○○○○○○●출력
289: }
290:
291: //두더지가 맞았으면
292: if(ucLED == ucTemp || ((0 != gSensor) && (0 < ucBomb))) //두더지를 맞추었으니
293: {
294: ucScore = ucScore + 1; //1점증가 (표시할 땐 *5해서 표시)
295: uart_send_string_suman("...OK!\n");
296: }
297: else
298: {
299: uart_send_string_suman("...Fail!!\n");
300: }
301:
302: //폭탄처리
303: if(0 != gSensor) //센서 감지되면,
304: {
305: gSensor = 0; //센서값 초기화
306:
307: if(0 < ucBomb)
308: {
309: --ucBomb; //폭탄 갯수 줄임.
310: }
311: }
312:
313: //100점은 제외. 16진수변환 함수가 3자리를 처리 못 함.
314: if(100 != ucScore)
315: {
316: PORT_FND = hex_to_dec(ucScore * 5); //FND에 점수표시
317: }
318:
319: PORT_LED = 0xFF; //LED모두 OFF
320: sleep(uiDiff); //500ms 대기
321: }
322:
323: //점수 출력.
324: printf_suman("\t\t\t점수: %d점\n", ucScore * 5, 0, 0);
325: sleep(2000); //2초 대기.
326:
327: ucScoreSum = ucScoreSum + ucScore; //점수 합산
328: ucLED = 0xFF; //점수 출력 전 초기화
329:
330: if(100 == (ucScore * 5)) //만약 모두 맞추었다면
331: {
332: PORT_FND = 0x00; // "00"표시
333: uart_send_string_suman("100점이네요. ㅊㅋㅊㅋ\n\n");
334:
335: for(ucLoop = 0; 5 > ucLoop ; ++ucLoop) //LED깜빡깜빡
336: {
337: PORT_LED = ucLED; // 모두 OFF
338: sleep(500);
339: ToggleNumber(&ucLED);
340: PORT_LED = 0xFF; // 모두 ON
341: sleep(500);
342: }
343: }
344: else //100점이 아니면 현재 점수 보여줌.
345: {
346: PORT_LED = ucLED; // LED 모두 OFF
347: sleep(300); // 300ms 딜레이
348:
349: if(8 > ucScore)
350: {
351: game_over(ucScoreSum); // GAME OVER메세지와 EEPROM에 총점 기록.
352:
353:
354: break; // 메뉴로
355: }
356: }
357:
358: ucScore = 0; // 점수 초기화
359: gKey = 0; // 키값 리셋
360: }
361: }
362:
363:
364: void game_display_LED_SW(unsigned char cNum)
365: {
366: char aBuf[][18] = {"○○○○ ○○○○",
367: "○○○○ ○○○●",
368: "○○○○ ○○●○",
369: "○○○○ ○●○○",
370: "○○○○ ●○○○",
371: "○○○● ○○○○",
372: "○○●○ ○○○○",
373: "○●○○ ○○○○",
374: "●○○○ ○○○○"};
375:
376: uart_send_string_suman(aBuf + cNum);
377:
378: return ;
379: }
380:
381:
382: /******************************************************************************
383:
384: 게임 옵션 설정
385:
386: *******************************************************************************/
387: unsigned int game_option(void)
388: {
389: unsigned int uiDiff = 1000;
390: unsigned char ucBreak = 0;
391:
392: uart_send_byte(0x0C); //다음 페이지
393:
394: uart_send_string_suman("\n\n\n\n");
395: uart_send_string_suman("\t\t\t1. EASY\n");
396: uart_send_string_suman("\t\t\t2. NORMAL\n");
397: uart_send_string_suman("\t\t\t3. HARD\n");
398: uart_send_string_suman("\t\t\t4. EXIT\n");
399:
400:
401: sleep(1000); //1초 대기
402:
403: while(0 == ucBreak)
404: {
405: gKey = 0; //key값 초기화
406: sleep(100); //키입력 받을 시간.
407:
408: switch(gKey)
409: {
410: //1번
411: case 0x01:
412: uiDiff = 1000; //1초
413: uart_send_string_suman("\rEASY MODE! ");
414: break;
415:
416: //2번
417: case 0x02:
418: uiDiff = 750; //0.75초
419: uart_send_string_suman("\rNORMAL MODE!");
420: break;
421:
422: //3번
423: case 0x04:
424: uiDiff = 500; //0.5초
425: uart_send_string_suman("\rHARD MODE! ");
426: break;
427:
428: //4번
429: case 0x08:
430: ucBreak = 1; //탈출값.
431: break;
432:
433: default:
434: break;
435: }
436: }
437:
438: sleep(1000);
439:
440: return uiDiff; //난이도 값 반환
441: }
442:
443:
444: /******************************************************************************
445:
446: 순위 출력 및 초기화
447:
448: *******************************************************************************/
449: void game_rank(void)
450: {
451: unsigned char ucLoop;
452:
453: game_score();
454:
455: uart_send_string_suman("\n\n");
456: uart_send_string_suman("\t순위를 초기화하려면 적외선 센서를 막으세요.\n");
457: uart_send_string_suman("\t나가시려면 아무 키나 눌러주세요.");
458:
459: sleep(1000); //1초 대기
460:
461: gKey = 0; //키 값 초기화
462:
463: while(1)
464: {
465: if(0 == (0x80 & PIN_SENSOR)) //적외선 센서가 감지되면,
466: {
467: for(ucLoop = 0 ; 10 > ucLoop ; ++ucLoop)
468: {
469: eeprom_write(ucLoop, 0); //EEPROM 데이터 초기화 (0~10까지)
470: }
471:
472: game_score(); //점수 출력.
473:
474: break;
475: }
476:
477: if(0 != gKey) //아무 키나 누르면 탈출.
478: {
479: break;
480: }
481: }
482:
483: sleep(1000);
484:
485: return ;
486: }
487:
488:
489: void game_score(void)
490: {
491: unsigned char ucLoop;
492: unsigned char ucTemp;
493:
494:
495: uart_send_byte(0x0C); //다음 페이지
496:
497: uart_send_string_suman("\n\n\n\n");
498:
499: //1위 부터 10위까지 출력
500: for(ucLoop = 0 ; 10 > ucLoop ; ++ucLoop)
501: {
502: uart_send_string_suman("\t\t\t");
503:
504: ucTemp = eeprom_read(ucLoop);
505: printf_suman("%d. %d점\n", ucLoop + 1, ucTemp * 5, 0);
506: }
507:
508: return ;
509: }
510:
511: /******************************************************************************
512:
513: 게임 종료 함수.
514:
515: *******************************************************************************/
516: void game_exit(void)
517: {
518: uart_send_byte(0x0C);
519: uart_send_string_suman("\n\n\n\n\t\t\tGood Bye~");
520:
521: while(1); //일단 지금은 잡아둠. 나중에 종료되도록 할 것..
522:
523: return ;
524: }
525:
526:
527: /******************************************************************************
528:
529: GAME OVER
530:
531: *******************************************************************************/
532: void game_over(unsigned char ucScoreSum)
533: {
534: unsigned char ucLoop;
535: unsigned char ucTemp;
536:
537: uart_send_byte(0x0C);
538: uart_send_string_suman("\n\n\n\n\t\t\tGAME OVER");
539:
540: //점수를 정렬하며 EEPROM에 기록 1위~10위까지
541: eeprom_write(10, ucScoreSum); //제일 밑에 총점을 넣고
542:
543: for(ucLoop = 10 ; 0 < ucLoop ; --ucLoop)
544: {
545: if(eeprom_read(ucLoop) > eeprom_read(ucLoop - 1)) //바로 위에 수치와 비교하여,
546: {
547: ucTemp = eeprom_read(ucLoop - 1); //교체
548: eeprom_write(ucLoop - 1, eeprom_read(ucLoop));
549: eeprom_write(ucLoop, ucTemp);
550: }
551: }
552:
553: sleep(3000);
554:
555: return ;
556: }
557:
558:
559:
560: /*********************************************************************************
561: <초기화 함수들>
562:
563: 모두 상단의 전처리문을 참조해야 함.
564:
565: *********************************************************************************/
566: //I/O 포트 초기화
567: void init_port(void)
568: {
569: DDR_KEY = 0x00; // 모두 입력
570: DDR_SENSOR = 0x00; // 모두 입력
571: DDR_LED = 0xFF; // 모두 출력
572: DDR_FND = 0xFF; // 모두 출력
573: PORT_LED = 0xFF; // 모든 LED꺼짐.
574: PORT_FND = 0x00; // 00출력
575: DDR_BELL = 0xFF; // 모두 출력.
576: PORT_BELL = 0xFF; // 모두 FF
577:
578: return ;
579: }
580:
581:
582: //타이머0 초기화
583: void init_TC0(void)
584: {
585: //CTC Mode, prescanler = 1/64
586: TCCR0 = (1 << WGM01) | (1 << CS02);
587: //8bit Timer0 = 16,000,000 / 1000 / 64
588: // = 250
589: OCR0 = CPU_CLOCK / TICKS_PER_SEC / PRESCALER;
590: //타이머0 비교 매치 인터럽트 활성
591: TIMSK = (1 << OCIE0);
592:
593: return ;
594: }
595:
596: //UART1 초기화
597: void init_USART1(void)
598: {
599: //baud rate설정
600: UBRR1L = (unsigned char)BAUD_RATE_L;
601: UBRR1H = (unsigned char)BAUD_RATE_H;
602:
603: // no parity, 1stop bit, 8bit data설정
604: UCSR1C = (0 << UPM1) | (0 << UPM0) | (0 << USBS) | (1 << UCSZ1) | (1 << UCSZ0);
605: // rx/tx interrupt설정, 8bit설정
606: UCSR1B = (1 << TXEN) | (1 << RXEN) | (0 << UCSZ2);
607: // x2 speed
608: UCSR1A = (1 << U2X);
609:
610: return ;
611: }
612:
613:
614: /*>>>>>>>>>>>>>>>>>> 하드웨어와 밀접한 관련이 있는 함수들 (통신주변장치) <<<<<<<<<<<<<<<<<<<<*/
615:
616: //1바이트 수신함수
617: unsigned char USART_Receive(void) // ← 이름 바꿀까?
618: {
619: //RXC의 값이 0이어 수신버퍼가 비어 있으면 계속 대기.
620: while(!(UCSR1A & (1 << RXC)));
621:
622: return UDR1;
623: }
624:
625: //1바이트 전송함수
626: void uart_send_byte(unsigned char byte)
627: {
628: while(!(UCSR1A & (1 << UDRE))); //전송 버퍼가 빌 때까지 대기
629: UDR1 = byte; //문자1개를 전송한다.
630:
631: return ;
632: }
633:
634:
635: /*******************************************************
636: EEPROM에 데이터 읽기/쓰기 함수
637: *******************************************************/
638: void eeprom_write(unsigned int uiAddress, unsigned char ucData)
639: {
640: while(EECR & (1 << EEWE)); //쓰기 작업 중이면 루프
641:
642: EEAR = uiAddress; //쓸 주소 설정
643: EEDR = ucData; //쓸 데이터
644: EECR = EECR | (1 << EEMWE); //EEWE할 준비해라
645: EECR = EECR | (1 << EEWE); //쓰기 명령
646:
647: return ;
648: }
649:
650: unsigned char eeprom_read(unsigned int uiAddress)
651: {
652: while(EECR & (1 << EEWE)); //쓰기 작업 중이면 루프
653:
654: EEAR = uiAddress; //읽을 주소 설정
655: EECR = EECR | (1 << EERE); //읽기 명령
656:
657: return EEDR; //데이터 읽기
658: }
659:
660:
661:
662:
663: /**********************************************************************************************
664: <급조한 printf함수>
665:
666: 일정 포맷에 맞게 제작된 함수.
667: 3개의 10진수 입력만 받아 문자열로 변환하여 합성하여 출력. (1Byte크기의 정수)
668:
669: printf_suman("const char *", num1, num2, num3)
670:
671: <요구사항>
672: uart_send_string_suman()필요.
673:
674: 작 성 자: 김수만
675: 작성일자: 2011년 5월 23일
676:
677: **********************************************************************************************/
678: void printf_suman(char *cStr, unsigned char cNum1, unsigned char cNum2, unsigned char cNum3)
679: {
680: int i; //문자열 시작부터의 Offset값.
681: char cCnt = 0; //%d형식지정자에 전달할 값의 위치 기억.
682: char aStr[4]; //숫자를 문자로 바꿀 때 사용하는 문자배열
683:
684: for(i = 0 ; '\0' != *(cStr + i) ; ++i) //문자열의 끝까지 반복.
685: {
686: if('%' == *(cStr + i)) //형식지정자를 만나면
687: {
688: switch(cCnt)
689: {
690: //첫 번째 인자를 문자로 변환하여 출력.
691: case 0:
692: dec_to_ascii(cNum1, aStr);
693: uart_send_string_suman(aStr);
694: break;
695: //두 번째 인자를 문자로 변환하여 출력.
696: case 1:
697: dec_to_ascii(cNum2, aStr);
698: uart_send_string_suman(aStr);
699: break;
700: //세 번째 인자를 문자로 변환하여 출력.
701: case 2:
702: dec_to_ascii(cNum3, aStr);
703: uart_send_string_suman(aStr);
704: break;
705: //인자를 추가하려면 여기다 하이소.
706: default:
707: break;
708: }
709:
710: ++i; //다음 문자를 가리키도록 1증가.
711: ++cCnt; //다음 인자를 가리키도록 1증가.
712: }
713: else //형식지정자가 아닌 일반 문자이면,
714: { //문자를 출력.
715: if('\n' == *(cStr + i))
716: {
717: uart_send_byte('\r'); //개행문자를 만나면,
718: uart_send_byte('\n'); //케리지리턴 + 라인피드
719: }
720: else
721: {
722: uart_send_byte(*(cStr + i)); //시작번지로 부터 i번째 문자 전송.
723: }
724: }
725: }
726:
727: return ;
728: }
729:
730: //문자열 전송함수 len은 문자열의 길이.
731: void uart_send_string(unsigned char *str, unsigned int len)
732: {
733: int i;
734:
735: for(i = 0 ; i < len ; i++) //문자열의 길이만큼 반복.
736: {
737: uart_send_byte(*(str + i)); //시작번지로 부터 i번째 문자 전송.
738: }
739:
740: return ;
741: }
742:
743: //문자열 전송함수(수만)
744: void uart_send_string_suman(char *cStr)
745: {
746: int i; //Offset
747:
748: for(i = 0 ; '\0' != *(cStr + i) ; ++i) //NULL문자까지 반복.
749: {
750: if('\n' == *(cStr + i)) //개행문자를 만나면,
751: {
752: uart_send_byte('\r'); //캐리지 리턴후에
753: uart_send_byte('\n'); //라인 피드
754: }
755: else
756: {
757: uart_send_byte(*(cStr + i)); //시작번지로 부터 i번째 문자 전송.
758: }
759: }
760:
761: return ;
762: }
763:
764:
765: /*>>>>>>>>>>>>>>>>>>>>> 어느 하드웨어에나 이식이 자유로운 수치처리함수 <<<<<<<<<<<<<<<<<<<<<<*/
766:
767:
768: //16진수를 10진수로 바꾸는 함수 (100미만의 값만 취급한다.)
769: unsigned char hex_to_dec(unsigned char cNum)
770: {
771: unsigned char temp;
772:
773: //실제 16진수가 아닌 10진수를 16진수로 취급하여,
774: //10의 자리 잘라내 곱하기 16 + 1의 자리.
775: temp = (cNum / 10) * 16 + (cNum % 10);
776:
777: return temp;
778: }
779:
780: //정수를 문자로 바꾸는 함수. (0~255까지만 취급함.)
781: void dec_to_ascii(unsigned char cNum, char *p)
782: {
783: unsigned char ucLoop = 3;
784:
785: *(p + ucLoop) = '\0'; //문자열끝.
786:
787: for(; 0 < ucLoop ; --ucLoop)
788: {
789: *(p + ucLoop - 1) = (cNum % 10) + '0'; //일자리부터 백자리까지 저장 후 문자로 변환.
790: cNum = cNum / 10; //일자리부터 10단위로 잘라냄.
791: }
792:
793: //숫자 앞에 0을 없애는 부분.
794: for(ucLoop = 0 ; 2 > ucLoop ; ++ucLoop)
795: {
796: if('0' == *(p + ucLoop)) //현재 자리가 '0'이면,
797: {
798: if(0 == ucLoop) //첫 번째 자리에는,
799: {
800: *(p + ucLoop) = ' '; //공백문자로 만들어 버림.
801: }
802: else if((0 != ucLoop) && (2 != ucLoop) && (' ' == *(p + ucLoop - 1)))
803: { //첫 번째와 마지막자리를 제외한 자리에는,
804: *(p + ucLoop) = ' '; //공백문자로 만들어 버림.
805: }
806: else //마지막자리는,
807: {
808: *(p + ucLoop) = '0'; //'0'으로 만들어 버림.
809: }
810: }
811: }
812:
813: return ;
814: }
815:
816:
817: //log2 N의 값을 구함. (128~0 -> 8~0)
818: char log_2(unsigned char cNum)
819: {
820: unsigned char ucLoop = 0; //log2 N에서 N의 값이 0이면 0이다.
821:
822: //계속 2로 나누어 나눈 횟수를 반환.
823: while(cNum >= 1)
824: {
825: cNum = cNum / 2;
826: ucLoop++;
827: }
828:
829: return ucLoop;
830: }
831:
832: //입력 받은 숫자 반전. (변수의 주소를 참조해 1의 보수를 취함.)
833: void ToggleNumber(unsigned char * state)
834: {
835: *state = ~*state; //반전
836:
837: return ;
838: }