반도체 Study/아두이노

디지털 타이머 - (아두이노, C언어(포인터))

잇(IT) 2024. 5. 10. 13:32
728x90

https://insoobaik.tistory.com/592

 

디지털 논리회로 설계 - 가산기, 인코더, 디코더, 멀티플렉서, 7_Segment

기본 논리게이트에 대한 내용 (NOT, AND, OR, NAND, NOR XOR)https://insoobaik.tistory.com/576 기본 논리 게이트 설계 (아두이노 IC Chip, Code 구현, C언어 Code 구현)보호되어 있는 글입니다. 내용을 보시려면 비밀

insoobaik.tistory.com

7_segment 및 기본 내용들은 위 글을 참고한다.


디지털 타이머를 만들기 위해서는 0~9초 다음 10초가 0~59초 다음 1분이 0~59분 다음 1시간이 되어야 한다.

시,분,초를 위해서는 총 6개의 7_segment가 필요하고, 각 자리에 맞게 이전 시간에서 정보를 받아 해당 자리의 숫자를 증가시켜야 한다.

 

시계를 동작 시키기 위해서는 실제 시간 1초에 맞춰 신호를 전달할 클럭이 필요하며, 그 신호는 정확한 타이밍에 0과 1의 신호를 전달해야 한다.


무안정 멀티바이브레이터

 

무안정 멀티바이브레이터는 불안정한 두가지 상태 HIGH, LOW 상태를 가지고 한쪽 상태에 머무르지 못하고 두 상태를 왔다 갔다하는 것으로 일종의 발진기에 해당한다.

 

NOT게이트(7404), 컨패시터, 저항을 이용하여 완벽한 클럭과 같은 완벽한 구형파를 생성할 수 있다.

7404 chip을 이용하여 위와 같이 회로도를 구성한 뒤 x 부분의 신호를 측정하게 되면 삼각 파형이 나오는 것을 확인할 수 있으며, 출력 단을 찍어보게 되면 구형파가 나오는 것을 확인할 수 있다.

위와 같이 출력단에 나오는 깨끗한 구형파를 이용하여 클럭 신호와 같이 일정한 주기로 신호를 전달할 수 있다.


6진 카운터(7492), 10진 카운터(7490)

 

7490, 7492 chip은 각각 10진 6진 카운터 chip에 해당한다.

각 chip은 이름 그대로 0~9, 0~5까지 숫자를 카운트 하는 칩에 해당한다.

 

7490 datasheet

7492 datasheet

7490과 7492 chip의 datasheet를 보게 되면 구조가 유사한 것을 확인할 수 있다.

 

각 chip은 클럭 신호의 rising, falling 신호에 맞춰 count를 하게 되고, CKA를 통해 클럭 주기를 전달 받아 CKB를 통해 해당 클럭의 신호를 rising, falling 신호에 맞게 주기를 생성하여 전달한다.

7490의 경우 QA~QD를 통해 10진의 숫자를 2진수로 나타내며, 위 사진과 같이 클럭 신호에 맞춰 LED 4개로 0~9까지 숫자가 출력되는 것을 확인할 수 있다.

7492의 경우에도 마찬가지로 QA~QD를 통해 6진의 숫자를 2진수로 나타내며, 위 사진과 같이 클럭 신호에 맞춰 LED 3개로 0~5까지 숫자가 출력되는 것을 확인할 수 있다.


7490, 7492 chip을 이용하여 0~59 생성

 

시계를 구성하기 위해서 기본적으로 분, 초의 경우 0~59를 표현해야 한다. 하지만 7_segment의 경우 0~9까지만 표현이 가능하고, 초의 일의 자리가 10이 되는 순간 십은 1씩 증가해야 한다.

두개의 chip을 보게 되면 CKA를 통해 외부에서 클럭 신호를 받아오고, 해당 클럭의 rising, falling을 이용하여 카운팅을 실행한다.

 

* 클럭 신호도 결국 0과 1의 신호를 주기적으로 전달하는 것이기 때문에 7490의 counter가 10이 되는 순간을 주기로 생성하여 7492에게 신호를 전달하게 되면 시계와 같이 동작하게 되는 것이다.

 

즉, 7492 6진 counter chip의 CKA에 7490 10진 counter chip의 QD(2진수의 2^3 위치에 해당)로부터 신호를 전달 받는다.

위 datasheet를 보게 되면 2진수 4bit를 통해 10의 숫자를 나타내고 있는 것을 확인할 수 있다. QA는 2^0 위치를 QB는 2^1 위치를 QC는 2^2 위치를 QD는 2^3의 위치를 나타내는 것을 확인할 수 있다.

또, counter chip은 클럭의 rising, falling 신호를 통해 counting을 하기 때문에 위 표를 보게 되면 8, 9의 신호는 HIGH 신호를 전달하고, 다시 0이 되는 순간 LOW 신호를 전달하기 때문에 특정 주기를 생성한다고 생각할 수 있다.

즉, 8, 9에서 신호가 HIGH가 되고 다시 0이 되는 순간 falling 신호를 7492 6진 counter에 전달하여 counting 하도록 동작시킬 수 있다.

위 그림과 같이 선을 연결하게 되면 7492 6진 counter chip에서 7490 chip에서 0~10 마다 counting을 1씩 하도록 동작 시킬 수 있다.

 

결과적으로 이전 글에서 동작 시킨 7_segment 7447chip과 7490, 7492 10진, 6진 counter chip을 이용하게 되면, 시계를 생성할 수 있다. 

(클럭 주기 생성의 경우 처음 소개한 NOT 게이트를 이용한 CLK 신호 생성과 함께 4020 분주기 chip을 이용하여 실제 1초애 맞게 주기를 조절할 수 있고, 아두이노와 코드를 통해 실제 1초 클럭과 같이 0과 1의 신호를 pin으로 전달하여 시계처럼 동작 시킬 수 있다.


C언어(포인터)를 이용한 시계 만들기

 

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdbool.h>
#include <windows.h>
#include <conio.h>

void Clk(int speed, bool *clk) {

	Sleep(speed);

	*clk = !*clk;
}

void s_One(int *s_one, int *s_ten) {

	*s_one += 1;

	if (*s_one == 10) {
		*s_ten += 1;
		*s_one = 0;
	}
}

void s_Ten(int *s_ten, int *m_one) {
	
	if (*s_ten == 6) {
		*m_one += 1;
		*s_ten = 0;
	}
}

void m_One(int *m_one, int*m_ten) {
	
	if (*m_one == 10) {
		*m_ten += 1;
		*m_one = 0;
	}
}

void m_Ten(int* m_ten, int* h_one) {
	
	if (*m_ten == 6) {
		*h_one += 1;
		*m_ten = 0;
	}
}

void h_One(int* h_one, int* h_ten) {

	if (*h_one == 10) {
		*h_ten += 1;
		*h_one = 0;
	}
	
}

void h_Ten(int* h_one, int* h_ten) {

	if (*h_ten == 2 && *h_one == 4) {
		*h_one = 0;
		*h_ten = 0;
	}
}

void clock_on() {

	int speed = 100;
	bool clk = 0;
	int s_one = 0, s_ten = 5;
	int m_one = 9, m_ten = 5;
	int h_one = 3, h_ten = 2;

	while (true) {
		if (_kbhit()) {
			char input = _getch();

			if (input == 'q') {
				printf("************************\n");
				printf("입력된 키 : %c\n", input);
				printf("타이머를 종료합니다.\n");
				printf("************************\n");
				printf("\n");
				break;
			}
			else if (input == 'r') {
				printf("************************\n");
				printf("입력된 키 : %c\n", input);
				printf("타이머를 리셋합니다.\n");
				printf("************************\n");
				printf("\n");
				clk = 0, s_one = 0, s_ten = 0, m_one = 0, m_ten = 0, h_one = 0, h_ten = 0;
			}
		}
		Clk(speed, &clk);
		if (clk == 1) {
			printf("%d%d시 %d%d분 %d%d초\n", h_ten, h_one, m_ten, m_one, s_ten, s_one);
			s_One(&s_one, &s_ten);
			s_Ten(&s_ten, &m_one);
			m_One(&m_one, &m_ten);
			m_Ten(&m_ten, &h_one);
			h_One(&h_one, &h_ten);
			h_Ten(&h_one, &h_ten);
			
		}
	}
}

void main() {

	int sel_fun;
	int sel_num;

	while (true) {
		printf("--------------------------\n");
		printf("[1]. 시계\n");
		printf("실행할 기능을 입력하세요 : ");
		scanf("%d", &sel_fun);
		printf("\n");

		while (true) {
			switch (sel_fun) {
			case 1:
				printf("----------------------------------------------------------------------------\n");
				printf("[1]. 타이머 실행(타이머 실행 중 [q] 입력 시 타이머 종료, [r] 입력 시 타이머 리셋)\n");
				printf("or\n");
				printf("[2].메인 화면으로\n");
				printf("입력 : ");
				scanf("%d", &sel_num);
				printf("\n");

				switch (sel_num) {
				case 1:
					clock_on();
					break;
				case 2:
					break;
				}
				if (sel_num == 2) {
					break;
				}
			}
			if (sel_num == 2) {
				break;
			}
		}
	}
}

728x90