2011년5월20일_C과제4 풀이, C과제5, ATmega128 ↔ PC간 양방향직렬통신, 숫자만 입력받아 LED에 출력
★코딩 전 문제에 대한 분석이 선행되어야 함.
C과제4 풀이
● 1번 – 생략
● 2번...절대값출력.
~N + 1 (2의 보수) 연산을 수행하면 양수는 음수로 음수는 양수로 바뀐다.
1: if(num < 0)
2: {
3: num = (~num) + 1; //num값의 2의 보수를 구해 num에 저장
4: }
● 3번...미끄럼틀 출력(중첩for문 사용)
i는 행, j는 열
1: //선생님꺼...사진과 다름
2: for(i = 0 ; i < 5 ; i++)
3: {
4: for(j = 0 ; j < i ; j++)
5: {
6: printf(" ");
7: }
8: printf("*\n");
9: }
1: for(i = 4 ; i > 0 ; i--)
2: {
3: for(j = 0 ; j < i ; j++)
4: {
5: printf(" ");
6: }
7: printf("*\n");
8: }
● 4번...삼각형 출력
1: scanf("%d", &num);
2:
3: for(i = 0 ; i < num ; i++)
4: {
5: for(j = 0 ; j <= i ; j++)
6: {
7: printf("*");
8: }
9: printf("\n\n");
10: }
● 5번...알파벳삼각형
num에 5를 입력하면,
j는 0부터 4까지 1씩 증가하므로,
대문자 알파벳에 해당되는 ASCII인 65를 더하면 A, B, C, D, E까지 출력이 됨.
65대신 ‘A’문자를 넣어도 됨. 가독성이 더 높아질듯.
1: scanf("%d", &num);
2:
3: for(i = 0 ; i < num ; i++)
4: {
5: for(j = 0 ; j <= i ; j++)
6: {
7: printf("%3c", j + 65);
8: }
9: printf("\n");
10: }
C과제5
1. 조건식의 결과는 참과 거짓, 둘 중 하나입니다.
N이 5일 경우, 다음 조건은 거짓입니까? 참입니까?
1) N & 1 답: 참 5는 이진수로 101 & 001 = 1 이므로 0이 아니니 참.
2) (N > 0) && (N < 6) 답: 참 5는 0보다 크고 6보다 작으므로 참.
3) N % 5 답: 거짓 5를 5로 나누면 나머지는 0이므로 거짓.
4) N ^ 0x05 답: 거짓 101과 101을 XOR연산하면 서로 같으므로 0이 되어 거짓.
<풀이>
N = 5;
1) N & 1
N => 0000 0000 0000 0000 0000 0000 0000 0101
& 0000 0000 0000 0000 0000 0000 0000 0001
0000 0000 0000 0000 0000 0000 0000 0001 => 결과는 0x00000001
그러므로, 0이 아니니 참이다.
2) (N > 0) && (N < 6)
(N > 0) -> (5 > 0) -> (1) -> 참.
(N < 6) -> (5 < 6) -> (1) -> 참.
(1) && (1) -> (1) -> 참
Note: (1)은 논리가 참이라는 뜻이고 값이 1이라는 뜻이 아님. (내가 무슨 글을 적은 거지;;;)
3) N % 5
N % 5 -> 5 % 5 -> 0 –> 거짓
4) N ^ 0x05
N ^ 0x05 -> 5 ^ 0x05 -> 0x05 XOR 0x05 -> 아래와 같이 이진수로 보면,
0000 0000 0000 0000 0000 0000 0000 0101
XOR 0000 0000 0000 0000 0000 0000 0000 0101
0000 0000 0000 0000 0000 0000 0000 0000 => 결과는 0x00000000
그러므로, 0이니 거짓이다.
2. 다음과 같은 형태로 문자열이 출력되는 프로그램을 작성하시오. (중첩 for문 사용)
a
b a
c b a
d c b a
e d c b a
1: /*************************************************************
2: 2. 다음과 같은 형태로 문자열이 출력되는
3: 프로그램을 작성하시오. (중첩 for문 사용)
4: a
5: b a
6: c b a
7: d c b a
8: e d c b a
9:
10: 소 속: 내장형하드웨어
11: 작 성 자: 김수만
12: 작성일자: 2011년 5월 20일
13:
14: **************************************************************/
15: #include <stdio.h>
16:
17: int main()
18: {
19: int iRow; //행
20: int iCol; //열
21:
22: for(iRow = 0 ; 5 > iRow ; ++iRow)
23: {
24: for(iCol = 4 ; 0 <= iCol ; --iCol)
25: {
26: if(iRow >= iCol)
27: {
28: printf("%c\t", iCol + 'a'); //'a'부터 'e'까지
29: }
30: else
31: {
32: printf("\t");
33: }
34: }
35:
36: printf("\n");
37: }
38:
39: return 0;
40: }
41:
3. 문제에 나온 그림대로 출력하세요. (중첩 for문 사용)
1)
* *
* *
* *
*
* *
* *
* *
1: /*************************************************************
2: 3. 문제에 나온 그림대로 출력하세요. (중첩 for문 사용)
3: 1)
4: * *
5: * *
6: * *
7: *
8: * *
9: * *
10: * *
11:
12: 소 속: 내장형하드웨어
13: 작 성 자: 김수만
14: 작성일자: 2011년 5월 20일
15:
16: **************************************************************/
17: #include <stdio.h>
18:
19: int main()
20: {
21: int iRow; //행
22: int iCol; //열
23:
24: for(iRow = 0 ; 7 > iRow ; ++iRow)
25: {
26: for(iCol = 0 ; 7 > iCol ; ++iCol)
27: {
28: //행과 열이 같거나 합이 6이되면 *표시
29: if(iRow == iCol || (iRow + iCol) == 6)
30: {
31: printf("%3c", '*');
32: }
33: else
34: {
35: printf("%3c", ' ');
36: }
37: }
38: printf("\n");
39: }
40:
41: return 0;
42: }
43:
2)
*
* *
* *
* *
* *
* *
*
행을 y라 하고, 열을 x라고 하였을 때, (x, y)표시
① 좌표(0, 3) 에서 (3, 6)으로 올라가는 직선의 식은 1차식으로 다음과 같다,
y = x + 3
y – 3 과 x가 같으면 되므로 이를 조건문으로 바꾸면,
if((iRow - 3) == iCol)
② 좌표(3, 0) 에서 (6, 3)으로 올라가는 직선의 식은 1차식으로 다음과 같다,
y = x - 3
y + 3 과 x가 같으면 되므로 이를 조건문으로 바꾸면,
if((iRow + 3) == iCol)
③ 좌표(0, 3) 에서 (3, 0)으로 내려가는 직선의 식은 1차식으로 다음과 같다,
y = -x + 3
3 - y 와 x가 같으면 되므로 이를 조건문으로 바꾸면,
if((3 - iRow) == iCol)
④ 좌표(3, 6) 에서 (6, 3)으로 내려가는 직선의 식은 1차식으로 다음과 같다,
y = -x + 9
9 - y 와 x가 같으면 되므로 이를 조건문으로 바꾸면,
if((9 - iRow) == iCol)
① ~ ④까지 조건문을 합치면,
1: if(iCol == (9 - iRow) || iCol == (iRow - 3) || iCol == (3 - iRow) || iCol == (iRow + 3))
2: {
3: printf(" * ");
4: }
5: else
6: {
7: printf(" ");
8: }
가로로 너무 길어지므로 아래와 같이 소스코드를 보기 좋게 하면 된다.
1: /*************************************************************
2: 3. 문제에 나온 그림대로 출력하세요. (중첩 for문 사용)
3: 2)
4: *
5: * *
6: * *
7: * *
8: * *
9: * *
10: *
11:
12: 소 속: 내장형하드웨어
13: 작 성 자: 김수만
14: 작성일자: 2011년 5월 20일
15:
16: **************************************************************/
17: #include <stdio.h>
18:
19: int main()
20: {
21: int iRow; //행
22: int iCol; //열
23:
24: for(iRow = 6 ; 0 <= iRow ; --iRow)
25: {
26: for(iCol = 0 ; 7 > iCol ; ++iCol)
27: {
28: if(iCol == (9 - iRow) ||
29: iCol == (iRow - 3) ||
30: iCol == (3 - iRow) ||
31: iCol == (iRow + 3))
32: {
33: printf(" * ");
34: }
35: else
36: {
37: printf(" ");
38: }
39: }
40: printf("\n");
41: }
42:
43: return 0;
44: }
45:
[도전] 정수 N은 소수입니까?
출력) 정수 입력 : 97
결과 : 소수
정수 입력 : 1
결과 : 소수가 아닙니다.
정수 입력 : 91
결과 : 합성수[7]
정수 입력 : –1
프로그램 종료!
<해법찾기>
소수는 1과 자신 이외의 약수를 가지지 않는 자연수이니,
1이하는 무조건 소수가 아닌 것으로 취급하고,
2로 나누기 시작해서 (입력한 수 – 1)까지 나머지가 0인지 검사하여 0이면 나누어 떨어졌으므로 소수가 아니다.
끝까지 나머지가 0이 아니었다면 소수다.
합성수출력 시 대괄호 안의 수치는 최소 약수이다. 최초 0으로 나누어 떨어진 수를 구하면 되겠다.
1: /*************************************************************
2: [도전] 정수 N은 소수입니까?
3:
4: 출력) 정수 입력 : 97
5: 결과 : 소수
6:
7: 정수 입력 : 1
8: 결과 : 소수가 아닙니다.
9:
10: 정수 입력 : 91
11: 결과 : 합성수[7]
12:
13: 정수 입력 : -1
14: 프로그램 종료!
15:
16:
17: 소 속: 내장형하드웨어
18: 작 성 자: 김수만
19: 작성일자: 2011년 5월 20일
20:
21: **************************************************************/
22: #include <stdio.h>
23:
24: //소수판별함수
25: //compare의 뜻인 비교라 어울리지 않음. 판별철자는 어려움.
26: int compare_prime_number(int iNum);
27:
28: int main()
29: {
30: int iNum;
31: int iFlag_prime = 0; //합성수이면 1로 세트
32:
33: while(1)
34: {
35: printf("\n정수 입력: ");
36: scanf("%d", &iNum);
37:
38: if(-1 == iNum) //if(0 > iNum)으로 바꿀 것.
39: {
40: break;
41: }
42:
43: iNum = compare_prime_number(iNum); //소수인지 아닌지 알아냄.
44:
45: if(0 == iNum) //0으로 소수이다.
46: {
47: printf("결과 : 소수\n");
48: }
49: else if(1 == iNum) //1이니 소수가 아니네.
50: {
51: printf("결과 : 소수가 아닙니다.\n");
52: }
53: else //합성수구나...
54: {
55: printf("결과 : 합성수[%d]\n", iNum);
56: }
57: }
58:
59: printf("프로그램 종료!\n");
60:
61: return 0;
62: }
63:
64: /************************************************************
65: 소수인지 판별하는 함수
66: 리턴값으로,
67: 0 - 소수
68: 1 - 소수가 아님. 1이다. 0
69: 2 - 합성수
70: 2부터는 합성수의 원소? 배수?를 나타냄.
71: *************************************************************/
72: int compare_prime_number(int iNum)
73: {
74: int iLoop = 2; //2부터 나누기 시작.
75:
76: while(iNum > iLoop) //2이하는 들어 올 수 없음. 애들은 가라~
77: {
78: if(0 == iNum % iLoop) //나누어 나머지가 0이면 나누어 지므로
79: {
80: iNum = iLoop; //나눈 수를 반환하고,
81: return iNum; //종료 [합성수]리턴
82: }
83:
84: ++iLoop; //나눌 수를 증가시킴.
85: }
86:
87: if(2 > iNum) //2이하인 경우
88: {
89: iNum = 1; //소수가 아님. [1]리턴
90: }
91: else
92: {
93: iNum = 0; //소수. [0]리턴.
94: }
95:
96: return iNum;
97: }
참조: http://pythagoras0.springnote.com/pages/4544355
ATmega128 ↔ PC간 양방향 시리얼통신
<상태체크>
① UCSR1A 레지스터의 5번 비트 UDRE1이 1이면 송신버퍼가 비어 있음.
UCSR1A 레지스터의 5번 비트 UDRE1이 0이면 아직 전송 중.
② UCSR1A 레지스터의 7번 비트 RXC1이 1이면 수신버퍼가 차서 데이터가 들어 있음.
UCSR1A 레지스터의 7번 비트 RXC1이 0이면 수신된 데이터가 없음.
○ 수신대기
while(!(UCSR1A & (1 << RXC)));
수신X → 0XXX XXXX
& 1000 0000
0000 0000 (거짓) -> 부정 –> (참) –> 대기
수신O → 1XXX XXXX
& 1000 0000
1000 0000 (참) –> 부정 –> (거짓) –> 데이터가 들어 왔으니 받을 명령실행
○ 값읽기
1: return UDR; //R24 ← 수신버퍼
2: //또는
3: buffer = UDR; //변수 ← 수신버퍼
데이터수신함수를 만들었을 땐 1행과 같이 UDR값을 리턴하면 되고,
main()에 삽입 시엔 변수에 저장하면 된다.
○ 1Byte 수신함수
1: //1바이트 수신함수
2: unsigned char USART_Receive(void)
3: {
4: while(!(UCSR1A & (1 << RXC)));
5:
6: return UDR1;
7: }
직렬포트로 값을 입력 받아 LED제어 |
하이퍼터미널에서 입력한 키를 COM1포트를 통해 DK128보드로 전송하고,
ATmega128 MCU는 이를 수신하여 아래의 C Code와 같은 반전처리를 하여 사람이 보기 좋게 LED에 출력한다.
1: while(1)
2: {
3: ch = USART_Receive(); //수신된 값을 저장.
4: PORT_LED = ch ^ 0xFF; //ch값을 반전하여 LED에 출력. 풀업이니 부논리.
5: PORT_FND = ch; //ch값을 그대로 FND에 출력. 정논리.
6: uart_send_byte(ch); //수신된 값을 돌려줌. (echo)
7: }
만약 0x31(‘1’)이 입력되었다면,
0011 0001
XOR 1111 1111
1100 1110 → 입력된 0x31의 반전된 0xCE가 출력된다. LED는 5, 4, 0번만 켜진다.
LED에 켜진 2진수값을 16진수값으로 표시하면...
하이퍼터미널에서 친 키 | 16진수값 | 표시 |
0 ~ 9 | 0x30 ~ 0x39 | 0 ~ 9 |
A ~ Z | 0x41 ~ 0x5A | A ~ Z |
a ~ z | 0x61 ~ 0x7A | a ~ z |
Ctrl + a | 0x01 | ┌ |
Ctrl + b | 0x02 | ┐ |
Ctrl + c | 0x03 | └ |
Ctrl + d | 0x04 | ┘ |
Ctrl + e | 0x05 | 변화x |
Ctrl + f | 0x06 | ─ |
Ctrl + g | 0x07 | 변화x |
Ctrl + h | 0x08 | backspace누른 효과 |
Ctrl + i | 0x09 | TAB처럼 들여쓰기 |
Ctrl + j | 0x0A | LF (다음 줄로) |
Ctrl + k | 0x0B | VT (다음 줄로??) |
Ctrl + l | 0x0C | FF (다음 페이지) |
Ctrl + m | 0x0D | CR (첫 열로) |
Ctrl + n | 0x0E | ♬ |
Ctrl + o | 0x0F | (태양모양) |
숫자만 입력 받아 LED에 출력
1: while(1) //무한루프
2: {
3: ch = USART_Receive(); //데이터수신
4:
5: if(0x30 < ch && 0x39 > ch) //숫자키 범위만 필터
6: {
7: ch = ch - 0x31; //0x30을 빼면 문자->숫자 됨.
8: PORT_LED = ~(1 << ch); //0 ~ 7사이의 값만 표시.
9: //시프트하면 하나만 들어옴.
10: }
11: else //숫자키 이외는 LED를 OFF시킴.
12: {
13: PORT_LED = 0xFF;
14: }
15:
16: PORT_FND = ch; //FND는 그대로 출력. (정논리)
17: }
입력한 키 | LED상태 |
‘1’ | ●●●● ●●●○ |
‘2’ | ●●●● ●●○● |
‘3’ | ●●●● ●○●● |
‘4’ | ●●●● ○●●● |
‘5’ | ●●●○ ●●●● |
‘6’ | ●●○● ●●●● |
‘7’ | ●○●● ●●●● |
‘8’ | ○●●● ●●●● |
그 외 | ●●●● ●●●● (모두 OFF) |
Ctrl+C, Ctrl+V신공!!
참조 (Reference)
'내장형하드웨어 > 일일보고서' 카테고리의 다른 글
2011년5월24일_두더지게임2 소스코드의 주석을 보기 좋게 정리함 (0) | 2011.05.25 |
---|---|
2011년5월23일_두더지 잡기 게임2, 문자열 처리 함수(숫자를 문자로 변환) (0) | 2011.05.24 |
2011년5월19일...ATmega128 -> PC(단방향직렬통신), (0) | 2011.05.19 |
2011년5월18일...시리얼통신복습, C과제3풀이, C과제4 (0) | 2011.05.19 |
2011년5월17일...Eltima Software Virtual Serial Port Driver, C과제2풀이, C과제3 (0) | 2011.05.18 |