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문 사용)

image

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:  }

 

image

   1:  for(i = 4 ; i > 0 ; i--)
   2:  {
   3:      for(j = 0 ; j < i ; j++)
   4:      {
   5:          printf("  ");
   6:      }
   7:      printf("*\n");
   8:  }

 


● 4번...삼각형 출력

image

   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번...알파벳삼각형

image

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:   

 

<실행결과>
clip_image002

 

 

3. 문제에 나온 그림대로 출력하세요. (중첩 for문 사용)

1)
  *            *
     *      *
       *  *
         *
       *  *
     *      *
  *            *

<해법찾기>
image

   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:   

 

<실행결과>
clip_image002[4]

 

 

2)
           *
        *    *
     *          *
   *              *
     *          *
        *     *
           *

<해법찾기>
 image

행을 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:   

<실행결과>
clip_image002[6]

 

 

[도전] 정수 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:  }

 

<실행결과>
clip_image002[8]clip_image004clip_image006clip_image008

참조: http://pythagoras0.springnote.com/pages/4544355

 

 

               ATmega128 ↔ PC간 양방향 시리얼통신                

image

<상태체크>
① 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제어

image

하이퍼터미널에서 입력한 키를 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)                               

소수관련 참조: http://pythagoras0.springnote.com/pages/4544355

DSCN3016DSCN3017DSCN3018DSCN3019