LCD Chinese character display mechanism

Posted by amcgrath on Fri, 14 Jan 2022 23:46:27 +0100

1, Character display mechanism

1. Character display principle

The LCD passes through each pixel. To display a character on the LCD, the following two steps are required:

  • Occupy a place on the screen, the size has the final say in the big font.
  • ② Control whether each pixel is displayed in turn on the occupied place.

For example, Chinese characters 24 × 24 font size indicates that 24 pixels are required horizontally and 24 pixels are required vertically.

In this 24 × 24 of the sites, each pixel is displayed by the font has the final say, each 1 bits of the font data represent a pixel, if the bit is 0, it means that the pixels do not show, 1 shows the code.

Therefore, the function of character display only needs to be realized based on dot function. Read the font bit by bit in the program. If the bit is 0, the point will write the background color, and if the bit is 1, the foreground color will be written.

2. Font generation (dot matrix font)

Because of the mechanism of LCD displaying characters, this font is called dot matrix font.

In order to facilitate you to understand the principle, I first use a gadget to generate a font.

The font generation rules of the setting tool are as follows: negative code, line by line, reverse mold taking and C51 format:

Then generate the font of Chinese characters:

Then copy the generated data and define it in the program as a two-dimensional array as the font. The first value represents the number of elements in the font, which can be determined by the compiler. The second value is the size of each element, which must be specified, so we can use hz_16x16[0] to find the position of the Chinese character "spring" in the font library:

#ifndef _HZ_H_
#define _HZ_H_

const unsigned char hz_16x16[][32] = {
    
{0x01,0x00,0x01,0x00,0x7F,0xFC,0x01,0x00,0x3F,0xF8,0x02,0x00,0xFF,0xFE,0x08,0x20,
0x10,0x10,0x2F,0xE8,0xC8,0x26,0x08,0x20,0x0F,0xE0,0x08,0x20,0x08,0x20,0x0F,0xE0},/*"Spring ", 0*/
/* (16 X 16 , (Arial)*/

};

#endif /* _HZ_H_*/

The font we selected is 16x16, so:

  • There are 16 pixels in the horizontal direction, and each pixel occupies 1 bit, which requires 16bit and two bytes to represent a line;
  • There are 16 lines in the vertical direction, so there are 2 * 16 = 32 bytes as a whole;

The software needs to remove the extra curly braces for each two-dimensional array. Note that the software needs to remove the extra curly braces for each two-dimensional array.

2, How to display characters on LCD

1. Dot function support

Character display needs the support of dot function. Here I use the dot function of RGB-LCD:

void lcd_draw_point(uint16_t x, uint16_t y, uint16_t color);

2. Font support

Introduce the header file of the 2D array we just created:

#include "hz.h"

2. Read font display

void lcd_show_chinese(uint16_t x, uint16_t y, char ch, uint16_t back_color, uint16_t font_color, uint8_t font_size)
{
    uint16_t i, j;
    uint16_t x_pos, y_pos, size, font_width, font_height;
    uint8_t *font_ptr;
    uint8_t bit_width, temp;
	
    if((x > (LCD_WIDTH - font_size)) || (y > (LCD_HEIGHT - font_size)))	{
        return;
    }
	
    x_pos = x;
    y_pos = y;
    font_height = font_size;
    font_width = font_size;
    bit_width = 8;
    size = (font_width / 8 + ((font_width % 8) ? 1 : 0)) * font_height;
    
	font_ptr = (uint8_t*)&hz_16x16[ch];

    for (i = 0; i < size; i++) {
        temp = *(font_ptr + i);
        for (j = 0; j < bit_width; j++) {
            if(temp & 0x80){
                lcd_draw_point(x_pos, y_pos, font_color);
            } else {
                lcd_draw_point(x_pos, y_pos, back_color);
            }
            temp <<= 1;
            x_pos++;
        }
        if (x_pos >= (x + font_width)) {
            y_pos++;
            x_pos = x;
        }
    }
}

After implementation, remember to declare:

/**
 * @brief       Show a chinese char.
 * @param[in]   x1  horizontal start position.
 * @param[in]   y1  vertical start position.
 * @param[in]   x2  horizontal end position.
 * @param[in]   y2  vertical end position.
 * @param[in]   ch  offset in hz library.      
 * @param[in]   back_color  rgb565
 * @param[in]   font_color  rgb565
 * @param[in]   font_size   support 16.
 * @return      None
 * @note        This function need hz library.
*/
void lcd_show_chinese(uint16_t x, uint16_t y, char ch, uint16_t back_color, uint16_t font_color, uint8_t font_size);

3. Test display

Call in the main function:

lcd_show_chinese(0, 0, 0, BLACK, GREEN, 16);

You can see the effect by compiling and downloading:

3, Use of small font library

1. Make small font library

In the project, we need to display some Chinese, but it is not necessary to include the whole Chinese character library, so we often make an exclusive small character library for the project.

The mold taking tool here uses MakeDot of anfulai electronics, which is very convenient:

Input text rearrangement is selected here, which can remove duplicate Chinese characters and reduce the size of font.

Copy the entire array generated as the array we created earlier Hz_ Contents of 16x16:

#ifndef _HZ_H_
#define _HZ_H_

const unsigned char hz_16x16[][32] = {
    
{0x00,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,// ! //
 0x10,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x10,0x00,0x00,0x00,0x00,0x00},


{0x00,0x00,0x20,0x00,0x17,0xFE,0x10,0x08,0x80,0x08,0x43,0xC8,0x42,0x48,0x12,0x48,// River//
 0x12,0x48,0x22,0x48,0xE3,0xC8,0x22,0x48,0x20,0x08,0x20,0x08,0x20,0x28,0x00,0x10},


{0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x7C,0xFE,0x44,0x12,0x44,0x12,0x44,0x12,0x44,// Add//
 0x12,0x44,0x12,0x44,0x12,0x44,0x12,0x44,0x22,0x44,0x22,0x7C,0x4A,0x44,0x84,0x00},


{0x01,0x00,0x01,0x00,0xFF,0xFE,0x01,0x00,0x01,0x00,0x7F,0xFC,0x48,0x24,0x44,0x44,// South//
 0x4F,0xE4,0x41,0x04,0x41,0x04,0x5F,0xF4,0x41,0x04,0x41,0x04,0x41,0x14,0x40,0x08},


{0x00,0x40,0x20,0x40,0x10,0x40,0x10,0x40,0x87,0xFC,0x44,0x44,0x44,0x44,0x14,0x44,// Oil//
 0x14,0x44,0x27,0xFC,0xE4,0x44,0x24,0x44,0x24,0x44,0x24,0x44,0x27,0xFC,0x04,0x04},

};

#endif /* _HZ_H_*/

This completes the production of the small font library of our whole project. In the same way, we can produce hz_24x24 font, hz_32x32 font.

const unsigned char hz_24x24[][72] = {
	//...
};

const unsigned char hz_32x32[][128] = {

};

2. Use small font library

Further improve the Chinese display function and find the code to obtain font data:

font_ptr = (uint8_t*)&hz_16x16[ch]

Optimized as:

switch (font_size) {
    case 16:
        font_ptr = (uint8_t*)&hz_16x16[ch];
        break;
    case 24:
        font_ptr = (uint8_t*)&hz_24x24[ch];
        break;
    case 32:
        font_ptr = (uint8_t*)&hz_32x32[ch];
        break;
    default:
        return;
}

Further add the test program in the main function:

lcd_show_chinese(0, 0, 1, BLACK, RED, 16);      // river
lcd_show_chinese(16, 0, 3, BLACK, RED, 16);     // south
lcd_show_chinese(32, 0, 2, BLACK, RED, 16);     // plus
lcd_show_chinese(48, 0, 4, BLACK, RED, 16);     // oil
lcd_show_chinese(64, 0, 0, BLACK, RED, 16);     // !

lcd_show_chinese(0, 20, 1, BLACK, RED, 24);
lcd_show_chinese(24, 20, 3, BLACK, RED, 24);
lcd_show_chinese(48, 20, 2, BLACK, RED, 24);
lcd_show_chinese(72, 20, 4, BLACK, RED, 24);
lcd_show_chinese(96, 20, 0, BLACK, RED, 24);

lcd_show_chinese(0, 60, 1, BLACK, RED, 32);
lcd_show_chinese(32, 60, 3, BLACK, RED, 32);
lcd_show_chinese(64, 60, 2, BLACK, RED, 32);
lcd_show_chinese(96, 60, 4, BLACK, RED, 32);
lcd_show_chinese(128, 60, 0, BLACK, RED, 32);

The display effect is as follows:

4, Further optimization

This paper describes only the most basic Chinese display method, which can be further optimized.

① Character offset optimization

The inconvenient point of using small font here is that the offset position of characters in the font needs to be controlled by yourself. If you want to automatically control, it involves coding. After implementation, you can directly write Chinese character strings to display.

② Font optimization

The safer way in the project is to use the full font library. The on-chip Flash is certainly not enough. The usual way is to plug in a SPI Flash, burn the whole full font file into Flash and read it when you use it.

③ Font optimization

In this article, we all use Song typeface when taking models. It's not easy to build a font. Maybe one day the boss suddenly came and said that he would change it to some strange font. That's not the end~

Therefore, in the implementation, we should consider establishing a file system on SPI Flash to directly use files to facilitate the replacement of font files.

I will also write articles and share these optimization points later. I'm going out to eat this weekend~

Topics: LCD