[Embedded Software] 경희대 임베디드 소프트웨어 과제2 - FND

경희대학교 컴퓨터공학과 조진성 교수님의 ‘임베디드 소프트웨어’ 강의의 과제입니다.


개발 환경




실습 3


3.1 FND(Flexible Numeric Display: 7-Segment LED)를 이용하여 특정 숫자를 표시해보기(8888)

#define F_CPU 16000000UL

#include <avr/io.h>
#include <util/delay.h>

int main() {
	// FND에서 표시할 수 있는 문자를 배열로 미리 정의
	unsigned char FND_DATA[ ]= {0x3f, 0x06, 0x5b, 0x4f, 0x66,
                              0x6d, 0x7d, 0x27, 0x7f, 0x6f,
                              0x77, 0x7c, 0x39, 0x5e, 0x79,
                              0x71, 0x80, 0x40, 0x08};

	// FND의 LED는 C포트에 연결되어 있으며,
	// FND의 상태를 결정짓는 것은 G포트의 끝의 두 비트이다.
	DDRC = 0xFF;
	DDRG = 0x0F;

	while(1) {
		// FND는 output으로 사용되기 때문에 PORT를 사용한다.
		PORTC = FND_DATA[8];
		PORTG = 0x0f;
	}
}


3.2 FND의 1개만 특정 숫자를 표시해 보기(7)

#define F_CPU 16000000UL

#include <avr/io.h>
#include <util/delay.h>

int main() {
	unsigned char FND_DATA[ ]= {0x3f, 0x06, 0x5b, 0x4f, 0x66,
                              0x6d, 0x7d, 0x27, 0x7f, 0x6f,
                              0x77, 0x7c, 0x39, 0x5e, 0x79,
                              0x71, 0x80, 0x40, 0x08};
	DDRC = 0xFF;
	DDRG = 0x0F;

	while(1) {
		PORTC = FND_DATA[7];
		PORTG = 0x01;
	}
}


3.3 FND의 4개 숫자를 각각 다르게 표시해 보기 (AbCd)

#define F_CPU 16000000UL

#include <avr/io.h>
#include <util/delay.h>

int main() {
	unsigned char FND_DATA[ ]= {0x3f, 0x06, 0x5b, 0x4f, 0x66,
                              0x6d, 0x7d, 0x27, 0x7f, 0x6f,
                              0x77, 0x7c, 0x39, 0x5e, 0x79,
                              0x71, 0x80, 0x40, 0x08};
	DDRC = 0xFF;
	DDRG = 0x0F;

	while(1) {
		// 4개의 FND에 서로 다른 값을 넣기 위해
		// _delay_ms()를 사용한다.
		// 사람의 눈이 인식하지 못할 정도의 딜레이를 주면
		// 4개의 FND 동시에 작동하는 것처럼 보이게 할 수 있다.
		PORTC = FND_DATA[13];
		PORTG = 0x01;
		_delay_ms(2);

		PORTC = FND_DATA[12];
		PORTG = 0x02;
		_delay_ms(3);

		PORTC = FND_DATA[11];
		PORTG = 0x04;
		_delay_ms(2);

		PORTC = FND_DATA[10];
		PORTG = 0x08;
		_delay_ms(3);
	}
}


3.4 FND를 사용하여 1ms마다 1씩 증가하는 1/100 초시계를 만든다.

#define F_CPU 16000000UL

#include <avr/io.h>
#include <util/delay.h>

int main() {
	unsigned char FND_DATA[ ]= {0x3f, 0x06, 0x5b, 0x4f, 0x66,
                              0x6d, 0x7d, 0x27, 0x7f, 0x6f};
	unsigned int time = 0, time0, time1, time2, time3;

	DDRC = 0xFF;
	DDRG = 0x0F;

	while(1) {
		// time이 계속 증가하면서 자릿수를 바꾸기 위해 다음과 같이 정의한다.
		time++;
		time3 = (time/1000)%10;
		time2 = (time/100)%10;
		time1 = (time/10)%10;
		time0 = time%10;

		// 1/100 초 단위
		PORTC = FND_DATA[time0];
		PORTG = 0x01;
		_delay_ms(2);
	
		// 1/10 초 단위
		PORTC = FND_DATA[time1];
		PORTG = 0x02;
		_delay_ms(3);

		// 1초 단위
		// FND의 점(0x80)을 찍어 자릿수를 구분하였다.
		PORTC = FND_DATA[time2] | 0x80;
		PORTG = 0x04;
		_delay_ms(2);

		// 10초 단위
		PORTC = FND_DATA[time3];
		PORTG = 0x08;
		_delay_ms(3);
	}
}


3.5 FND로 문장 표시해 보기

#define F_CPU 16000000UL

#include <avr/io.h>
#include <util/delay.h>

int main() {
	// '042-486-0761'이라는 숫자가 한 글자씩 나타나다가,
	// 끝까지 디스플레이 되면 왼쪽으로 한 칸씩 이동하여 표시하기 위한 배열이다.
	// 처음 전압이 공급되었을 때 부터, 숫자가 오른쪽 끝에서 나오게 하기 위해
	// 앞에 0x00을 3개 두어 초기화를 하였다.
	// 마지막에 하나씩 사라질 때도 마찬가지이다. 
	unsigned char WORD_DATA[ ]= {0x00, 0x00, 0x00, 0x3f, 0x66,
                              0x5b, 0x40, 0x66, 0x7f, 0x7d,
                              0x40, 0x3f, 0x27, 0x7d, 0x06,
                              0x00, 0x00, 0x00, 0x00};
															 
	unsigned char count = 0, word0, word1, word2, word3;
	unsigned int i, j;
	DDRC = 0xFF;
	DDRG = 0x0F;

	while(1) {
		for(i = 0; i < 16; i++) {
			word0 = count % 16;
			word1 = (count % 16) + 1;
			word2 = (count % 16) + 2;
			word3 = (count % 16) + 3;

			for(j = 0; j < 100; j++) {
				PORTC = WORD_DATA[word0];
				PORTG = 0x08;
				_delay_ms(2);

				PORTC = WORD_DATA[word1];
				PORTG = 0x04;
				_delay_ms(3);

				PORTC = WORD_DATA[word2];
				PORTG = 0x02;
				_delay_ms(2);

				PORTC = WORD_DATA[word3];
				PORTG = 0x01;
				_delay_ms(3);
			}
			count++;
		}
	}
}


실습 응용


문제: FND로 1시간짜리 분/초 시계 만들어 보기

조건 : 왼쪽 2개는 분 표시, 오른쪽 2개는 초 표시. 가운데 점도 표시

#define F_CPU 16000000UL

#include <avr/io.h>
#include <util/delay.h>

int main() {
   unsigned char TEN_DATA[ ]= {0x3f, 0x06, 0x5b, 0x4f, 0x66,
                              0x6d, 0x7d, 0x27, 0x7f, 0x6f};
   unsigned char SIX_DATA[ ]= {0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d};
   unsigned int time = 0;
   unsigned int sec0 = 0;
   unsigned int sec1 = 0;
   unsigned int min0 = 0;
   unsigned int min1 = 0;

   DDRC = 0xFF;
   DDRG = 0x0F;

   while(1) {
      time++;
      sec0 = (time/100)%10;
      sec1 = (time/1000)%10;
            
      if(sec0 > 9) {
         sec1++;
      }
      if(sec1 > 5) {
         time = 0;
         min0++;
      }
      if(min0 > 9) {
         time = 0;
         min0 = 0;
         sec1 = 0;
         sec0 = 0;
         min1++;
      }
      if(min1 > 5) {
         min1 = 0;
      }

      PORTC = TEN_DATA[sec0];
      PORTG = 0x01;
      _delay_ms(2);

      PORTC = SIX_DATA[sec1];
      PORTG = 0x02;
      _delay_ms(3);
      
      PORTC = TEN_DATA[min0] | 0x80;
      PORTG = 0x04;
      _delay_ms(2);

      PORTC = SIX_DATA[min1];
      PORTG = 0x08;
      _delay_ms(3);


   }
}