레이블이 LED인 게시물을 표시합니다. 모든 게시물 표시
레이블이 LED인 게시물을 표시합니다. 모든 게시물 표시

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언어의 문법을 잘 숙지하고 있다면 어떻게 동작이 되는지 쉽게 분석해 볼 수 있을 것이다.