Drive LCD display based on stm32f103RB system board

First, what is LCD? What is the LCD used for?

consists of

 

Uses: Display what you want to display. (sorry, nonsense)

Second, how to use LCD?

Remarks: The COG LCD screen is used, it can only display black and white images and text, and the displayed pixel size is 128*128.

The corresponding relationship between LCD display dot matrix and DD RAM (display data memory) address:

  • PAGE: 8 lines represent a "page", a 128*128 dot matrix screen is divided into 16 "pages", from the 0th "page" to the 15th "page".
  • DB7--DB0: The data is arranged from bottom to top. The lowest bit D0 is at the top, and the highest bit D7 is at the bottom. Each bit (bit) of data corresponds to a dot matrix, usually "1" means to turn on the dot matrix, and "0" means to turn off the dot matrix. As shown below:

 There are 128 pixels in one row, and the dot matrix can be turned on/off by writing data to the memory

Next, we will use the LCD screen to display simple Chinese and English characters and pictures. Through the above introduction, we can conclude that the relevant setting steps for COG LCD liquid crystal display are as follows:

  • 1. Set the IO connected between STM32 F1 and COG LCD module . Initialize the IO port connected to the COG liquid crystal module to drive the LCD.
  • 2. Initialize the COG LCD module. The initialization sequence is to write a series of setting values ​​(such as gamma calibration) to the LCD controller. These initialization sequences are generally provided by LCD suppliers to customers, and we can use these sequences directly. After initialization, the LCD can be used normally.
  • 3. Display Chinese and English characters and pictures, and display the pictures/characters on the COG LCD screen module by calling the character display function.

3. Actual operation

 

/**
  ****************************************************************************
  * @文件名     : lcd.c
  * @作者       : Apana
  * @文件版本   : V1.0.0
  * @编写日期   : 2020-08-17
  * @说明       : lcd源文件
	*	@备注       : lcd使用JTAG引脚,在使用之前需要禁用JTAG,使能SW
  ******************************************************************************/
/*----------------------------------------------------------------------------
  更新日志:
  2020-08-17 V1.0.0:初始版本
  ----------------------------------------------------------------------------*/
	

/* 包含的头文件 --------------------------------------------------------------*/
#include "lcd.h"
#include "gbhz.h"  	 
#include "ascii.h"
#include "delay.h"

u8 LCD_GRAM[16][128]; //显示缓存

//初始化LCD_GPIO
void LCD_GPIO_Init(void)
{
	GPIO_InitTypeDef  GPIO_InitStructure;		//GPIO结构体定义

	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOC, ENABLE); //使能端口时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE); //开启复用时钟
	GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable,ENABLE);	//禁用JTAG,使能SW
 
	//数据引脚
	GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_6 | GPIO_Pin_7 | GPIO_Pin_12 | GPIO_Pin_14 | GPIO_Pin_15 ; //PC
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;//推挽输出
	GPIO_Init(GPIOC,&GPIO_InitStructure);
	
	GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_8  ; //PB
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;//推挽输出
	GPIO_Init(GPIOB,&GPIO_InitStructure);
	
	//控制引脚
	GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_11;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;//推挽输出
	GPIO_Init(GPIOC,&GPIO_InitStructure);
	GPIO_SetBits(GPIOC,GPIO_Pin_9);		  //将引脚置
	GPIO_ResetBits(GPIOC,GPIO_Pin_8 | GPIO_Pin_10 | GPIO_Pin_11);	  //将引脚复位
	//LCD-RD
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;	
	GPIO_Init(GPIOB, &GPIO_InitStructure); //根据设定参数初始化
	GPIO_SetBits(GPIOB,GPIO_Pin_13); //输出高	
	//背光灯初始化
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //使能PA端口时钟
	//释放JTAG的IO口保留SWD
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE); 
	GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable,ENABLE); 
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;					//引脚PA8	
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;	//时钟频率
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;	//推挽输出
	GPIO_Init(GPIOA, &GPIO_InitStructure); 		//根据设定参数初始化
	GPIO_SetBits(GPIOA,GPIO_Pin_8); 					//输出高电平,开启背光灯	
}
//lcd写模式
void LCD_WRITE(u8 x)
{
	if(x&0x01)PCout(14) = 1;else PCout(14) = 0;
	if(x&0x02)PCout(15) = 1;else PCout(15) = 0;
	if(x&0x04)PBout(4) = 1;else PBout(4) = 0;
	if(x&0x08)PBout(3) = 1;else PBout(3) = 0;
	if(x&0x10)PCout(12) = 1;else PCout(12) = 0;
	if(x&0x20)PBout(8) = 1;else PBout(8) = 0;
	if(x&0x40)PCout(6) = 1;else PCout(6) = 0;
	if(x&0x80)PCout(7) = 1;else PCout(7) = 0;
}

//写命令
void LCD_WR_CMD(u8 cmd)
{
	LCD_CS = 0;
	LCD_RS = 0;
	LCD_RD = 0;
	LCD_WR = 0;
	LCD_WRITE(cmd);
	LCD_RD = 1;
	LCD_CS = 1;
	LCD_RD = 0;
}

//写数据
void LCD_WR_DATA(u8 data)
{
	LCD_CS = 0;
	LCD_RS = 1;
	LCD_RD = 0;
	LCD_WR = 0;
	LCD_WRITE(data);
	LCD_RD = 1;
	LCD_CS = 1;
	LCD_RD = 0;
}

//LCD模块初始化
void LCD_Init(void)
{
	LCD_GPIO_Init(); /*GPIO初始化*/
	//lcd硬件复位
	LCD_RESET = 0;
  delay_ms(20);
  LCD_RESET = 1;
	delay_ms(20);	
	
  LCD_WR_CMD(0xae);        //关显示
	LCD_WR_CMD(0xa9);  	//a9       
	LCD_WR_CMD(0xc8);                   
	LCD_WR_CMD(0xa0);        //a0       
	LCD_WR_CMD(0xab);                   
	LCD_WR_CMD(0xa6);                   
	LCD_WR_CMD(0xa4);                   
	LCD_WR_CMD(0x4c);        //n-line   
	LCD_WR_CMD(0x00);        //0a       
	LCD_WR_CMD(0x38);        //frame    
	LCD_WR_CMD(0x08);                   
	LCD_WR_CMD(0x48);        //duty     
	LCD_WR_CMD(0x80);        //128   
	LCD_WR_CMD(0xb0);        
	LCD_WR_CMD(0x40);                   
	LCD_WR_CMD(0x00);                   
	LCD_WR_CMD(0x44);        //com0     
	LCD_WR_CMD(0x00);                   
	LCD_WR_CMD(0x52);        //bias 54  
	LCD_WR_CMD(0x25);         //27      
	LCD_WR_CMD(0x81);         //        
	LCD_WR_CMD(0x22);         //18      
	LCD_WR_CMD(0xa8);         //        
	
	LCD_WR_CMD(0x2c);
	delay_ms(200);
	LCD_WR_CMD(0x2e);
	delay_ms(200);
	LCD_WR_CMD(0x2f);
	delay_ms(200);
	
	LCD_WR_CMD(0x7B); 	//Enter Test Command Set 3
	LCD_WR_CMD(0x10); 	//Set Color Mode(0x11Black/White mode),0x10=Gray mode (default)
	LCD_WR_CMD(0x00); 	//Exit Test Command Set 3
	
	LCD_WR_CMD(0xaf);
}

//更新显存到LCD		 
void LCD_RefreshGram(void)
{
	u8 i,n;		
	for(i=0;i<16;i++)  
	{
		LCD_WR_CMD(0xb0+i); 
		LCD_WR_CMD(0x10);
		LCD_WR_CMD(0x00);
		for(n=0;n<128;n++)
		{
			LCD_WR_DATA(LCD_GRAM[i][n]);
			LCD_WR_DATA(LCD_GRAM[i][n]);
		}
	}
}

//清除显示缓存  
void LCD_ClearGram(void)
{
	u8 i,n;  
	for(i=0;i<16;i++)
	{
		for(n=0;n<128;n++)
		{
			LCD_GRAM[i][n]=0x00;  
		}
	}
}
//清除显示缓存  
void LCD_ClearGramLine(u8 line1,u8 line2)
{
	u8 i,n;  
	for(i=line1;i<line2;i++)
	{
		for(n=0;n<128;n++)
		{
			LCD_GRAM[i][n]=0x00;  
		}
	}
}

//以下函数均是将数据写入显示缓存中---------------
//画点 
//x,y 点坐标
//t:点状态 1填充 0清空
void LCD_DrawPoint(u8 x,u8 y,u8 t)
{
	u8 temp=0;
	if(x>127||y>127) return;//超出范围了
	temp=1<<(y%8);
	if(t) LCD_GRAM[y/8][x]|=temp;
	else LCD_GRAM[y/8][x]&=~temp;
}

//画线
void LCD_DrawLine(u16 sx,u16 sy,u16 ex,u16 ey)
{
	u16 t; 
	int xerr=0,yerr=0,delta_x,delta_y,distance; 
	int incx,incy,uRow,uCol; 
	delta_x=ex-sx; //计算坐标增量 
	delta_y=ey-sy; 
	uRow=sx; 
	uCol=sy; 
	if(delta_x>0)incx=1; //设置单步方向 
	else if(delta_x==0)incx=0;//垂直线 
	else {incx=-1;delta_x=-delta_x;} 
	if(delta_y>0)incy=1; 
	else if(delta_y==0)incy=0;//水平线 
	else{incy=-1;delta_y=-delta_y;} 
	if( delta_x>delta_y)distance=delta_x; //选取基本增量坐标轴 
	else distance=delta_y; 
	for(t=0;t<=distance+1;t++ )//画线输出 
	{  
		LCD_DrawPoint(uRow,uCol,1);//画点 
		xerr+=delta_x ; 
		yerr+=delta_y ; 
		if(xerr>distance) 
		{ 
			xerr-=distance; 
			uRow+=incx; 
		} 
		if(yerr>distance) 
		{ 
			yerr-=distance; 
			uCol+=incy; 
		} 
	}  
}    


//画矩形	  
void LCD_DrawRect(u16 sx,u16 sy,u16 width,u16 height)
{
	u16 ex = sx + width -1;
	u16 ey = sy + height -1;
	LCD_DrawLine(sx,sy,ex,sy);
	LCD_DrawLine(sx,sy,sx,ey);
	LCD_DrawLine(sx,ey,ex,ey);
	LCD_DrawLine(ex,sy,ex,ey);
}
//画圆
void LCD_DrawCircle(u16 x0,u16 y0,u8 r)
{
	int a,b;
	int di;
	a=0;b=r;	  
	di=3-(r<<1);             //判断下个点位置的标志
	while(a<=b)
	{
		LCD_DrawPoint(x0+b,y0-a,1);  //1
		LCD_DrawPoint(x0+a,y0-b,1);  //2
		LCD_DrawPoint(x0-a,y0-b,1);  //3
		LCD_DrawPoint(x0-b,y0-a,1);  //4
 		LCD_DrawPoint(x0-b,y0+a,1);  //5
		LCD_DrawPoint(x0-a,y0+b,1);  //6
 		LCD_DrawPoint(x0+a,y0+b,1);  //7
		LCD_DrawPoint(x0+b,y0+a,1);  //8   	         
		a++;
		//使用Bresenham算法画圆     
		if(di<0)di +=4*a+6;	  
		else
		{
			di+=10+4*(a-b);   
			b--;
		} 						    
	}
}

//显示一个字符
//x,y 点坐标
//mode:0,反白显示;1,正常显示
//size:选择字体 8、16
void LCD_ShowOneChar(u8 x,u8 y,u8 chr,u8 size,u8 mode)
{
	u8 temp,t,t1;
	u8 y0=y;
	u8 csize=16;
	u8* pdata=NULL;
	chr=chr-' ';//得到偏移后的值			
	
	if(chr > 94) return; //超出范围
	//确定字符点阵起始地址和数据个数
	if(size == 8) 
	{
		csize = 5;
		pdata = (u8*)ascii_table_5x8[chr]; //调用0805字体
	}
	else if(size == 16) 
	{
		csize = 16;
		pdata = (u8*)ascii_table_8x16[chr]; //调用1608字体
	}	
	else return;
	//显示字符
	for(t=0;t<csize;t++)
	{   
		temp=pdata[t];                       
		for(t1=0;t1<8;t1++)
		{
			if(temp&0x80)LCD_DrawPoint(x,y,mode);
			else LCD_DrawPoint(x,y,!mode);
			temp<<=1;
			y++;
			if((y-y0)==size)
			{
				y=y0;
				x++;
				break;
			}
		}  	 
	}	
}

//显示一串字符
void LCD_ShowStrChar(u8 x,u8 y,uc8* str,u8 size,u8 mode)
{
	u8 i=0;
	u8 xlen = 8;
	if(size == 8) xlen = 6; //实际为5列,空一列更美观
	else if(size == 16) xlen = 8;
	else return;
	while(str[i] != 0x00)
	{	
		if(x > 127) break; //超出范围了
		if((str[i] >= 0x20) && (str[i] <= 0x7f))
		{
			LCD_ShowOneChar(x,y,str[i],size,mode); //是可见字符
		}
		else
		{
			LCD_ShowOneChar(x,y,' ',size,mode);//非可见字符显示空格
		}
		x += xlen; //下一个位置
		i++; // 下一个字符
	}
}

//显示一个汉字
void LCD_ShowOneHz(u8 x,u8 y,uc8* ptr,u8 size,u8 mode)
{  							  
	u8 temp,t1,t;
	u16 num=0;
	u16 y0=y;
	uc8 *pdata=NULL; 
	u8 csize=(size/8+((size%8)?1:0))*size;		//得到字体一个字符对应点阵集所占的字节数	
 	
	//查找点阵数据
	if(size==16)
	{
		while(GB_1616[num].Index[0] > 0x80) 
		{
			if((*ptr==GB_1616[num].Index[0])&&(*(ptr+1)==GB_1616[num].Index[1]))	break;
				num++;
			if(num > (sizeof(GB_1616) / sizeof(FNT_GB16) - 1))	return; //搜索下标约束 
		}
		pdata = GB_1616[num].Msk;
	}
	else if(size==32)
	{
		while(GB_3232[num].Index[0] > 0x80) 
		{
			if((*ptr==GB_3232[num].Index[0])&&(*(ptr+1)==GB_3232[num].Index[1]))	break;
				num++;
			if(num > (sizeof(GB_3232) / sizeof(FNT_GB3211) - 1))	return; //搜索下标约束 
		}
		pdata= GB_3232[num].Msk;
	}
	else return;
	//显示
	for(t=0;t<csize;t++)
	{   
		temp=pdata[t];                       
		for(t1=0;t1<8;t1++)
		{
			if(temp&0x80)LCD_DrawPoint(x,y,mode);
			else LCD_DrawPoint(x,y,!mode);
			temp<<=1;
			y++;
			if((y-y0)==size)
			{
				y=y0;
				x++;
				break;
			}
		}  	 
	}		
} 

//显示一串汉字
void LCD_ShowStrHz(u8 x,u8 y,uc8* ptr,u8 size,u8 mode)
{
	uc8 *pcStr=ptr;

	while((*pcStr!=0)&&(*pcStr>0x80))//判断是汉字
	{       
		LCD_ShowOneHz(x,y,pcStr,size,mode);
		x+=size;
		pcStr+=2;
	}  
}

/************************************************
函数名称 : LCD_ShowAllString
功    能 : 自适应显示字符和汉字
参    数 : x,y,* ptr,size,mode
						x,y:显示坐标
						* ptr:显示内容
						size:显示尺寸 支持08*05和16*08字符,16*16和32*32汉字
						mode:显示模式,1-正常 0-反白
返 回 值 : 无
作    者 : andyLuo
*************************************************/
//显示所有字符和汉字	
void LCD_ShowAllString(u8 x,u8 y,uc8* ptr,u8 size,u8 mode)
{
	uc8 *pcStr = ptr;
	
	while(*pcStr != '\0')
	{       
		if(*pcStr > 0x7f)
		{
			LCD_ShowOneHz(x,y,pcStr,size,mode);
			pcStr += 2;
			x += size;
		}else
		{
			LCD_ShowOneChar(x,y,*pcStr,size,mode);
			pcStr++;
			x += size/2;				
		}
	}  
}
//画单色图标
void LCD_DrawIcon(u8 x,u8 y,uc8* icon,u8 mode)
{
	u16 xlen,ylen,csize;
	u16 y0=y,i,j;
	u8 temp;	
	
	if(icon != NULL)
	{
		xlen = icon[0];
		ylen = icon[1];
		csize=(ylen/8+((ylen%8)?1:0))*xlen+2;
	}
	for(i=2;i<csize;i++)
	{   
		temp = icon[i];
		for(j=0;j<8;j++)
		{			    
			if(temp&0x80) LCD_DrawPoint(x,y,mode);
			else LCD_DrawPoint(x,y,!mode);
			temp<<=1;
			y++;
			if((y-y0)==ylen)
			{
				y=y0;
				x++;
				break;
			}
		}  	 
	} 
}

void LCD_DrawLineX(u8 x,u8 y_start,u8 y_end,u8 mode)		 //画水平线
{
	u8 temp;
	if(x > 127 || y_start > 127 || y_end > 127) return;
	if(y_end < y_start)
	{
		temp = y_end;
		y_end = y_start;
		y_start = temp;
	}
	for(;y_start <= y_end;y_start++) LCD_DrawPoint(x,y_start,mode);	
}

void LCD_DrawLineY(u8 x_start,u8 x_end,u8 y,u8 mode)		//画垂直线
{
	u8 temp;
	if(x_start > 127 || x_end > 127 || y > 127) return;
	if(x_end < x_start)
	{
		temp = x_end;
		x_end = x_start;
		x_start = temp;
	}
	for(;x_start <= x_end;x_start++) LCD_DrawPoint(x_start,y,mode);	
}


void LCD_Fill(u8 x_start,u8 y_start,u8 x_end,u8 y_end,u8 mode)		//填充
{
	u8 i,j;
	u8 temp;
	if(x_start > 127 || y_start > 127 || x_end > 127 || y_end > 127) return;
	if(x_start > x_end)
	{
		temp = x_start;
		x_start = x_end;
		x_end = temp;
	}
	if(y_start > y_end)
	{
		temp = y_start;
		y_start = y_end;
		y_end = temp;
	}
	if(x_start == x_end && y_start == y_end) {LCD_DrawPoint(x_start,y_start,mode);return;}
	if(x_start == x_end) {LCD_DrawLineX(x_start,y_start,y_end,mode);return;} 
	if(y_start == y_end) {LCD_DrawLineY(x_start,x_end,y_start,mode);return;}
	for(i = 0;i <= (x_end - x_start);i++)
	{
		for(j = 0;j <= (y_end - y_start);j++)
		{
			LCD_DrawPoint(x_start + i,y_start + j,mode);
		}	
	}		
}



/**** Copyright (C)2019-2029 中科智博. All Rights Reserved.  **** END OF FILE ****/


The corresponding header file, h

/**
  ********************************  STM32F10x  *********************************
  * @文件名     : lcd.h
  * @作者       : Apana
  * @库版本     : V3.5.0
  * @文件版本   : V1.0.0
  * @日期       : 2020-08-17
  * @摘要       : lcd驱动库头文件
  ******************************************************************************/

/* 定义防止递归包含 ----------------------------------------------------------*/
#include "sys.h"

#ifndef __LCD_H_
#define __LCD_H_

/* 定义引脚 ------------------------------------------------------------------*/
#define LCD_RD 				PBout(13)	//LCD读信号
#define LCD_WR 				PCout(11)	//LCD写信号
#define LCD_RS 				PCout(10)	//LCD指令数据控制信号
#define LCD_RESET 		PCout(9)	//LCD复位信号
#define LCD_CS 				PCout(8)	//LCD片选信号
#define LCD_BACK 			PAout(8)	//LCD背光控制
#define LCD_BACK_ON 	PAout(8)=1	//LCD背光开
#define LCD_BACK_OFF 	PAout(8)=0	//LCD背光关


void LCD_WRITE(u8 x);//LCD写
void LCD_RefreshGram(void); //更新显存到lcd
void LCD_ClearGram(void); //清除显存
void LCD_ClearGramLine(u8 line1,u8 line2);//清除显存
void LCD_Init(void); //LCD模块初始化
void LCD_DrawPoint(u8 x,u8 y,u8 t); //画点 
void LCD_DrawLine(u16 sx,u16 sy,u16 ex,u16 ey); //画线
void LCD_DrawRect(u16 sx,u16 sy,u16 width,u16 height); //画矩形	  
void LCD_DrawCircle(u16 x0,u16 y0,u8 r); //画圆
void LCD_ShowOneChar(u8 x,u8 y,u8 chr,u8 size,u8 mode); //显示一个字符
void LCD_ShowStrChar(u8 x,u8 y,uc8* str,u8 size,u8 mode); //显示一串字符
void LCD_ShowOneHz(u8 x,u8 y,uc8* ptr,u8 size,u8 mode); //显示一个汉字
void LCD_ShowStrHz(u8 x,u8 y,uc8* ptr,u8 size,u8 mode); //显示一串汉字
void LCD_ShowAllString(u8 x,u8 y,uc8* ptr,u8 size,u8 mode); //显示所有字符和汉字	
void LCD_DrawIcon(u8 x,u8 y,uc8* icon,u8 mode); //画单色图标
void LCD_Fill(u8 x_start,u8 y_start,u8 x_end,u8 y_end,u8 mode);		//填充

#endif

/**** Copyright (C)2019-2029 中科智博. All Rights Reserved.  **** END OF FILE ****/

Among them, #include "gbhz.h" contains the Chinese characters I obtained with the modulo software

(It can not only display Chinese characters, numbers, etc., but also display patterns)

#ifndef _GBHZ_H_
#define _GBHZ_H_

//结构体定义
typedef struct typFNT_GB16				// 汉字字模数据结构
{
	unsigned char Index[2];					// 汉字内码索引
	unsigned char Msk[32];					// 点阵码数据
}FNT_GB16;

typedef struct typeFNT_GB32
{                                                /* 汉字字模数据结构             */
  unsigned char Index[2];                       /* 汉字内码索引                 */
  unsigned char Msk[128];                        /* 点阵码数据                   */
}FNT_GB32;



// ------------------  汉字字模的数据结构定义 ------------------------ //
typedef struct typFNT_GB32                // 汉字字模数据结构
{
       unsigned char Index[2];              // 汉字内码索引
       unsigned char Msk[128];                      // 点阵码数据
}FNT_GB3211 ;

/
// 汉字字模表                                                          //
// Font:宋体32, 纵向取模上高位,数据排列:从上到下从左到右               //
/

const FNT_GB3211 GB_3232[] =        // 数据表
{

"院", 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
      0x00,0x00,0x00,0x00,0x1F,0xFF,0xFF,0xFE,
      0x0F,0xFF,0xFF,0xFC,0x08,0x00,0x00,0x00,
      0x08,0x00,0x00,0x00,0x08,0x18,0x04,0x00,
      0x08,0xE4,0x06,0x00,0x0F,0x83,0x06,0x04,
      0x1E,0x01,0xFC,0x04,0x08,0x00,0x78,0x04,
      0x00,0xC0,0x80,0x08,0x07,0xC0,0x80,0x10,
      0x02,0x08,0x80,0x30,0x02,0x08,0x80,0xE0,
      0x02,0x08,0x87,0xC0,0x02,0x08,0xFE,0x00,
      0x22,0x08,0x80,0x00,0x12,0x08,0x80,0x00,
      0x1E,0x08,0x80,0x00,0x0A,0x08,0xFF,0xF8,
      0x02,0x08,0xFF,0xFC,0x02,0x18,0x80,0x0C,
      0x02,0x18,0x80,0x04,0x02,0x48,0x80,0x04,
      0x03,0x81,0x80,0x04,0x07,0x01,0x80,0x0C,
      0x02,0x00,0x01,0xFC,0x00,0x00,0x00,0x08,
      0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
};

// 汉字表:
const FNT_GB16 GB_1616[] =				// 数据表
{
"同", 0x00,0x00,0x7F,0xFF,0x40,0x00,0x48,0x00,
      0x49,0xFC,0x49,0x08,0x49,0x08,0x49,0x08,
      0x49,0x08,0x49,0x08,0x5B,0xFC,0x49,0x02,
      0x40,0x01,0xFF,0xFE,0x40,0x00,0x00,0x00,

"学", 0x02,0x20,0x0C,0x20,0x88,0x20,0x69,0x20,
      0x09,0x20,0x09,0x22,0x89,0x21,0x69,0x7E,
      0x09,0x60,0x09,0xA0,0x19,0x20,0x28,0x20,
      0xC8,0x20,0x0A,0x60,0x0C,0x20,0x00,0x00,

"们", 0x02,0x00,0x04,0x00,0x1F,0xFF,0xE0,0x00,
      0x00,0x00,0x1F,0xFF,0x40,0x00,0x20,0x00,
      0x10,0x00,0x20,0x00,0x20,0x00,0x20,0x02,
      0x20,0x01,0x7F,0xFE,0x20,0x00,0x00,0x00,

"好", 0x08,0x02,0x08,0x44,0x0F,0xA8,0xF8,0x10,
      0x08,0x28,0x0F,0xC6,0x01,0x00,0x41,0x00,
      0x41,0x02,0x41,0x01,0x47,0xFE,0x49,0x00,
      0x51,0x00,0x63,0x00,0x01,0x00,0x00,0x00,

"呀", 0x00,0x00,0x3F,0xF8,0x20,0x10,0x20,0x10,
      0x7F,0xF0,0x20,0x08,0x41,0x08,0x47,0x10,
      0x59,0x10,0x41,0x22,0x41,0x41,0x7F,0xFE,
      0xC1,0x00,0x43,0x00,0x01,0x00,0x00,0x00
			

			
};

This is the knowledge I have learned in my school training. Welcome to give advice!

Guess you like

Origin blog.csdn.net/qq_60043905/article/details/131873123