전에 한번 8Bit 7-Segment LED를 이용하여 Bread Board에 Full Adder를 만든것을 포스팅 한적이 있다.
이번에 학교에서 이것을 PCB로 떠서 4Bit (보드 크기가 제한되어 8Bit는 불가)로 전가산기를 만드는 프로젝트가 있어서 이 기회에 다시한번 remind 하고자 이 포스트를 작성하였다.
이 회로를 간단히 설명하자면 DIP스위치로 숫자를 입력 받아 7segment LED로 4bit 가감산 결과를 (7483 Full Adder 이용) 출력하는 회로이다.
Toggle Switch를 이용하여 덧셈을 할 것인지 뺄셈을 할 것인지 정하고 숫자의 입력은 DIP Switch로 0~F (Binary : 0000~1111) 까지의 숫자 입력 범위를 가진다.
다만 F+F와 같은 연산은 8bit 연산이므로 Carry를 넘길 수 없는 단점이 존재한다.
제일 먼저 할일은 7-Segment LED의 점등을 위한 진리표를 만들어야 한다.
이를 위해서는 7-Segment LED의 원리를 알 필요가 있는데, 아래의 그림을 참고한다.
Cathode의 경우는 그라운드가 공통이며 Anode의 경우는 Vcc(+5v)가 공통이다.
용도에 따라서 다르게 쓸수 있으나 Active Low가 대세이므로 Anode 타입을 사용하며 다음과 같이
회로가 켜질 수 있도록 설계하는것이 포인트.
이 때 신호는 Active Low가 되야 하므로 0이 될때 Vcc와 Signal 사이의 전압차가 생겨서 전류가 흐르므로 LED가 켜지게 된다.
TTL 7447 (Binary to Decimal Decoder)를 사용해도 좋지만 이것의 경우는 0~9까지만 표시되므로
0~F까지의 범위를 가질 수 있도록 GAL을 이용하여 따로 프로그램을 작성하기로 한다.
위 7-Segment LED에 A,B,C,D 와 같이 알파벳으로 값이 매겨져 있는데 그것은 하나의 LED를 뜻한다.
A자리에 불이 들어오게 하기 위한 진리표는 다음과 같다.
수(Bin)
|
수(Hex)
|
값
|
0000
|
0x00
|
1
|
0001
|
0x01
|
0
|
0010
|
0x02
|
1
|
0011
|
0x03
|
1
|
0100
|
0x04
|
0
|
0101
|
0x05
|
1
|
0110
|
0x06
|
1
|
0111
|
0x07
|
1
|
1000
|
0x08
|
1
|
1001
|
0x09
|
1
|
1010
|
0x0A
|
1
|
1011
|
0x0B
|
0
|
1100
|
0x0C
|
1
|
1101
|
0x0D
|
0
|
1110
|
0x0E
|
1
|
1111
|
0x0F
|
1
|
왜 이런값을 매겼냐하면 다음과 같은 Character Set을 이용하기 위함이다.
숫자 0을 예로 들어보면 현재 켜져 있는 LED는 A, B, C, D, E, F가 켜져있고 G는 꺼져있는 상태이다.
0에서 A가 켜지므로 이것의 값은 1이 나와야 한다.
하나의 예를 더 들어보자면 숫자 1에는 현재 켜져 있는 LED가 B,C가 켜져있고 나머지는 꺼져있으므로
A의 값은 0이 된다.
이러한 진리표를 Boolean Algebra를 만든 후 식을 축약하는데, 여기서는 카노맵을 사용하면 된다.
카노맵과 원래 식이 맞는지 확인하기 위해 다음과 같은 프로그램을 만들었다.
// Equivalent Discriminator for Boolean Function by Xeriars
#include <stdio.h>
#include <stdlib.h>
int main () {
int a_,b_,i,fcount=0;
system(“cls”);
printf(” Truth Tablenn”);
for(i=0;i<16;i++) {
int A=!!(i&8), B=!!(i&4), C=!!(i&2), D=!!(i&1);
a_ = (!A & !B & !C & !D) + (!A & !B & !C & D) + (!A & B & C & D) + (A & B & !C & !D);
b_ = (!A & !B & !C) + (B & (!A & C & D) + (A & !C & !D));
if (a_ != b_) { printf(“%X : t1 = %d, t2 = %d ——– Xn”, i,a_,b_); ++fcount; }
else { printf(“%X : t1 = %d, t2 = %dn”, i,a_,b_); }
}
if (fcount > 0) { printf(“nFalse Count : %d”, fcount); }
getch();
return 0;
}
a_랑 b_ 부분을 수정해서 컴파일해보면 알 수 있다.
원래 식과 축약된 식이 일치하면 위와 같은 화면을 볼 수 있지만 틀리다면 다음과 같이 프로그램의 출력이 변한다.
2개가 틀렸다는것을 알 수 있다. 이 식은 잘못된 경우이다. 축약을 다시 하여야 한다.
아무튼 이 짓이 싫으면 Karnaugh Minimizer란 프로그램을 구해서 사용하면 된다.
아래 표는 0~F까지의 진리표를 종합한 것이다.
Input
|
Output
|
HEX.
|
|||||||||
A
|
B
|
C
|
D
|
OUTA
|
OUTB
|
OUTC
|
OUTD
|
OUTE
|
OUTF
|
OUTG
|
|
0
|
0
|
0
|
0
|
1
|
1
|
1
|
1
|
1
|
1
|
0
|
0
|
0
|
0
|
0
|
1
|
0
|
1
|
1
|
0
|
0
|
0
|
0
|
1
|
0
|
0
|
1
|
0
|
1
|
1
|
0
|
1
|
1
|
0
|
1
|
2
|
0
|
0
|
1
|
1
|
1
|
1
|
1
|
1
|
0
|
0
|
1
|
3
|
0
|
1
|
0
|
0
|
0
|
1
|
1
|
0
|
0
|
1
|
1
|
4
|
0
|
1
|
0
|
1
|
1
|
0
|
1
|
1
|
0
|
1
|
1
|
5
|
0
|
1
|
1
|
0
|
1
|
0
|
1
|
1
|
1
|
1
|
1
|
6
|
0
|
1
|
1
|
1
|
1
|
1
|
1
|
0
|
0
|
0
|
0
|
7
|
1
|
0
|
0
|
0
|
1
|
1
|
1
|
1
|
1
|
1
|
1
|
8
|
1
|
0
|
0
|
1
|
1
|
1
|
1
|
0
|
0
|
1
|
1
|
9
|
1
|
0
|
1
|
0
|
1
|
1
|
1
|
0
|
1
|
1
|
1
|
A
|
1
|
0
|
1
|
1
|
0
|
0
|
1
|
1
|
1
|
1
|
1
|
B
|
1
|
1
|
0
|
0
|
1
|
0
|
0
|
1
|
1
|
1
|
0
|
C
|
1
|
1
|
0
|
1
|
0
|
1
|
1
|
1
|
1
|
0
|
1
|
D
|
1
|
1
|
1
|
0
|
1
|
0
|
0
|
1
|
1
|
1
|
1
|
E
|
1
|
1
|
1
|
1
|
1
|
0
|
0
|
0
|
1
|
1
|
1
|
F
|
여기서 사용할 GAL은 G22V10이며 핀배치는 아래처럼 생겼다.
이것을 wincupl의 형식에 맞게 적용한 파일은 다음과 같다.
———————————————————————————–
Name 7segment;
PartNo g22v10;
Date 2007-05-18 ;
Revision 01;
Designer Xeriars;
Company The X.D.C.;
Assembly 000;
Location In_the_Hell;
Device g22v10;
/* *************** INPUT PINS *********************/
PIN 02 = A;
PIN 03 = B;
PIN 04 = C;
PIN 05 = D;
/* *************** OUTPUT PINS *********************/
PIN 17 = OUTA;
PIN 18 = OUTB;
PIN 19 = OUTC;
PIN 20 = OUTD;
PIN 21 = OUTE;
PIN 22 = OUTF;
PIN 23 = OUTG;
/* *************** EQUATIONS *********************/
!OUTA = (B & C) # (!A & C) # (A & !D) # (!B & !D) # (!A & B & D) # (A & !B & !C);
!OUTB = (!B & !D) # (!B & !C) # (!A & C & D) # (A & !C & D) # (!A & !C & !D);
!OUTC = (!C & D) # (!A & D) # (A & !B) # (!A & B) # (!B & !C);
!OUTD = (!A & C & !D) # (!B & C & D) # (B & !C & D) # (A & B & !D) # (!B & !C & !D);
!OUTE = (C & !D) # (A & C) # (A & B) # (!B & !D);
!OUTF = (A & C) # (A & !B) # (B & !D) # (!C & !D) # (!A & B & !C);
!OUTG = (A & C) # (!B & C) # (A & !B) # (B & !C & D) # (!A & B & !D);
———————————————————————————–
위 내용을 복사해서 붙인후 *.pld 파일로 저장한다음 Rom Wrinter로 GAL을 구워주면 된다.
이렇게 만들어진 GAL의 핀 관련정보는 위에서 보면 잘 나와있으므로 자세한 설명은 생략한다.
덧셈과 뺄셈을 하기 위해서는 TTL 7483(Full Adder)과 7486(XOR Gate)을 사용하게 되는데 IC 부품 가게에 가면 두가지 타입이 있다.
74LS83과 74HC83 두가지가 있는데 이 두가지는 사용법이 엄연히 다르므로 주의해서 사용하여야 하지만
이 포스트에서는 모든 핀을 사용하므로 이것에 대한 자세한 설명은 생략하지만 HC Type을 쓰는경우
안쓰는 핀은 반드시 High로 신호를 걸어주는 편이 신상에 이롭다.
(이것을 모르면 개피보는 수가 생기므로 반드시 주의한다.)
모든 회로에는 타임차트를 작성하여 동작 원리를 알수 있도록 한다.
이렇게 해주면 실수할 확률이 상당히 줄어든다.
1단계적인 완성을 위해 위에서 설명한 내용을 종합하여 아래와 같은 회로 설계를 할 수 있다.
스위치 부위에 Array 저항(10k)를 달아서 스위치가 닫혔을때도 신호가 제대로 들어갈 수 있도록 하여야 한다.
위 도면은 전원부 관련 회로이다. 7805(5Volt Regulator)를 사용하였고 전해 커페시터를 사용하여 전압이 항상 일정하게 공급될 수 있도록 해준다. (커페시터를 달아주는것은 7805 Data Sheet에서 권장하고 있는 형태이다.)
그리고 각 IC에는 반드시 커페시터를 달아서(이것을 Bypass Capacitor라고 표현) 노이즈를 막고 또한 전압이 일정하게 공급될수 있도록 한다.
※ 7805를 사용하려면 입력전압이 2~5V정도 높은 것을 사용하여야 한다.
필자는 9V/500mA의 어뎁터를 사용하였다.
이렇게 회로를 구성했으면 PCB를 뜨기위한 Footprint 작업으로 넘어간다.
다음 표를 참고하여 PCB Footprint의 정보를 입력한다.
No.
|
Part Name
|
PCB Footprint
|
1
|
7SEG-ANODE
|
r_FND_507 (직접 제작)
|
2
|
Capacitor 10u
|
CYL/D.250/LS.125/.031
|
3
|
Capacitor 104
|
RAD/.150X.100/LS.100/.031
|
4
|
Resistor 330
10k |
AX/.400X.100/.031,BLKCON.100/VH/TM1SQ/W.100/6
|
5
|
TTL 74LS83
|
DIP.100/16/W.300/L.800
|
6
|
TTL 74HC86
|
DIP.100/14/W.300/L.700
|
7
|
GAL22V10
|
DIP.100/24/W.300/L1.175
|
8
|
HEADER2
|
BLKCON.100/VH/TM1SQ/W.100/2
|
9
|
LM7805
|
TO220AA/RF2
|
10
|
SW DIP-4/SM
|
DIP.100/8/W.300/L.400
|
11
|
SW KEY-SPDT
|
BLKCON.100/VH.TM1SQ/W.100/3
|
OrCAD Lay-out을 사용하여(사용법은 알아서 숙지) 수작업으로 Routing을 하던지 아니면
OrCAD Layout Plus SmartRoute Calibrate를 사용하여 자동으로 뜨는 방법을 고려한다.
필자는 Routing이 귀찮아서 후자의 방법을 채택하였으나 몇가지 기준은 필요하다.
1. PCB는 양면기판 이상을 사용하자. (단면기판은 라우팅 하기가 까다롭다, 그리고 4층 이상의 다층 기판을 사용하게 되면 한면은 VCC, 다른 한면은 GND로 사용할수 있는 장점이 있으므로 노이즈에 대해서도 매우 유리하다. 다만 돈이 많이 들게 되므로 대량생산하는 경우는 심각히 고려해야 할 사항이다.)
2. 앞면을 세로 기준으로 라우팅을 한다면 뒷면은 가로 기준으로 라우팅을 하자. (이렇게 기준을 정하면 회로가 미관상으로 이뻐 보인다.)
3. 가급적 뺑뺑 돌아가는 라우팅은 피한다. (공간 전도 노이즈에 감염될 확률이 높아지며, 배선 자체가 코일, 저항 역할을 하게 되므로 전류흐름의 방해요소로 작용된다.)
필자는 시간이 없어서 자동 라우팅을 하고 급하게 PCB를 뜨고 나서 생각해보니 3번항목을 지키지 못하였다.
아무튼 결과는 다음과 같이 나왔다.
양면 기판을 사용하여 작성하였고 PCB 기판의 크기 제한은 11cm x 7cm이다.
신호선폭은 12mil(1/1000인치), 전원 선폭은 25mil로 작성되었다.
PCB 기판의 앞면만 나타낸 모습이다. 자동 뜨기를 했더니만 2번항목이 전혀 지켜지지 않았다. -_-;;
PCB 기판의 뒷면만 나타낸 모습이다. 앞면에 비해서 2번항목이 비교적 잘 지켜졌다.
이렇게 라우팅이 100%가 된다고 끝나는 것은 아니다. Copper pour 라는 작업을 해주어 동판이 기판에 전반적으로 덮을 수 있도록 해준다. 이것은 양면기판으로 다층기판의 효과를 낼 수 있다.
필자의 경우는 앞면을 VCC, 뒷면을 GND로 Copper pour 작업을 해주었다.
녹색부분이 Copper pour 작업이 된 부분인데 라우팅의 문제로 Copper가 기판 곳곳으로 끝까지 들어가지 않았다. (빨강,검정부분이 들어가지 않은 부분)
마찬가지로 뒷면도 Copper pour 작업을 해준다. 역시 앞면처럼 라우팅의 문제로 Copper가 제대로 들어가지 않았다. (녹색, 검정부분이 들어가지 않은 부분임)
이렇게 해서 라우팅이 되면 Gerber File을 생성하여 PCB 생산 업체에 보내주면 PCB기판을 제작해준다.
완성된 PCB에 각종 부품을 조립한 모습이다.
(뒷면은 납땜질이 서툰관계로 차마 공개할수가 없었다.. -_-;;;)
누군가에 의해 검색된 이 자료가 많은 도움이 되길 바라며 이 포스팅으로 2008년의 모든 포스팅을 마친다.