본문 바로가기

Embedded/AVR

ATMEGA128을 이용한 LCD(캐릭터)제어 - 4bit

//###################################################################//

//              캐릭터 LCD 제어 프로그램                                      
// Compiler : CodeVision
// Productor: Shim Woo Sung

//<각 포트 구현>
//RS : PORTB.0
//RW : PORTB.1
//E  : PORTB.2
//Data line : PORTD

//###################################################################//
#include<mega128.h>
#include<delay.h>
#include<string.h>
//###################################################################//
//
//                      <LCD 제어 포트 설정>
#define H 1
#define L 0

#define TRUE  1
#define FALSE 0

#define RS   PORTB.0 
#define RW   PORTB.1
#define E    PORTB.2
#define DATA PORTD

//###################################################################//
//
//                      <Function Set>
// <설 명>
// - LCD초기화를 설정하기 위한 명령 
//
// RS RW DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0
//  0    0    0     0     1    DL    N    F     -     -
//
//  DL   : 몇 비트의 라인으로서 인터페이스를 할 것인지를 결정한다.
//  DL=1 : 8비트(DB7 ~ DB0) 라인을 사용해서 인터페이스 할 수 있다.
//  DL=0 : 4비트(DB7 ~ DB4) 라인을 사용해서 인터페이스 할 수 있다.
//  (이때는 상위 4비트의 데이터 전송을 하고, 다음에 하위 4비트의 데이터를 전송해야 한다.)
//  N    : 글자를 표기하는 디스플레이 라인의 수를 결정한다.
//  F    : 글자 폰트를 결정한다.
//
//  N   F       디스플레이 라인         글 자 폰 트        Duty Factor     
//  0   0               1                        5*8  Dot             1/8
//  0   1               1                        5*10 Dot            1/11
//  1   *               2                        5*8  Dot             1/16             
//  ※ 5*10 Dot의 글자폰트는 2라인으로 디스플레이 안 됨

#define INTERFACE_8BIT 0x30
#define INTERFACE_4BIT 0x20
#define LINE_1         0x20
#define LINE_1_58DOT   0x24
#define LINE_2         0x28

unsigned char FUNCTION_SET = INTERFACE_8BIT | LINE_2;

//###################################################################//
//
//                      <Entry Mode Set>
//
// <설 명>
// - DB2 비트가 1인 경우로서 커서의 움직이는 방향을 설정하거나 글자 시프트할 것인지 결정한다.
//   명령이 수행하는데 필요한 시간 : 37uS
 
// RS RW DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0
//  0    0    0     0     0     0     0     1    I/D   S
// I/D : D.D.RAM의 어드레스의 인크리먼트(증가 : I/D=1) 혹은 디크리먼트(감소 : I/D=0) 결정한다.
//  S  : 글자가 표기된 전체 디스플레이를 오른쪽.왼쪽으로 이동시키기 위한 변수
//          I/D=1, S=1 : 글자가 표기된 디스플레이는 왼쪽으로 시프트한다.
#define LEFT_SHIFT  0x07

//          I/D=0, S=1 : 글자가 표기된 디스플레이는 오른쪽으로 시프트한다.
#define RIGHT_SHIFT 0x05

//          S=0 : 글자가 표기된 디스플레이는 시프트되지 않는다.
#define SHIFT_OFF 0x00

unsigned char ENTRY_SET = RIGHT_SHIFT;
//###################################################################//
//
//                      <Display ON/OFF Control>
//
// <설 명>
// - DB3번 비트가 1인 경우 Display On/Off 제어 한다.
//   명령이 수행하는데 필요한 시간 : 37uS
// RS RW DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0
//  0    0    0     0     0     0     1     D     C    B
//
// D : 글자가 표기되는 디스플레이를 ON/OFF 하기 위한 변수이다.
//          D=1 : 글자가 표기되는 디스플레이 부분이 ON되어서 글자가 나타난다.
#define DISPLAY_ON       0x0c

// D=0 : 글자가 표기되는 디스플레이 부분이 OFF되어서 글자가 나타나지 않는다.
// (이때, 디스플레이 부분의 글자 데이터가 D.D.RAM에 남아 있기 때문에 D=1로 하면 글자가 나타 난다.)
#define DISPLAY_OFF      0x08

// C : 커서 부분의 ON/OFF 제어하는 변수이다.
//      C=1 이면 커서가 나타난다.
#define CURSER_ON        0x0a

//      C=0 이면 커서가 나타나지 않는다.
//      ※ 5*8 Dot의 경우 8행째에, 5*10도트의 경우 11행째에 커서가 존재한다.
#define CURSER_OFF       0x08
// B : 커서의 위치에 있는 문자를 깜박이게 하는 변수이다.
//      B=1 이면 커서 위치의 문자를 깜박인다.
#define CURSER_BLANK_ON  0x09

//      B=0 이면 커서 위치의 문자를 깜박이지 않는다. 
#define CURSER_BLANK_OFF 0x08

unsigned char DISPLAY_SET = DISPLAY_ON | CURSER_OFF | CURSER_BLANK_OFF;

//###################################################################//
//
//                      <Etc Command>
//
//※ 화면 클리어
//  - LCD의 화면의 내용을 클리어하고 커서 위치는 홈(0번지)으로 돌아간다.
// RS RW DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0
//   0   0    0     0     0     0     0     0     0     1
#define CLEAR            0x01

//※ 커서 홈
//  - 커서의 위치를 홈으로 돌아가게 하는것으로 D.D.RAM의 내용은 변하지 않는다.
//   명령이 수행하는데 필요한 시간 : 1.52mS

// RS RW DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0   
//  0    0    0     0     0     0     0      0     1    -
#define RETURN_HOME      0x02         

//###################################################################//
void portSet(void) //PORT I/O 기능 설정
{
        DDRB = 0xff; //LCD 제어 포트
        DDRD = 0xff; //LCD 데이터 포트
        
        PORTB = 0x00;//포트 초기화
        PORTD = 0x00;//포트 초기화
}
                  
void instructionSet(unsigned char data)
{
        RS = L;
        RW = L;
        delay_ms(1);
        E = H;
        DATA = data;
        delay_ms(1);
        E = L;
        RS = L;
        RW = L;
        delay_ms(1);
}

void charPosition(int x, int y)
{
        unsigned char position;

         if (y > 1) y = 1;
         if (x > 15) x = 15;
         position = y ? x + 0xc0 : x + 0x80;
         instructionSet(position);
}

void charDisplay(char display)
{
         RW = L;    
         RS = H;     
         delay_ms(1);
         E = H;    
         delay_ms(1);
         DATA = display;
         delay_ms(1);
         RW = L;
         RS = H; 
         E = L;
         delay_ms(1);       
}

void stringDisplay(char *str)
{        
        int i=0;
        for(i=0; i<16; i++)
        {
                charDisplay( *(str+i));
        }       
}

//###################################################################//
//
//                      <LCD 초기화 순서>
//
// 1. VCC가 4.5V가 된 후 15ms이상 지연 (명령중에는 비지 플러그 체크 불가)
//
// 2. Fuction Setting
//      - Data Line Interface 방식
//      - 출력 라인
//      - 커서 On/Off
//      - 커서 위치(커서 On 했을 시)
//      - 디스플레이 On/Off
//
// 3. 화면 클리어

// <함수 구현시>
void initLCD(void)
{
        delay_ms(15);
        instructionSet(FUNCTION_SET); //Funtion Set 주석 참조
        instructionSet(DISPLAY_SET);  //Display On/Off 주석 참조
        instructionSet(CLEAR); //Etc Command 주석 참조
}
//###################################################################//
void main(void)
{
        char *str = "      Zero      ";
       
        //초기화
        portSet(); //LCD 관련 포트 설정 / 초기화
        initLCD(); //LCD 초기화 / 화면 클리어        
    
        charPosition(0, 0); //화면상 출력될 글자 위치 설정
        stringDisplay(str); //문자열 화면 출력
        while(TRUE)
        {
        
        }
}