AVR 을이용한 DotMatrix 지은이 : 도시락 ( 당근이의 AVR 갖구놀기 ) 날짜 : 2009/1/23
목차 서론 1. 사용한부품목록 2. 회로도 3. DotMatrix의원리 4. 소스코드 5. 구동이미지 부록 데이터시트
서론 안녕하세요. 이글에서는 AVR을이용한 DotMatrix 구동에대해서다뤄보도록하겠습니다. 이글에서는기본적으로 MCU로 AVR을이용하지만여타다른 8-bit 혹은그이상의 bit로구동되는어떤 MCU를사용해도상관없다는것을알게될것입니다. 저또한아직걸음마단계이지만, 마이크로컨트롤러세계에입문하신분들에게가장흥미있는분야가이 DotMatrix가아닐까싶어서최대한쉽게쓰겠습니다.( 중급이상이신분들은스스로만들수있겠죠?) 이글을읽기전에이미기본적인회로이론과 C언어와기본적인디지털논리회로설계 (DLD), AVR의컴파일등은알고있어야합니다. 모르시면우선숙지하신후에읽어주세요. AVR의컴파일러는코드비전을사용했습니다.
1. 사용한부품목록 부품 수량 8X8 도트매트릭스 ( 디x이스마트 ) 1 AVR보드 1 8핀 +4핀커넥터 1 100옴 2012칩저항 ( 일반저항사용해도됩니다 ) 16 2sa1015(PNP Tr) 8 12핀커넥터 2 74HC138, 74HC595 1
2. 회로도 Fig.1 전체회로도
3. DotMatrix 의원리 a. 도트매트릭스 Fig.2 도트매트릭스핀배열 이회로도는디X이스마트에서 3천원에판매중인 8X8 투컬러도트매트릭스의회로도입니다. 직접 LED로납땜하셔서만들어도되지만, 노가다비용따지면구동회로없는매트릭스사는게훨씬이익입니다. 원래사이트에개제된핀배열은글씨가알아보라고쓴건지말라고쓴건지모르겠지만 ( 확인해보세요.. ㅠ ) 제가대충보이는건그대로활용하고안보이는건직접찍어보면서찾은것입니다. 보시는것처럼 Common Cathode Type입니다. 즉, Col에서 Vcc를걸어주고 Row에서 GND로빠
져나가는방식입니다. 예를들면, Col 3, Row 3에있는적색 LED를키기위해서는, 17번핀에 Vcc를, 16번핀에 GND를물려주시면됩니다. 이때, 14번핀에 Vcc를물리면, Col 4, Row 3의적색 LED 도켜지겠죠. 거기에 18번핀에도 Vcc를물려주면 Col3, Row3의불이주황색으로바뀝니다. 적색 + 녹색이켜지기때문이죠. 방금설명한것을 MCU로구현하려면, Row에해당하는핀을각각 MCU의포트에물려주시고, Col에해당하는핀들도각각물려주시면간단하게구동시킬수있습니다만, 8x8 도트매트릭스 ( 단컬러일경우만고려해도 ) 16개의핀을허비해야합니다 ATMega8535나 8051등등저가 8-bit MCU의포트가 8-bit씩 4개가있으니.. 총 2개가사용되니, 남는포트는 2개 (2*8=16개) 밖에남지않네요. MCU한개의반을도트매트릭스켜는데사용하면상당히바보같은짓이죠.. 그렇다고핀많은 MCU를쓰자니그것도바보같은짓이죠. 또한 MCU의포트를 COL에바로물려포트에 1 을넣어 5V를만들어줘도 MCU에서뽑아낼수있는전류가한계가있기때문에불이밝지도않습니다.. 그것에대한해결책은잠시뒤로 ~ 여튼그러한이유때문에 MCU만으로도트매트릭스를구동시키지않을것입니다! 물론 8255를사용하셔도됩니다만, 걍저는로직IC로구현하겠습니다.( 많은분들이이미저와같은방식으로사용하고있구요..) b. 로직 IC 어떤로직 IC를사용해야할까 저혼자괜히많이고민했습니다.. 근데당근님의카페에서당근님이이미고민하시고답을제시해주셨더라구요ㅋ ( 주워먹긴나쁜것이지만..;) 제가지금부터설명하는내용은로직IC에대해서잘아시는분은건너뛰셔도되구요, 전공이이쪽분야가아니시던가, 아직학부 1학년과정이라디지털논리회로에대해배우지않으신분은꼼꼼히읽어주세요. 방금위에서제가포트가너무많이사용되는문제에대해언급을했습니다. 그렇다면, 어떻게하면포트를줄일수있을까요? 저는여기서로직IC를이용하는해결책을언급하겠습니다. 저는 2학년때논리회로설계를배우면서, 마이크로컨트롤러한개면모두해결할수있는데도대체왜이런구시대의유물을배워야하는지의아했습니다.( 그땐마이크로컨트롤러를쓸줄몰랐거든요.. 하나면되는줄안..;) 근데그게아니더라구요.. 어리석죠. 각설하고, 사용할로직IC는 3-to-8 Line Decoder와 8-bit Serial Shift Register입니다.
Column 3-to-8 Line Decoder 로우리는 74HC138 을사용하겠습니다. Fig.3 74HC138 A0, A1, A2는 Input이구요, /Y0, /Y1, /Y2,,/Y7는 Output, /E1, /E2, E3는 Control입니다. 제짧은식견으로는, 마이크로컨트롤러를완벽정복하기위해서는데이터시트를얼마나잘이해 하느냐에달려있는것같더라구요.. 여튼, 3-to-8 디코더이기때문에입력이 3개출력이 8개입니다.( 당연히도!) 출력에바가붙어있는이유는 Active일때 LOW이기때문입니다. A0 A1 A2 /Y0 /Y1 /Y2 /Y3 /Y4 /Y5 /Y6 /Y7 0 0 0 0 1 1 1 1 1 1 1 0 0 1 1 0 1 1 1 1 1 1 0 1 0 1 1 0 1 1 1 1 1 0 1 1 1 1 1 0 1 1 1 1 1 0 0 1 1 1 1 0 1 1 1 1 0 1 1 1 1 1 1 0 1 1 1 1 0 1 1 1 1 1 1 0 1 1 1 1 1 1 1 1 1 1 1 0 Table1. 74HC138의 Truth Table 위의 Truth Table 을보면, Active일때 0이나오는걸알수있죠? Line Decoder는 Active일때 1이 나오는것도있습니다. 근데왜우린요놈을썼을까요?? 바로 ~ 회로도를보셨다면아시겠지만, 요놈이 GND역할을하게됩니다 ~( 즉 Row에붙인다는얘기죠 ) 예를들어 ~ 3번 Row에있는 LED만켜고싶다 (Column은몇번 Column의 LED가켜질지는요놈
을알방법도없고알필요도없습니다여튼어떤 Column에해당하는 LED던 Row가 3번에있으면켜진다는것이죠일단은.. 아직 Column은안배웠으니까 ~) 면 ~ /Y2가 Low(0) 이고나머진 High(1) 이되어야하니까 ~ A0, A1, A2에 010을입력해주시면됩니다! 예리하신분들은벌써고민하고계실지모르겠지만, 그렇다면동시에두개이상의 Row의 LED 를출력하려면어떻게할까요? 그건잠시후에 ~ Row 이번엔 8-bit Serial Shift Register에대해서고민해보도록하겠습니다. 디지털논리회로설계시간에기말고사때 Register를배워서..( 영어강의라진도가느리더라구요ㅠ ) 진도막빼느라교수님말씀은하나도기억이안나네요ㅠ시험기간에책보고공부한내용을바탕으로데이터시트를보면서설명하겠습니다. 8-bit이므로출력이 8개이구요, Serial 이니까직렬로데이터를넣습니다. Shift Register는말그대로데이터 (bit) 를이동시키는 Register이구요.. 우리는이기능을하는놈으로 74HC595를사용합니다. 수업시간엔기본적인 Register와 Latch만배워서몰랐는데요놈은 Shift Register기능과함께 Latch기능도갖고있습니다. 뭔말인지는잠시후에 ~ Fig.4 74HC595 핀배치와이데이터시트는감사하게도진리표도있네염ㅋ QA, QB,, QH는 Output이구요 Q H는 QH의반전출력같은데우린여기서사용하지않구사용할필요도없습니다. SER는유일한 Input입니다 (Serial로입력하니까당연한개겠죠?) /G는 three state 버퍼기능입니다. Truth Table보시면요, /G 가 H(1) 일경우출력단이 High Impedance(3- STATE) 가되어출력쪽으로전류가들어올수도없고, 밖으로전압, 전류를보낼수도없습니다. 간단히생각하면출력단이 Open( 한국어로뭐더라.. 그니까스위치가끊긴것 ) 된상태라고봐도무관하긴한데엄연히다른데.. 교수님이하신말씀이잘기억안나네요ㅠ지성.. 여튼우리는요기능을사용안할거니까 13번핀을 GND에물려놓습니다. 그럼언제나 L(0) 인상태를유지하겠죠. 요놈의동작방법은다음과같습니다.
계략적으로 Truth table 에서볼수있듯이, SER 에 1 이나 0 을넣고, SCK 에 Clock 을줍니다. 그럼한 번줄때마다줄줄이데이터가들어가구요, 마지막에 RCK 에클락을줘서저장된데이터를출력 으로쏴줍니다. 학부 3 학년이상이신분들은알고넘어가시겠지만, 아니신분들을위해쉽게설명하겠습니다. 우선 SER 에입력시킬데이터를 QA~QH 까지어떻게넣는지알아봅시다 ~ 일단방식은 SER 에 bit 한개를입력시키고 SCK 에클락을주면 QA 로 SER 의 bit 가들어가고 QA 의 bit 는 QB 로, QB 는 QC 로죽죽밀려나가면서저장하는겁니다. 즉 ~ 굴로온돌이박히돌빼는 Truth table 에서 SCK 에 H 도 L 도아닌 가있죠? 이건 Rising Edge 에서데이터가저장된단겁니 다. Fig.5 타이밍다이어그램 위의그림을타이밍다이어그램이라고합니다. 데이터가저장되는과정을보여드리겠습니다. 0~a SER에 1을넣은상태에서시작합니다. 근데 SCK가아직 0에서변하지않았기때문에데이터는아직 0입니다. a~b 그런데 a에서 SCK가 1로 Rising했습니다. 이 SCK가 Rising하는순간을 Rising Edge라고합니다. Truth table을보면이때 Shift Register가기능을해서 Qn = Qn-1, QA = SER라고써있습니다. 그니까데이터가한칸씩다음칸으로이동하고첫번째칸은비어있을테니 SER에서가져온다는것이죠. 즉 ~ QA~QH : 00110011 이고 SER에 1을주고 SCK가 Rising Edge일때, QA~QH : 10011001 로변한다는것이죠 ~ 또한이구간에서중간에 SER가 0으로떨어졌지만데이터는여전히 1이죠! SCK가 1인데도왜안변해? 가아니라 SCK가 0에서 1로변하는타이밍에만데이터로 SER가올라가므로당연히안변하죠! b~c 이구간에서 SCK 가다시 0으로떨어졌지만여전히데이터는변함없죠? 왜냐! 데이터는 SCK가
0 에서 1 로오를때만변합니다! 그외에이제왜타이밍다이어그램이저런가잘보시면이해될거에요 ~ 우선예를들겠습니다. QA부터QH까지차례대로 11011010 을넣고싶다고가정하겠습니다. SER = 1; SCK = 1; Delay(); SCK = 0; SER = 1; SCK = 1; Delay(); SCK = 0; SER = 0; SCK = 1; Delay(); SCK = 0; 이런식으로.. 걍쉽게설명하기위해아무런기교도없이무식한코드로작성했습니다. 이런식으로 8개를다넣으면됩니다. 그럼스코프로 QA에서 QH까지찍어보면정말 11011010이뜰까요?? 답은노노입니다. 그럼왜? 595는 Latch기능이있습니다. 즉데이터를저장하는능력이있다는거죠 ~ 8bit 그니까 1byte저장할수있네염. 해서저장을시켜놓은데이터를바꿔줘야합니다. Latch에서꺼내서출력단에물려주기위해서는 RCK에클락을줘야합니다. 클락을주기전에는그전에올려놓은데이터가그대로출력되고있습니다. 클락주는방법은위에서 SCK와같은방법이구요 그럼위에소스에서마지막에 RCK = 1; Delay(); RCK = 0; 해주심됩니다. 그렇다면위에서처럼 11011010을넣어주면! Column에서 1,2,3,4,7번 Col에해당하는 LED가켜지게됩니다. 그런데막바로도트매트릭스에 595를연결시켜줘봤자, 595가출력할수있는전류는 LED 한개켜기도버겁습니다 산넘어산이네요.. 그럼또어떻게한다..
c. 트랜지스터트랜지스터는뭘까요.. 학교에따라다르겠지만저희학교 (HY대학) 에선 3학년때배웁니다.. 자세한내용은전자회로책을보심되구요간단한이론만찝고넘어가겠습니다. 트랜지스터는걍간단히전류증폭기능을한다고생각하면맞습니다. NPN과 PNP타입이있구요, N과 P는반도체의종류입니다 ( 아시죠? 몰라도뭐상관없습니다계속가죠 ) 둘이문자가반대이니까사용법도반대입니다. 우린 PNP타입을썼어요. 뭐 NPN밖에없으시면회로좀수정하셔서사용해도됩니다. 뭐여담이지만 MOSFET써도됩니다 당연히.. PNP타입 2sa1015를사용했구요, 트랜지스터 8개꼽아넣으려면 PCB많이차지하니까 TR Array사용하셔도되지만, 기본적인기능을익히기위해걍 TR로썼습니다.( 사실저도아직 TR Array는써본적이 ) Fig.6 트랜지스터 E는 Emitter, B는 Base, C는 Collector입니다. Emitter에다가 V(+) 를걸어주구요, C에다가부하를, B에컨트롤을물려주심됩니다. 간단하죠. V는뭐모터같은거돌릴때는좀더큰전압달아도상관없지만우린 LED킬거니까 (2.4V정도) 걍 Vcc를걸어줍니다. NPN 트랜지스터구동방식은요 ~ E로들어오는전압이 C로나가는겁니다. 그런데 B가컨트롤을합니다. 일반물리실험같은거할때실험해보셔서알겠지만 NPN타입이므로 B에 L를넣어주면 E->C가 Short된것같은것이구, B에 H를넣어주면 E->C가 Open된것같은것입니다. 센스있으신분들은우리가왜 74HC138을썼는지이제야아시겠죠! 바로 B에 0이들어가야 C에전압이뜨기때문입니다! 74HC138은우리가원하는한놈만 Low를출력하잖아요그쵸! 또한우리는하나의궁금증을하나더풀었습니다. 로직IC와 MCU에서충분한전류를공급해줄수없었지만, 트랜지스터를이용함으로써우리는로직IC나 MCU로 Base만조종하면전류는 E에서
받아서 C로줍니다. 그래서우리는전류문제도해결했습니다. ㅋ이제 3페이지로가서회로도를다시한번봅니다. 이해되셨나요?? Two Color Dot Matrix사용시 RED와 GREEN을쓰고싶으시면 138하나추가하고트랜지스터 8개더넣으셔서똑같이만들어서한세트더붙이시면됩니다 ~ 또한, 저항 100옴넣었는데요밝기라던가뭐고려해서가감하셔도되는데 100옴이면충분하네요 (5V기준) d. 정리 74HC138 이 Column 를, 74HC595 가 Row 를 Control 합니다. 또한 595 가뽑아낼수있는전류는 미약하므로 Transistor 를이용해서전류를증폭시켜주고 74HC595 는 Transistor 를컨트롤합니다. 아직해결되지않은궁금증 Row는동시에여러개의 Row줄을켤수있는데, Column은한번에한줄밖에켜지못합니다. 그쵸? 그럼동시에여러 Column의 LED를켜고싶다면?? 그래서도트매트릭스를로직IC를이용해서구동시한번에모두켜지못합니다. 한줄씩처리를합니다. 즉 For문을이용해서, 138의 A0,A1,A2에차례로 000, 001, 010, 011, 100, 101, 110, 111을넣어줍니다. 요러면 1행, 2행, 3행,, 8행이순서대로켜지겠죠? 바꿔말하면한행씩전압을넣어주는것이죠. 그러나한행에전압을넣어줬지만, 어느열에접지를시켜줄지아직정해주지않았으므로 LED 는켜지지않습니다. 이때 ~ 595 를이용해원하는열에만 GND를물려주고켜지지않아야하는열에는 High를줍니다. 그러니까예를들면 11011101 요런식으로주면 1,2,4,5,6,8열에해당하는 LED만켜지겠죠? 그다음 2행에전압을걸어주면이번엔 595에 10101010을넣어줬다고치면 2 행에 1,3,5,7열만켜지겠죠? 그리고 1행에있는 LED는모두꺼집니다 ( 전압을안주니까요이제 ) 이런식으로 8행까지무지하게빠르게바꿔나가면잔상에의해우리의눈은불이꺼졌다켜졌다하는걸알지못합니다. 그러나카메라로셔터스피드를빠르게하면보이게되죠.. 전철좋아하시는지모르겠지만 ~ 전철타고가다맞은편전철이지나갈때옆면에부착된행선지표시전광판보세요. 정차해있는전철은글이제대로보이지만달리는전철의글은이상하게보이죠? 그것도다이원리때문입니다. 말솜씨가부족해서머리속에서는막생각이헤엄치고있는데쉽게설명하기가쉽지않네요.. 잘 이해가되셨는지.. 잘모르시겠으면소스코드를보심이해가될겁니다!
4. 소스코드 /* ================================================================ 사용컴파일러 : 코드비전 DotMatrix 기초실험제작 : 도시락 (doshrock) 날짜 : 2009/01/22 사용 IC : AtMega8535, 74HC595, 74HC138 포트리스트 : RED LED를제어하는 74HC138 PORTA.0 :: A0 PORTA.1 :: A1 PORTA.2 :: A2 GREEN LED를제어하는 74HC138 PORTA.3 :: A0 PORTA.4 :: A1 PORTA.5 :: A2 74HC595 PORTC.4 :: SER ( 시리얼인풋 ) PORTC.5 :: RCK ( 래치클락 ) PORTC.6 :: SCK ( 쉬프르클락 ) PORTC.7 :: SCLR ( 클리어 ) ================================================================ */ #include <mega8535.h> #define SER PORTC.4 #define RCK PORTC.5 #define SCK PORTC.6 #define SCLR PORTC.7 typedef unsigned char u08;
u08 rowdata[8] = {0xE7, 0xC3, 0x81, 0xC0, 0xE0, 0xC1, 0x83, 0xC7; // 모양그림.. //0xE7은 0b11100111입니다. 즉, 1행의 1,2,3,6,7,8열 LED를켠다는얘기입니다. u08 coldata[8] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07; //1행 ~8행까지선택하게만든건데요, 제방식으로만들경우요놈은바꿀일이없습니다. //delay_us, delay_ms 함수는당근이님이만드신거살짝도용했습니다 ;; void delay_us(unsigned char time_us) { // time delay(us) register unsigned char i; for(i = 0; i < time_us; i++) { // 4 cycle #asm ("PUSH R0 "); // + 2 cycle #asm ("POP R0 "); // + 2 cycle #asm ("PUSH R0 "); // + 2 cycle #asm ("POP R0 "); // + 2 cycle #asm ("PUSH R0 "); // + 2 cycle #asm ("POP R0 "); // + 2 cycle // 16 cycle * 62.5 ns = 1000 ns = 1 us at 16.000MHZ void delay_ms(unsigned int time_ms) { // time delay(ms) register unsigned int i; for(i = 0; i < time_ms; i++) { delay_us(250); delay_us(250); delay_us(250); delay_us(250); void delay() { register int i=1000; while(i--); void SetRow(u08 row)
{// 595에데이터를넣습니다. register int i=0; for ( i = 0 ; i <=7 ; i ++ ) {//595에 serial로데이터를입력시킨다 SER = row & 0x01; //row로입력받은내용을차례대로넣는다. 비트연산혹시모르시면..; 아무리마이크로프로세서라도 C언어는알아야합니다. ㅠ SCK = 1; delay(); SCK = 0; row = row >> 1; // 하나씩 Shift // 입력시킨데이터를 output으로올려보낸다. RCK = 1; delay(); RCK = 0; void SetCol(u08 col) {//138에데이터를넣는다. 굳이함수로만들필요없는데직관적으로보이게하려고 함수안만들고해도됩니다. PORTA = col; void main() { register int i = 0; DDRA = 0xFF; DDRC = 0xFF; SCLR = 1; while(1) { for ( i = 0 ; i <= 7 ; i ++ ) //1행 ~8행까지불을컨트롤 { SetCol(coldata[i]); SetRow(rowdata[i]); delay();
5. 구동이미지
부록 데이터시트