8x8 Dot LED (MAX7219 Controller)

1. 8x8 LED Matrix
     FND는 7개의 LED를 사용하여 숫자 또는 간단한 문자를 표현하는 것에 비하여 8x8 Dot LED Martix는 숫자 뿐만 아니라 다양한 문자 또는 기호를 표현 할 수 있는 간단한 표시장치이다.



Mambraine 4x4 Keypad의 앞면과 뒷면


     많은 8x8 LED matrix가 아래 그림과 같이 내부에 MAX7219 컨트롤러를 사용하기때문에 8x8 LED matrix를 사용하기 위하여 MAX7219를 조금 이해할 필요가 있다.

판매되고 있는 8x8 DOt LED matrix (기판 가운데 보이는 IC가 MAX7219임)


2. MAX7219
     MAX7219는 "Serially Interfaced, 8-Digit, LED Display Drivers"으로 직ㄹ렬통신 방법으로 여러개의 LED를 쉽게 컨트롤 할 수 있는 드라이버이다. 아래 그림에서도 볼 수 있듯이 직렬통신에 사용하는 핀은 DIN, LOAD(CS^), CLK등 3개의 선을 이용하여 통신 할 수 있다. 일반적으로 LEX Matrix Module의 경우 통신을 위한 3선과 전원 공급을 위한 2선 모두 5선을 제공하고 있다. MAX7219의 구조는 LED 8개를 각각 컨트롤 할 수 있는 Segment가 8개 존재하여 8개의 LED를 한번에 컨트롤 가능하다. 또한 8개의 Digit 선을 제공하고 있어 8개가 1세트로 이루어진 LED를 8개를 켜고 끌 수 있다. 따라서 8개로 이루어진 LED 8개를 컨트롤 할수 있어 모두 64개의 LED를 컨트롤 할 수 있도록 만든 IC이다. 따라서 LED Matrix Module을 다루기 위하여 MAX721을 이해하여야 한다.

     
ref) datasheets.maximintegrated.com/en/ds/MAX7219-MAX7221.pdf
MAX7219 Serially Interfaced, 8-Digit, LED Display Drivers

3. MAX7219 기능
     MAX7219의 기능은 아래 기능도에서 볼 수 있듯이 내부에 통신관련 기능을 할 수 있는 부분, 특수 기능을 위한 Register(일정한 기능을 수행하기위한 적은 단위의 기억장치), 그리고 LED 밝기 및 스캔을 위한 기능이 있다. 이러한 기능 중에서 통신관련 기능, Register관련해서는 데이타시트를 참고하여야 한다.


MAX7219 Functional Diagram



4. MAX7219 Timming Sequence
     MAX7219와 Microcontroller와의 통신을 위하여 MAX7219는 3선을 사용한다. Chip Select를 위한 선, 데이타를 MAX7219으로 주기위한 DIN 선, 신호 동기를 위한 CLK 선 등 모두 3선을 사용한다. Microcontroller의 3 선과 MAX7219 통신선 3개와 연결하고, Microcontroller에서 Bit Data를 MAX7219로 보내면 된다. Microcontroller에서 보내는 데이타의 형식은 16 Bit로 Address용 8 Bit (1 Byte)를 보낸 후, Data 8 Bit (1 Byte)를 보내는 형식으로 되어있다. 아래 그림에서의 상위 8 Bit에서 "X"는 Bit 값이 1 이든 0 이든 상관 없다는 표시이다. 주로 0을 사용한다.


MAX7219 Serial Data Format

MAX7219 Timming Diagram



     MAX7219와 Microcontroller와의 통신방법에서 데이타시트에 나와있는 시간에 따른 신호관계(위 그림)은 LED Module을 다루기 위한 코딩에 매우 중요하며, 코딩할때 반드시 참고하여야한다. 위의 그림을 참고하면 통신을 하기위하여 순서를 살펴보면 다음과 같다.

     1. LOAD(CS^) 신호를 High에서 Low로: LOAD 신호가 Low에서 MAX7219가 활성화 됨
     2. DIN 핀을 통하여 Data를 씀: Microcontroller를 사용하여 Bit Data 출력(Microcontroller입장에서 출력)
     3. CLK 핀을 통하여 Low에서 High로 다시 Low로: CLK 신호가 Low에서 High로 될때 MAX7219가 Data를 취함
     4. 2번 3번 과정을 15번 반복 (바로 위 과정 제외, 전체 16 번))
     5. LOAD(CS^) 신호를 High로: MAX7219가 비활성화 됨

아래 그림을 참고하면 쉽게 이해 할 수 있다.


POC와 MAX7219와의 통신과정(LED 밝기 조절을 위한 명령어(0x0A) 및 값(0x07)



5. MAX7219 Register
     MAX7219는 크게 14 개의 Register를 가지고 있고 각각의 Register의 기능에 따라 어떠한 값을 갖는냐에 따라 값에 해당하는 기능을 하게 된다. 아래 표는 MAX7219가 가지고 있는 14개의 Register의 Address에 대하여 보여 주고 있다. 이중 실제 사용하는 몇가지 Register에 대하여 설명하면,


     
- Digit Register (Address 0x01 ~ 0x08)
       8x8 LED의 제일 밑 줄 부터 윗줄까지 관여하는 레지스터로 실제 LED에 표시하기위하여 사용

      Digit 0 Register (Address 0x01): 1 번째 LCD Set(8 개의 LED, 1 개의 FND)
      Digit 1 Register (Address 0x02): 2 번째 LCD Set(8 개의 LED, 1 개의 FND)
      Digit 2 Register (Address 0x03): 3 번째 LCD Set(8 개의 LED, 1 개의 FND)
      Digit 3 Register (Address 0x04): 4 번째 LCD Set(8 개의 LED, 1 개의 FND)
      Digit 4 Register (Address 0x05): 5 번째 LCD Set(8 개의 LED, 1 개의 FND)
      Digit 5 Register (Address 0x06): 6 번째 LCD Set(8 개의 LED, 1 개의 FND)
      Digit 6 Register (Address 0x07): 7 번째 LCD Set(8 개의 LED, 1 개의 FND)
      Digit 7 Register (Address 0x08): 8 번째 LCD Set(8 개의 LED, 1 개의 FND)

     만약 1 번째 줄 LED 8개를 모두 켠다면
     Digit 0 Register인 Address 0x01에 0xFF를 써 넣으면 된다.
     예) write_MAX_7219 (1, 0xFF) ;


     다른 Register로서 Module을 Shutdown 할 수 있는 Shutdown Register (Address: 0x0C), LED의 밝기를 조절 할 수 있는 Intensity Register (Address: 0x0A), 그리고 스캔 영역을 정하기 위한 Scan-Limit Register (address: 0x0B)가 있다. 이 3 가지 Register는 주로 LED를 동작하기위하여 초기치 값으로 설정하기 위하여 주로 사용한다.
     
- Shutdown Register (Address: 0x0C)
       아래 표에서 볼 수 있듯이 D0 값이 0 인경우 Module이 꺼진상태, 1 인경우 정상동작.

     
- Intensity Register (Address 0x0A)
       아래 표에서 볼 수 있듯이 모두 16 단계의 밝기를 조절, 밝기 값은 D3, D2, D1, D0의 값에 따라 결정

     
- Scan-Limit Register (Address 0x0B)
       LED의 스캔 범위를 설정



     위의 Shutdown, Intensity, 그리고 Scan Limit Register를 사용한 MAX7219의 초기화 관련 코드는 아래와 같이 표현 가능하다.

     void init_MAX7219 (void)
     {
          write_MAX_7219 (SHT_DW, 0x01) ; //* 01:Normal Operation, 00: Shutdown
          write_MAX_7219 (INT_LT, 0x02) ; //* Light Intensity (0 ~ 15, 16 Steps)
          write_MAX_7219 (SCN_LM, 0x07) ; //* Scan Limit (Scan All, 0 ~ 7 Degits)
     }



     아래 프로그램은 8x8 Dot LED Matrix(MAX7219 사용)를 사용하여 몇가지 모양을 표시하기 위한 코드이다.

* 8x8 LCD Matrix Module을 사용하기 위한 Code
//* ****************************************************************************
//* *** 8x8 LCD Matrix Module을 사용하기 위한 Code *****************************
//* ****************************************************************************
//
//    Dot LED 8x8 - Max7219.X
//
//	  MAX7219: Serially Interfaced, 8-Digit, LED Display Drivers
//	
//
//* ****************************************************************************

#include    <16f18345.h>                   //* 사용 PIC
#fuses      HS,NOMCLR                        //* 20M 크리스탈 사용
#use        delay (clock = 20000000)    //* 20M 크리스탈 사용

//*** LCD 를 위한 핀 설정 ******************************************************
#pin_select		U1TX = PIN_B7       //* TX 핀을 B7으로 설정
#pin_select		U1RX = PIN_B5       //* RX 핀을 B5로 설정
#use			         rs232 (baud=19200, parity=N, xmit=PIN_B7, rcv=PIN_B5)   //* UART 설정

//******************************************************************************
//*** MAX7219 핀 설정 ***********************************************************
#define CLK_PIN     PIN_C7                      //* MAX7219 CLOCK 핀을 C7에 연결
#define CS_PIN      PIN_C6                       //* MAX7219 CS(LOAD) 핀을 C6에 연결
#define DIN_PIN     PIN_C5                      //* MAX7219 DIN 핀을 C5에 연결

#define ENABLE      output_low(CS_PIN)          //* 활성화 정의
#define DISABLE     output_high(CS_PIN)         //* 비활성화 정의

#define CLK_L       output_low(CLK_PIN)         //* Clock Low 정의
#define CLK_H       output_high(CLK_PIN)       //* Clock High 정의

int8    datFont [50][8] = {                                //* 화면 글씨 정의 (2차원 어레이)
            {0x3C,0x42,0x99,0xA5,0x81,0xA5,0x42,0x3C},  //* Good 
            {0x3C,0x42,0xBD,0x81,0x81,0xA5,0x42,0x3C},  //* Bad      
            {0x08,0x14,0x22,0x41,0x41,0x49,0x36,0x00},  //* Heart1
            {0x00,0x08,0x14,0x22,0x3A,0x36,0x00,0x00},  //* Heart2   
            {0x00,0x00,0x08,0x1C,0x14,0x00,0x00,0x00},  //* Heart3  
            {0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x00}   //* Heart5            
        } ;  

//* *******************************************************************************
//* *** MAX7219 함수 ************************************************************
void write_byte_MAX7219 (int8 byData)           //* 1 바이트 Data MAX7219에 쓰기
{   int8 idxBit ;
    
    for (idxBit = 0;idxBit < 8;idxBit++) {
        rotate_left(& byData, 1) ;                          //* MSB를 LSB로 만들기
        output_bit (DIN_PIN, (byData & 0x01)) ; delay_us (5) ; //* 끝자리 0,1 구분하여 출력
        CLK_H ; delay_us (5) ; CLK_L ; delay_us (5) ;                //* 클럭 을 올렸다 내림 (처음은 내려가 있음))
    }
}

void write_MAX_7219 (int8 valAddr, int8 valData)  //* MAX7219에 주소와 데이타 보내기
{   ENABLE ; delay_us(5) ;                                        //* MAX7219 활성화
    write_byte_MAX7219 (valAddr) ;                        //* MAX7219 레지스터 주소보내기
    write_byte_MAX7219 (valData) ;                         //* 데이타 (Value) 보내기
    DISABLE ; delay_us (5) ;                                      //* MAX7219 비활성화
}

void write_one_frame (int8 frmData)                       //* 제일 밑줄부터 제일 윗 줄까지 화면 출력
{   int8 idx_dig ;
    
    for (idx_dig = 0;idx_dig < 8;idx_dig++) {
        write_MAX_7219 (idx_dig+1, datFont[frmData][idx_dig]) ; //* Digit 주소와 해당 값을 MAX7219에 쓰기
    }
}

void init_MAX7219 (void)                   //* MAX7219 초기화
{   DISABLE ; CLK_L ;
    write_MAX_7219 (0x0C, 0x01) ;     //* Shutdown Mode, 01:Normal Operation, 00: Shutdown
    write_MAX_7219 (0x0A, 0x04) ;     //* Light Intensity
    write_MAX_7219 (0x0B, 0x07) ;     //* Scan Limit
}

//******************************************************************************
//*** Start Main Function ******************************************************
void main (void)
{   int8 idx_no ;

    init_MAX7219 () ;
    
    delay_ms (1000) ;
    printf ("$#BL_100;") ; delay_ms (20) ;          //* LCD 밝기 100%
    printf ("$#CLR_LCD;") ; delay_ms (20) ;        //* LCD 화면 지우기
    
    while (1) {
        for (idx_no = 0;idx_no <= 4;idx_no++) {
            write_one_frame (idx_no) ;                  //* 순차적으로 8x8 LED 정해진 글씨 표시
            printf ("$2,1, No. : %2d;", idx_no) ;       //* LCD에 LED 표시된 글씨 번호 표시
            delay_ms (500) ;
        }
    }
}
//*** End Function *************************************************************
//******************************************************************************

  8x8 LED Metrix (MAX7219), C Source Code




위 프로그램을 사용한 결과-1


참고:

     1. Serially Interfaced, 8-Digit, LED Display Drivers
     2. LED Displays Dot Matrix
     3. 8 X 8 LED 도트 매트릭스 모듈
     4. Arduino LED 8X8 Matrix Display MAX7219
     5. Working with LED Dot Matrix Displays
     6. 8x8 LED Matrix for Arduino
     7. Arduino Snake Game | 8X8 Matrix LED Display MAX7219