거북이처럼 천천히

FND (Flexible Numeric Display) - 기초 (2) 본문

Embedded Programming/Atmega 128A (실습)

FND (Flexible Numeric Display) - 기초 (2)

유로 청년 2024. 5. 31. 19:32

서론

 

 4-FND (Flexible numeric display)는 4개의 FND를 모아 하나의 단일 소자로서 각각의 FND는 LED의 출력을 위해 동일한 8개의 핀을 공유하여 사용하지만, 아래와 같이 4개의 핀 ( 12핀, 9핀, 8핀, 6핀 )을 이용하여 각 자리의 FND의 출력을 제어하게 된다.

 

4-FND , 3461AS-1
각각의 FND는 LED의 출력을 위해 동일한 8개의 핀을 공유하여 사용하지만, cathode 쪽 핀들을 통해 해당 FND을 제어하게 된다.

 


 

본론

 

 이번에는 아래와 같은 회로 및 환경을 구현하여 4-FND에 대해서 알아보겠으며, 특히 4-FND을 이용하여 서로 다른 자리에 서로 다른 숫자들을 동시에 출력함으로서 C언어에 대한 이해 및 FND에 대한 지식 및 활용 능력을 쌓도록 하겠다.

 

  • 4-FND을 연결한 뒤, for문을 이용하여 0 ~ 9까지 순차적으로 단순히 출력하도록 하겠다.
  • 0 ~ 9999 까지 동시 출력하도록 설계하도록 하겠다.

 

 

구현 1) for문을 이용하여 0 ~ 9까지 순차적으로 단순히 출력

 

구현 내용) PORT C에 4-FND을 연결하고,  4-FND의 각 자리 출력 제어를 담당하는 핀 ( 12, 9, 8, 6 )을

                  PORT G에 연결한다. 그리고 모든 FND를 이용하여 0 ~ 9 를 순차적으로 출력하도록 설계한다.

 

 

Source code)

#define F_CPU 16000000UL
#include <avr/io.h>
#include <util/delay.h>

#define FND_CONTROL_DDR			DDRG
#define FND_CONTROL_PORT		PORTG
#define FND_PRINT_DDR			DDRC
#define FND_PRINT_PORT			PORTC
#define TIME					600

// Function prototype.
void init_Control();
void init_FND();

// Main method
int main(void) {
	init_Control();
	init_FND();
	
	uint8_t fnd_digits[] = {0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x27, 0x7F, 0x67};
	
	while(1) {
		for(uint8_t i = 0; i<10; i++) {
			FND_PRINT_PORT = fnd_digits[i];
			_delay_ms(TIME);
		}
	}
}

// Initialization of Control 
void init_Control() {
	// cathode 쪽에 0V 전압을 인가해야 전위차에 의해 anode에서 cathode 쪽으로 전류가 흐르게 된다.
	FND_CONTROL_DDR = (1<<DDRG0 | 1<<DDRG1 | 1<<DDRG2 | 1<<DDG3);
	FND_CONTROL_PORT = 0x00;
}

// Initialization of FND
void init_FND() {
	FND_PRINT_DDR = 0xff;
}

 

  • Diode의 cathode 쪽에 0V 전압을 인가해야 PORT C를 통해 5V 전압을 인가해줌으로서 전위차에 의해 diode에서 anode에서 cathode 쪽으로 전류가 흐르게 되어 FND에 불이 들어오게 된다.

 

구현 영상)

 

 

 


구현 2) 0 ~ 9999 까지 숫자들을 동시 출력

 

Source code)

#define F_CPU 16000000UL
#include <avr/io.h>
#include <util/delay.h>

// Substitute Constant.
#define FND_CONTROL_DDR			DDRG
#define FND_CONTROL_PORT		PORTG
#define FND_LED_DDR				DDRC
#define FND_LED_PORT			PORTC
#define TIME					100

// Function prototype
void init_FND_LED();
void init_FND_CONTROL();
void print_FND(uint16_t digit, uint8_t pos);

// Main method
int main(void) {
	init_FND_CONTROL();
	init_FND_LED();
	
	uint16_t digit = 0;
	
	while(1) {
		int time = 0;
		
		while(time<TIME) {		
			for(uint8_t pos = 0; pos<4; pos++) {
				FND_CONTROL_PORT &= ~(1<<pos);
				print_FND(digit, pos);
				_delay_ms(1);
				FND_CONTROL_PORT |= (1<<pos);
			}
			
			time++;
		}
		
		digit++;
	}
}

// Initialization for FND_CONTROL
void init_FND_CONTROL() {
	// PORT G 에 FND의 각 자리 출력을 컨트롤 하는 핀( 12핀, 9핀, 8핀, 6핀 ) 연결
	// PG0 : 12핀, PG1 : 9핀, PG2 : 8핀, PG3 : 6핀
	FND_CONTROL_DDR = (1<<DDRG0 | 1<<DDRG1 | 1<<DDRG2 | 1<<DDRG3);
	FND_CONTROL_PORT = (1<<PORTG0 | 1<<PORTG1 | 1<<PORTG2 | 1<<PORTG3);
}

// Initialization for FND_LED
void init_FND_LED() {
	// PORT C 에 FND 출력을 위한 핀 연결
	FND_LED_DDR = 0xff;
}

// Print digit
void print_FND(uint16_t digit, uint8_t pos) {
	static uint8_t FND_Number[] = {0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f};
	
	switch(pos) {
		case 0:
			FND_LED_PORT = FND_Number[digit/1000];
			break;
		case 1:
			FND_LED_PORT = FND_Number[(digit/100)%10];
			break;
		case 2:
			FND_LED_PORT = FND_Number[(digit/10)%10];
			break;
		case 3:
			FND_LED_PORT = FND_Number[digit%10];
			break;
	}
}

 

  • 각각의 FND는 FND의 막대의 출력을 컨트롤하는 8개핀 (11, 7, 4, 2, 1, 10, 5, 3) 을 공유하고 있는 상태이며,
    4개 핀( 12, 9, 8, 6 )을 통해 각 자리의 FND을 출력할지 여부를 결정한다.
  • Q) 그럼 어떻게 서로 다른 숫자들을 서로 다른 자리에서 동시에 출력시킬 것인가?
    A) 사람의 눈은 30Hz 이상을 넘어가게 되면 불연속적인 화면에 대해서 착각하여 연속적인 변화라고 인식하기 때문에 이보다 빠르게 0번째 FND부터 3번째 FND 까지 빠르게 출력하고, 이러한 과정을 여러 번 반복하면 연속적인 출력 형태로 착각하게 된다.
  • 해당 코드에서는 각각의 FND에 대해서 1ms 씩 출력하며, 0번째 FND부터 3번째 FND 까지 총 4ms 씩 출력한다.
    그리고, 위 과정을 100번 반복함으로서 한 숫자를 표현하기 위해 400ms = 0.4초 을 간격 두고 출력한다.
  • 주의)  원하는 FND를 출력하기 위해서는 해당 컨트롤 핀에 출력 값을 5V → 0V로 변화해줘야 하며, 
              출력을 마친 뒤에는 해당 FND의 출력을 막기 위해 해당 컨트롤 핀에 다시 출력 값을 0V 5V로
              전환함으로서 전위차 의해 출력을 막아야한다.

 

구현 영상)

 

 

 


 

추가적으로 수정된 코드)

#define F_CPU 16000000UL
#include <avr/io.h>
#include <util/delay.h>

// Substitute Constant.
#define FND_CONTROL_DDR			DDRG
#define FND_CONTROL_PORT		PORTG
#define FND_LED_DDR				DDRC
#define FND_LED_PORT			PORTC
#define TIME					100

// Function prototype
void init_FND_LED();
void init_FND_CONTROL();
void print_FND(uint16_t digit);

// Main method
int main(void) {
	init_FND_CONTROL();
	init_FND_LED();
	
	uint16_t digit = 0;
	
	while(1) {
		int time = 0;
		
		while(time<TIME) {		
			print_FND(digit);
			time++;
		}
			
		digit++;
		digit%=10000;
	}
}

// Initialization for FND_CONTROL
void init_FND_CONTROL() {
	// PORT G 에 FND의 각 자리 출력을 컨트롤 하는 핀( 12핀, 9핀, 8핀, 6핀 ) 연결
	// PG0 : 12핀, PG1 : 9핀, PG2 : 8핀, PG3 : 6핀
	FND_CONTROL_DDR = (1<<DDRG0 | 1<<DDRG1 | 1<<DDRG2 | 1<<DDRG3);
	FND_CONTROL_PORT = (1<<PORTG0 | 1<<PORTG1 | 1<<PORTG2 | 1<<PORTG3);
}

// Initialization for FND_LED
void init_FND_LED() {
	// PORT C 에 FND 출력을 위한 핀 연결
	FND_LED_DDR = 0xff;
}

// Print digit
void print_FND(uint16_t digit) {
	static uint8_t pos = 0;
	static uint8_t FND_Number[] = {0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f};
	
	FND_CONTROL_PORT &= ~(1<<pos);
	
	switch(pos) {
		case 0:
			FND_LED_PORT = FND_Number[digit/1000];
			break;
		case 1:
			FND_LED_PORT = FND_Number[(digit/100)%10];
			break;
		case 2:
			FND_LED_PORT = FND_Number[(digit/10)%10];
			break;
		case 3:
			FND_LED_PORT = FND_Number[digit%10];
			break;
	}
	
	_delay_ms(1);
	FND_CONTROL_PORT |= (1<<pos);
	
	pos++;
	pos %= 4;
}


          

'Embedded Programming > Atmega 128A (실습)' 카테고리의 다른 글

Timer / Counter - 기초 (2)  (0) 2024.06.01
Timer / Counter - 기초 (1)  (0) 2024.06.01
FND (Flexible Numeric Display) - 기초 (1)  (0) 2024.05.30
Interrupt - 기초 (1)  (0) 2024.05.29
GPIO - LED control (3)  (0) 2024.05.29