2015년 6월 20일 토요일

ATmega8(A) 포트를 이용한 LED 실험 (Part 2)

 여기에서는 이전 포스트에 이어서 포트를 이용한 LED 실습을 진행한다.

LED실험 2
 두 번째 LED실험도 앞의 실험과 비슷하다. 이번에는 다음과 같은 순서로 1→2→3→4→1→2→3→4→1→… 계속 시차를 두고 반복하는 실험이다.


[표 1] 두 번째 LED 실험
순서
LED상태
이진수
16진수
1
●●●○○●●●
0b00011000
0x18
2
●●○●●○●●
0b00100100
0x24
3
●○●●●●○●
0b01000010
0x42
4
○●●●●●●○
0b10000001
0x81


프로그램 예는 다음과 같다.


#define F_CPU 16000000
#include <avr/io.h>
#include <util/delay.h>
#include "Am8USBasp.h"
int main(void) {
   uchar ucA, ucaRelay[4] = {0x18, 0x24, 0x42, 0x81};
   InitAM8();
   while(1) {
       for (ucA=0; ucA<4; ucA++) {
           LED(ucaRelay[ucA]);
           _delay_ms(200);
       }
   }
}


이 예를 보면 typedef 명령어로 unsigned char형은 byte형으로 재정의하였으며 앞으로도 이것은 계속 사용할 것이다. 그리고 LED로 순차적으로 내보낼 데이터는 배열로 처리하였음을 눈여겨 보기 바란다.


LED실험 3

 다음 [표 2]에 설명한 바와 같이 1→2→ … →13→14→1→2→ … 의 순서로 14가지 패턴을 반복하면 마치 LED한개가 좌우로 왕복하는 듯이 보이는 예제이다. 이 세 번째 LED실험은 앞의 것들과 달리 조금 복잡해 보인다.


[표 2] 세 번째 LED 실험
순서
LED상태
이진수
16진수
1
●●●●●●●○
0b00000001
0x01
2
●●●●●●○●
0b00000010
0x02
3
●●●●●○●●
0b00000100
0x04
4
●●●●○●●●
0b00001000
0x08
5
●●●○●●●●
0b00010000
0x10
6
●●○●●●●●
0b00100000
0x20
7
●○●●●●●●
0b01000000
0x40
8
○●●●●●●●
0b10000000
0x80
9
●○●●●●●●
0b01000000
0x40
10
●●○●●●●●
0b00100000
0x20
11
●●●○●●●●
0b00010000
0x10
12
●●●●○●●●
0b00001000
0x08
13
●●●●●○●●
0b00000100
0x04
14
●●●●●●○●
0b00000010
0x02


 이번 프로그램을 이전 실험과 같이 14개의 데이터를 포트에 순차적으로 내보내는 식으로 프로그램을 작성할 수도 있으나 그렇게 하면 너무 비효율적인 프로그램이 된다. 그래서 비트이동 연산자와 반복문을 이용하면 좀 더 간단하게 프로그램이 가능하다. 프로그램 예는 다음과 같다.


#define F_CPU 16000000
#include <avr/io.h>
#include <util/delay.h>
#include "Am8USBasp.h"
typedef enum DIR {UP, DOWN} EDIR;
int main(void) {
   uchar ucLed = 1;
   EDIR eDir = UP;
   InitAM8();
   while(1) {
       if (eDir == UP) {
           ucLed <<= 1;
           if (ucLed == 0x80)
               eDir = DOWN;
       } else { // if (eDir == DOWN)
           ucLed >>= 1;
           if (ucLed == 0x01)
           eDir = UP;
       }
       LED(ucLed);
       _delay_ms(200);
   }
}


LED실험 4 : LED탑 쌓기

 마지막으로 아래와 같은 패턴을 보여주는 프로그램을 작성해보자. 벽돌로 하나씩 탑을 쌓는 것처럼 보여서 ‘LED 탑 쌓기’실험이라고 이름을 붙여 보았다.


[표 3] 네 번째 LED 실험
순서
LED상태
이진수
16진수
1
○●●●●●●●
0b01111111
0x7F
2
●○●●●●●●
0b10111111
0xBF
3
●●○●●●●●
0b11011111
0xDF
4
●●●○●●●●
0b11101111
0xEF
5
●●●●○●●●
0b11110111
0xF7
6
●●●●●○●●
0b11111101
0xFB
7
●●●●●●○●
0b11111110
0xFD
8
●●●●●●●○
0b11111110
0xFE
9
○●●●●●●○
0b01111111
10
●○●●●●●○
0b10111111
11
●●○●●●●○
0b11011111
12
●●●○●●●○
0b11101111
13
●●●●○●●○
0b11110111
14
●●●●●○●○
0b11111101
15
●●●●●●○○
0b11111110
16
○●●●●●○○
0b01111111
17
●○●●●●○○
0b10111111
18
●●○●●●○○
0b11011111
19
●●●○●●○○
0b11101111
20
●●●●○●○○
0b11110111
21
●●●●●○○○
0b11111101
22
○●●●●○○○
0b11111110


이 실험은 이제 포트에 데이터를 순차적으로 내보내는 식으로는 프로그램이 거의 불가능하다. 이번에도 역시 비트이동연산자와 반복문을 조합하여 프로그램을 작성할 수 있다.


#define F_CPU 16000000
#include <avr/io.h>
#include <util/delay.h>
#include "Am8USBasp.h"
int main(void) {
  uchar ucaLEDTower[8] = {0x00, 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F };
   uchar ucled, uck, ucl;
   InitAM8();
   while (1) {
       for (uck=0;uck<8;uck++) {
           ucled = 0x80;
           for (ucl=0;ucl<8-uck;ucl++) {
               LED( ucled | ucaLEDTower[uck] );
               _delay_ms(200);
               ucled >>= 1;
           }
       }
   }
}


위 프로그램은 길이는 짧지만 한 줄씩 읽어가면서 분석해 볼 여지가 있다. 다중 반복문을 사용하고 있는데 내부 반복문에서는 LED가 위에서 아래로 한 칸씩 떨어지는 것을 비트쉬프트 연산자로 처리하고 있으며 이 때 PORTB로 내보내는 데이터를 배열 byaLEDTower[]과 OR연산을 하여 마치 벽돌이 쌓여 있는 듯한 효과를 내는 것이다. 배열 byaLEDTower[]은 벽돌이 쌓인 모양의 데이터를 가지고 있다. 바깥 반복문에서는 떨어지는 루틴을 8번 반복하게끔 하는데 떨어지는 곳의 높이를 점차로 높인다.


 이번 포스트에서는 LED를 이용하여 간단한 예제들을 살펴보았다. 독자가 C언어의 문법을 잘 숙지하고 있다면 어떻게 동작이 되는지 쉽게 분석해 볼 수 있을 것이다.



댓글 없음:

댓글 쓰기