STM32 LCD 디스플레이 ASCII 문자 표시 实验

이전 강좌에서는 다양한 인코딩 형식과 비트맵 폰트 관련 기초 지식을 학습하였다. 이번 강좌에서는 STM32 내부 Flash 메모리에 저장된 폰트 데이터를 사용하여 LCD에 문자를 표시하는 실험을 다룬다. 이 방식은 폰트 데이터 크기가 비교적 작은 경우에 적합하다. 폰트 데이터가 큰 경우에는 외부 저장소를 사용하는 방법이 필요하며, 이는后续 강좌에서 설명할 예정이다.

하드웨어 설계

1. 내부 폰트库 방식

STM32 내부 Flash에 폰트 데이터를 저장하는 방식은 별도의 하드웨어가 필요하지 않다. 다만, 폰트 크기가 작은 경우에만 사용하는 것이 권장된다.

2. 외부 폰트库 방식

  • SPI-Flash 방식: 사전에 해당 폰트 파일이 플래시에 기록되어 있어야 한다
  • SD 카드 방식: FAT 형식이어야 하며, 프로그램에서 설정한 경로와 폰트 파일 위치가 일치해야 한다

ASCII 문자 표시 구현

実装 포인트

  1. 비트맵 폰트 데이터 확보
  2. 폰트 형식에 맞는 LCD 표시 함수 구현
  3. 영문 표시 테스트 프로그램 작성

코드 설명

ASCII 비트맵 데이터

ASCII 문자의 개수가 많지 않으므로, C 언어 const 배열로 비트맵 데이터를 직접 저장한다. const 배열은 STM32 내부 Flash에 상수로 저장된다.

/***********************영문 비트맵 폰트******************************/
/*
 * 기본 ASCII 테이블, 오프셋 32, 크기: 16(높이) x 8 (너비)
 */
const uint8_t ASCII8x16_FontData [ ] = {       //@conslons 폰트, 양코드 점진식, 행순서 추출
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x18,0x18,0x18,0x18,0x18,0x18,0x08,0x00,0x08,0x18,0x00,0x00,0x00,
// ... 나머지 문자 데이터省略
};

폰트 관리 구조체

typedef struct _tFont
{    
  const uint8_t *table;
  uint16_t Width;
  uint16_t Height;
  
} sFONT;

sFONT Font8x16 = {
  ASCII8x16_FontData, 
  8,  /* 너비 */
  16, /* 높이 */
};

sFONT Font16x32 = {
  ASCII16x32_FontData, 
  16, /* 너비 */
  32, /* 높이 */
};

sFONT Font24x48 = {
  ASCII24x48_FontData, 
  24, /* 너비 */
  48, /* 높이 */
};

폰트 전환

static sFONT *LCD_Currentfonts;  //영문 폰트

/**
  * @brief  영문 폰트 유형 설정
  * @param  fonts: 선택할 폰트
  *   매개변수 값:
  *   @arg: Font24x32;
  *   @arg: Font16x24;
  *   @arg: Font8x16;
  * @retval 없음
  */
void LCD_SetFont(sFONT *fonts)
{
  LCD_Currentfonts = fonts;
}

ASCII 문자 표시 함수

/**
 * @brief  ILI9806G 디스플레이에서 영문 문자 하나 표시
 * @param  usX : 특정 스캔 방향에서 문자의 시작 X 좌표
 * @param  usY : 특정 스캔 방향에서 문자의 시작 Y 좌표
 * @param  cChar : 표시할 영문 문자
 * @note LCD_SetBackColor, LCD_SetTextColor, LCD_SetColors 함수로 색상 설정 가능
 * @retval 없음
 */
void ILI9806G_DispChar_EN ( uint16_t usX, uint16_t usY, const char cChar )
{
    uint8_t  byteCount, bitCount, fontByteSize;    
    uint16_t ucRelativePositon;
    uint8_t *Pfont;
    
    //ASCII 코드 오프셋 (비주얼 기호 제외)
    ucRelativePositon = cChar - ' ';
    
    //각 문자의 바이트 수
    fontByteSize = (LCD_Currentfonts->Width * LCD_Currentfonts->Height) / 8;
        
    //비트맵 시작 주소
    Pfont = (uint8_t *)&LCD_Currentfonts->table[ucRelativePositon * fontByteSize];
    
    //표시 윈도우 설정
    ILI9806G_OpenWindow ( usX, usY, LCD_Currentfonts->Width, LCD_Currentfonts->Height);
    
    ILI9806G_Write_Cmd ( CMD_SetPixel );            

    //바이트 단위로 비트맵 데이터 읽기
    for ( byteCount = 0; byteCount < fontByteSize; byteCount++ )
    {
        //비트 단위로 처리
        for ( bitCount = 0; bitCount < 8; bitCount++ )
        {
            if ( Pfont[byteCount] & (0x80>>bitCount) )
                ILI9806G_Write_Data ( CurrentTextColor );            
            else
                ILI9806G_Write_Data ( CurrentBackColor );
        }    
    }    
}

문자열 표시 함수

//행 번호를 화면 픽셀 Y 좌표로 변환
#define LINE(x) ((x) * (((sFONT *)LCD_GetFont())->Height))


/**
 * @brief  ILI9806G 디스플레이에서 영문 문자열 표시
 * @param  line : 특정 스캔 방향에서 문자열의 시작 Y 좌표
  *   이 매개변수는 LINE(0), LINE(1)等形式으로 지정 가능,
  *   LINE(x) 매크로는 현재 선택된 폰트의 높이를 기준으로 Y 좌표 계산.
    *   한글 표시 시 LINE 매크로 사용시 Font8x16으로 영문 폰트 설정 필요
 * @param  pStr : 표시할 영문 문자열 시작 주소
 * @note LCD_SetBackColor, LCD_SetTextColor, LCD_SetColors 함수로 색상 설정 가능
 * @retval 없음
 */
void ILI9806G_DispStringLine_EN ( uint16_t line, char * pStr )
{
    uint16_t usX = 0;
    
    while ( * pStr != '\0' )
    {
        if ( ( usX - ILI9806G_DispWindow_X_Star + LCD_Currentfonts->Width ) > LCD_X_LENGTH )
        {
            usX = ILI9806G_DispWindow_X_Star;
            line += LCD_Currentfonts->Height;
        }
        
        if ( ( line - ILI9806G_DispWindow_Y_Star + LCD_Currentfonts->Height ) > LCD_Y_LENGTH )
        {
            usX = ILI9806G_DispWindow_X_Star;
            line = ILI9806G_DispWindow_Y_Star;
        }
        
        ILI9806G_DispChar_EN ( usX, line, * pStr);
        
        pStr ++;
        
        usX += LCD_Currentfonts->Width;
    }
}

화면 지우기 함수

/**
 * @brief  ILI9806G 디스플레이의 특정 윈도우를 지정된 색상으로 클리어
 * @param  usX : 특정 스캔 방향에서 윈도우 시작 X 좌표
 * @param  usY : 특정 스캔 방향에서 윈도우 시작 Y 좌표
 * @param  usWidth : 윈도우 너비
 * @param  usHeight : 윈도우 높이
 * @note LCD_SetBackColor, LCD_SetTextColor, LCD_SetColors 함수로 색상 설정 가능
 * @retval 없음
 */
void ILI9806G_Clear ( uint16_t usX, uint16_t usY, uint16_t usWidth, uint16_t usHeight )
{
    ILI9806G_OpenWindow ( usX, usY, usWidth, usHeight );
    ILI9806G_FillColor ( usWidth * usHeight, CurrentBackColor );        
}

/**
  * @brief  특정 행의 문자 삭제
  * @param  Line: 삭제할 행 지정
  *   이 매개변수는 LINE(0), LINE(1)等形式으로 지정 가능,
  *   LINE(x) 매크로는 현재 선택된 폰트의 높이를 기준으로 Y 좌표 계산 후 해당 행 삭제.
  * @retval 없음
  */
void ILI9806G_ClearLine(uint16_t Line)
{
  ILI9806G_Clear(0, Line, LCD_X_LENGTH, ((sFONT *)LCD_GetFont())->Height);
}

주요 함수 사용 예시

int main(void)
{    
    //LCD 초기화
    ILI9806G_Init ();         

    /* USART 설정 */
    Debug_USART_Config();        

    printf("\r\n ********** LCD 문자 표시 프로그램(외부 FLASH 폰트)*********** \r\n"); 
    printf("\r\n 한글 표시가 정상이지 않으면 readme.txt 파일 참조, FLASH에 폰트 데이터 재기록 필요\r\n"); 

    //0, 3, 5, 6 모드는 왼쪽에서 오른쪽으로 문자 표시에 적합
    //다른 모드는 문자 미러링 효과 발생
    //6 모드가 대부분의 LCD 예제 기본 표시 방향
    ILI9806G_GramScan ( 6 );
    
    Printf_Charater();
    
    while ( 1 )
    {
        LCD_Test();
    }
}

테스트 함수 구현

/* 다양한 LCD 테스트용 함수 */
void LCD_Test(void)
{
    /* 시연용 변수 */
    static uint8_t testCNT = 0;
    char dispBuff[100];
    
    testCNT++;
    LCD_SetFont(&Font16x32);
    LCD_SetColors(RED, BLACK);
    ILI9806G_Clear(0, 0, LCD_X_LENGTH, LCD_Y_LENGTH); /* 화면 클리어 */
    
    /******** 문자열 표시 예시 *******/
    ILI9806G_DispStringLine_EN(LINE(0), "BH 4.5 inch LCD");
    ILI9806G_DispStringLine_EN(LINE(2), "resolution:480x854px");
    ILI9806G_DispStringLine_EN(LINE(3), "LCD driver:ILI9806G");
    ILI9806G_DispStringLine_EN(LINE(4), "Touch driver:GT5688");
    
    /******** 변수 표시 예시 *******/
    LCD_SetTextColor(GREEN);
    /* c 표준 라이브러리로 변수→문자열 변환 */
    sprintf(dispBuff, "Count : %d ", testCNT);
    ILI9806G_ClearLine(LINE(7)); /* 한 행 삭제 */
    
    /* 문자열 표시, 다른 변수도 동일한 방식 */
    ILI9806G_DispStringLine_EN(LINE(7), dispBuff);
}

실행 결과

위 코드를 실행하면 LCD 화면에 다음과 같은 정보가 표시된다:

  • 화면左上角에 화면 크기 및 드라이버 칩 정보 표시
  • 아래쪽에 카운트 값이 초당 업데이트
  • 적/녹/검정색 색상 구분이 명확하게 표시

주의사항

ILI9806G_DispStringLine_EN 함수를 사용할 때 Y 방향 문자 겹침에 주의해야 한다. 예를 들어 (10, 20) 좌표에 높이 16 픽셀의 문자열을 표시한 후, 같은 X 좌표에 (10, 25)에 다른 문자열을 표시하면 높이가 부족하여 겹침 현상이 발생한다. 따라서 Y 좌표 계산 시 현재 폰트 높이를 반드시 고려해야 한다.

태그: STM32 LCD ILI9806G ASCII Embedded

6월 29일 03:01에 게시됨