百为STM32开发板教程之八——汉字显示
1、了解汉字编码
2、了解汉字点阵数据及显示过程
3、利用.c字库文件在程序中显示汉字
1、国标码:
国标码(GB2312-80):中国标准总局1981年制定了中华人民共和国国家标准GB2312--80《信息交换用汉字编码字符集--基本集》,即国标码。
是从0x2121开始的编码,具体可以参考下面的网页
http://examples.oreilly.com/cjkvinfo/unicode/gb2312-80.txt
3、机内码
根据国标码的规定,每一个汉字都有确定的二进制编码,在微机内部汉字代码都用机内码,在磁盘上记录汉字代码也使用机内码。
2、汉字区位码:
区位码是国标码的另一种表现形式,把国标GB2312--80中的汉字、图形符号组成一个94×94的方阵,分为94个“区”,每区包含94个“位”,其中“区”的序号由01至94,“位”的序号也是从01至94。94个区中位置总数=94×94=8836个,其中7445个汉字和图形字符中的每一个占一个位置后,还剩下1391个空位,这1391个位置空下来保留备用。
汉字区位码也叫汉字机内码,汉字机内码由国标码(GB2312-80)演化而来,把表示国际码的两个字节的最高位分别加1(加0x8080),就变成了汉字机内码。
是从0xA1A1开始的编码,具体可以参考下面的网页
http://www.knowsky.com/resource/gb2312tbl.htm
因此在程序中定义了汉字字库表之后,就可以通过汉字在表中的偏移,取得它的点阵数据,然后我们把点阵数据按一定高度和宽度扫描到LCD上,就可以显示汉字了
定义汉字字库表:
const uint8_t GB2312_16x16_Table [] =
{
……
}
程序中调用显示汉字函数:
LCD_DisplayString(80,100,"啊"); //这里“啊”是用汉字机内码表示,即0xB0A2
然后在LCD_DisplayString里判断编码是否大于等于0xA1,如果是表示当前要显示的是汉字:
void LCD_DisplayString(uint16_t xPos, uint16_t yPos, uint8_t *ptr)
{
uint32_t index = 0;
while (*ptr != 0) //显示一串字符串
{
if(*ptr < 0xA1) //当前字符是否小于0xA1,如果是,表示是非汉字显示
{
LCD_DisplayChar(xPos, yPos, *ptr); //显示ASCIII字符
if ( *ptr == 'A' || *ptr == 'G' || *ptr == 'M' || *ptr == 'O' || *ptr == 'Q' || *ptr == 'X' || *ptr == 'm') //宽字符显示
xPos += (LCD_Currentfonts->Width);
else
xPos += (LCD_Currentfonts->Width - 1);
ptr++; //指向下一个字符,ASCII字符只占一个字节
index++;
}
else
{
LCD_DisplayChineseChar(xPos, yPos, ptr); //显示一个汉字
xPos += (LCD_Currentfonts->Width - 1);
ptr++; //指向下一个字符,一个汉字占用两个字节
ptr++; //
index++;
}
}
}
调用函数LCD_DisplayChineseChar计算出汉字点阵数据在字库表中的偏移,显示一个汉字点阵数据
void LCD_DisplayChineseChar(uint16_t Line, uint16_t Column, uint8_t *Char_GB)
{
uint32_t offset;
uint16_t byteOfDots;
byteOfDots = LCD_Currentfonts->Height*(LCD_Currentfonts->Width/16);
offset = 94 * (*Char_GB - 0xA1) * byteOfDots + (*(Char_GB+1) - 0xA1) * byteOfDots;
LCD_DrawChineseChar(Line, Column, &GB2312_16x16_Table[offset]);
}
最终把点阵数据取出,画到LCD上的函数:
void LCD_DrawChineseChar(uint16_t Xpos, uint16_t Ypos, const uint16_t *c) /* 16bit char */
{
uint32_t line_index = 0, pixel_index = 0;
uint8_t Xaddress = 0;
uint16_t Yaddress = 0;
__IO uint16_t tmp_color = 0;
Xaddress = Xpos;
Yaddress = Ypos;
LCD_SetCursor(Xaddress, Ypos);
for (line_index = 0; line_index < LCD_Currentfonts->Height; line_index++)
{
LCD_WriteRAM_Prepare(); /* Prepare to write GRAM */
for (pixel_index = 0; pixel_index < LCD_Currentfonts->Width/2; pixel_index++)
{
/* SmallFonts have bytes in reverse order */
if ((((const uint16_t*)c)[line_index] & (0x80 >> pixel_index)) == 0x00)
{
LCD_WriteRAM(BackColor);
}
else
{
LCD_WriteRAM(TextColor);
}
}
for (pixel_index = 0; pixel_index < LCD_Currentfonts->Width/2; pixel_index++)
{
/* SmallFonts have bytes in reverse order */
if ((((const uint16_t*)c)[line_index] & (0x8000 >> pixel_index)) == 0x00)
{
LCD_WriteRAM(BackColor);
}
else
{
LCD_WriteRAM(TextColor);
}
}
// Xaddress++;
// Yaddress = Ypos;
Ypos++;
LCD_SetCursor(Xaddress, Ypos);
}
}
|