stm32【GT30L32S4W字库芯片】

GT30L32S4W字库芯片调试

测试平台:STM32F103RFT6
库版本:官方标准库3.5.0版本

字库芯片:GT30L32S4W
字库标准:GB2312国标汉字,ASCII字符
点阵排列方式:字节横置横排
字库套数:4套(12x12,16x16,24x24,32x32点阵)
驱动方式:SPI

在使用单片机+LCD屏幕进行显示控制时,文字显示是一个重要的内容,在比较小的屏幕使用中,例如0.96寸OLED的单色黑白屏幕等,通常是使用文字取模软件进行取模,然后存储在程序数组里,再拿去显示,当只显示一些特定的字符或文字时,这是一个不错的方式
但是当需要显示的字符比较多时,这种方法就不太适合了,这时候字库芯片的作用就体现出来了

这是高通的芯片,GT官网,在官网下载到这款芯片的数据手册,但是GT30L32S4W的数据手册的版本号是【V 1.0I_B 】,不知道是处于商业目的还是啥原因,这个版本的数据手册删除了关于编程指导的章节
GT30L32S4W (V1.0I_A)这是在百度文库找到的A版本,A版的第三章和第四章是B版本里缺少的,也是如何使用该芯片的关键内容,可惜下载不到这份数据手册,只能在线看了

注: 文中首次出现的代码块会标注[xxx.c]或[xxx.h],表明该代码是属于对应的文件,未标注的即为重复出现的

1、电路设计

电路设计方面没有啥讲究的,按照【datasheet_B版】里的来就行了,采用SPI通讯,注意不同封装对应的管脚不同就是了,这个SOP8封装

2、程序设计

2.1、SPI驱动

按照常规的SPI配置就行,注意时钟极性CPOL和时钟相位CPHA
【datasheet_B版】第2.2章节

数据在下降沿移出,实际测试中串行时钟稳态设置成高电平或低电平似乎都是可以的,这就有点迷惑了,或许是我的理解有问题

[spi.c]
	SPI_InitStructure.SPI_BaudRatePrescaler = speed;
	SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;						//数据捕获于第一个时钟沿
	SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;							//串行时钟稳态
	SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;					//每次收发数据大小
	SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;	//设置SPI单向/双向
	SPI_InitStructure.SPI_Mode = SPI_Mode_Master;						//设置SPI模式,主/从模式
	SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;					//指定数据传输从MSB位还是LSB位开始
	SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;							//NSS信号由硬件(NSS管脚)还是软件(使用SSI位)控制
	SPI_InitStructure.SPI_CRCPolynomial = 7;							//CRC值计算的多项式

由于是双向是通讯,需要一个SPI的读写函数▼

[spi.c]
u8 SPI2_ReadWriteByte(u8 data)
{
	u8 temp = 0;
	//等待发送数据寄存器清空,temp防止程序卡死
	while(!(SPI2->SR & SPI_I2S_FLAG_TXE)){
		temp++;
		if (temp > 200){return 0xFF;}
    }
	//发送数据
	SPI2->DR = data;
	temp = 0;
	
	//等待接收数据寄存器非空,temp防止程序卡死
	while(!(SPI2->SR & SPI_I2S_FLAG_RXNE)){
		temp++;
		if (temp > 200){return 0xFF;}
	}
	return SPI2->DR;
}

2.1、GT30L32S4W配置

芯片配置只有片选IO口配置+SPI

[GT30L32S4W.c]
/********************************************************************************
  * @brief  配置GT30L32S4W的SPI以及片选端口
  * @param  无
  * @retval 无
  *******************************************************************************/
void GT30L32S4W_Config(void)
{		
	GPIO_InitTypeDef GPIO_InitStructure;
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
	
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;	
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB, &GPIO_InitStructure);	

	GT_CS_1;
	
	//配置SPI2
	SPI2_Config(SPI_BaudRatePrescaler_2);
}

2.3、操作指令

从这里开始,编程就需要参考【datasheet_A版】了
第二章【指令操作】里提供了两种数据读取方式
【一般读取】
【快速读取点阵数据】

但是数据手册里的描述很迷惑,【一般读取】读取指定地址的数据后,如果片选CS不拉高,可以继续读取往后的地址上的数据,那么实际上和【快速读取点阵数据】实现是功能是一致的,而且使用【快速读取点阵数据】的话,前期需要发送5byte数据,【一般读取】则只需要发送4byte数据,详见datasheet
所以这里只介绍【一般读取】

看回上边2.2章节的【一般读取】的三个步骤
【1】片选置低 -> 发送0x03命令字+3字节地址(4byte)
【2】读取1byte数据
【3】片选置高,结束读取,片选保存,可以继续读取下一地址数据

由于【1】在各种规格的点阵读取里都会用到,这里单独编写一个发送字符地址函数▼

[GT30L32S4W.c]
/********************************************************************************
  * @brief  发送字符地址
  * @param  Address	地址
  * @retval none
  *******************************************************************************/
void GenitopZk_Address(u32 Address) 
{
	u8 AddH, AddM, AddL;
	
	AddH = Address >> 16;
	AddM = Address >> 8;
	AddL = Address;
	
	SPI2_ReadWriteByte(0x03);	//一般读取
	SPI2_ReadWriteByte(AddH);
	SPI2_ReadWriteByte(AddM);
	SPI2_ReadWriteByte(AddL);
	
//	SPI2_ReadWriteByte(0x0B);	//快速读取
//	SPI2_ReadWriteByte(AddH);
//	SPI2_ReadWriteByte(AddM);
//	SPI2_ReadWriteByte(AddL);
//	SPI2_ReadWriteByte(0xff);
}

2.4、ASCII字符获取

在字库芯片中,每一个文字或数字都存放在一个地址里边,需要找到这一个字符,就需要获取其首地址,通过上边的发送地址函数发送给字库芯片,再读取一定数量的点阵数据

【datasheet_A】里边的第三章给出了每套字库的起始地址▼

通过起始地址加上参考算法算出来的地址,就可以知道所需的字符的首地址

这里先对一些常用的基地址进行一个宏定义▼

[GT30L32S4W.c]
/************** GB2312字库字符基地址 *****************/
#define BaseAdd_12X12	0x00000
#define BaseAdd_16X16	0x2C9D0
#define BaseAdd_24X24	0x68190
#define BaseAdd_32X32	0xEDF00
/************** ASCII字符基地址 *****************/
#define ASCIIAdd_5X7	0x1DDF80
#define ASCIIAdd_7X8	0x1DE280
#define ASCIIAdd_6X12	0x1DBE00
#define ASCIIAdd_8X16	0x1DD780
#define ASCIIAdd_12X24	0x1DFF00
#define ASCIIAdd_16X32	0x1E5A50

在【datasheet_B】的第七章给出了8x16的字母“A”(横置横排)点阵数据▼

7 点阵数据验证(客户参考用) 
客户将芯片内“A”的数据调出与以下进行对比。若一致,表示 SPI 驱动正常工作;若不一致,请重 新编写驱动。 
 
排置:Y(竖置横排)点阵大小 8X16 字母"A"  点阵数据:00 E0 9C 82 9C E0 00 00 0F 00 00 00 00 00 0F 00  
 
排置:W(横置横排)点阵大小 8X16 字母"A"  点阵数据:00 10 28 28 28 44 44 7C 82 82 82 82 00 00 00 00 

那么先编写一个8x16点阵数据的看看数据是否能对应上▼

[GT30L32S4W.c]
/********************************************************************************
  * @brief  ASCII_8X16 ASCII字符读取
  * @param  *ASCIICode	ASCII字符码
  * @param  *BUF		缓存数组
  * @retval none
  *******************************************************************************/
void ASCII_8X16(char *ASCIICode, u8 *BUF)
{
	u8 i;
	u32 BaseAdd;
	u32 Address;
	
	BaseAdd = ASCIIAdd_8X16;
	
	if(*ASCIICode >= 0x20 && *ASCIICode <= 0x7E){
		Address = (*ASCIICode - 0x20) * 16 + BaseAdd;
	}

	GT_CS_0;

	GenitopZk_Address(Address);
	for(i = 0; i < 16 ; i++){
		BUF[i] = SPI2_ReadWriteByte(0xFF);
//		printf("%c", BUF[i]);
	}
	
	GT_CS_1;

}

Address就是字符的首地址,该算法是【datasheet_A】里给出的▼

Address = (*ASCIICode - 0x20) * 16 + BaseAdd;

这里的【16】是每两个字符之间的偏置地址
1bit的0/1对应一个像素点的灭/亮,8x16的点阵就需要【(8x16)/8bit = 16byte】的数据大小来存储,对于其他大小的点阵也是同理推算

计算出字符地址后,就可以发送出去,然后读取相应数量(这里是16byte)的数据,使用数组存储起来就可以了

在main函数写个数组传递进去即可检验该函数是否可行▼

[main.c]
	u8 BUF[16];
	ASCII_8X16("A", BUF);

通过仿真可以查看各个变量的数值▼

"A"实际上是把其对应的ASCII码(0x41)传递进去计算,仿真里可以看见指针【*ASCIICode】指向的值正是【0x41】
而且BUF数组能对应上参考数据▼

排置:W(横置横排)点阵大小 8X16 字母"A"  点阵数据:00 10 28 28 28 44 44 7C 82 82 82 82 00 00 00 00 

这就说明这个点阵读取函数是正确有效的,其他大小的ASCII点阵参考其写法就行

这里给一个16x32点阵的写法,可以看看如何改写,其中的【64】是根据上边给的公式算出来的▼

[GT30L32S4W.c]
/********************************************************************************
  * @brief  ASCII_16X32 ASCII字符读取
  * @param  *ASCIICode	ASCII字符码
  * @param  *BUF		缓存数组
  * @retval none
  *******************************************************************************/
void ASCII_16X32(char *ASCIICode, u8 *BUF)
{
	u8 i;
	u32 BaseAdd;
	u32 Address;
	
	BaseAdd = ASCIIAdd_16X32;
	
	if(*ASCIICode >= 0x20 && *ASCIICode <= 0x7E){
		Address = (*ASCIICode - 0x20) * 64 + BaseAdd;
	}

	GT_CS_0;

	GenitopZk_Address(Address);
	for(i = 0; i < 64 ; i++){
		BUF[i] = SPI2_ReadWriteByte(0xFF);
//		printf("%c", BUF[i]);
	}
	
	GT_CS_1;

}

2.5、GB2312字符获取

ASCII码有数字,字母,英文字符等对应编码号,对于中文,则是由汉字国标码(GB2312)来表示的,同样是把编码(汉字机内码)传递进去,再获取点阵数据即可

由于汉字数量众多,汉字的机器内码不再是1byte,而是2byte,内码高八位和低八位都需要判断
【datasheet_A】里给出12x12的算法如下▼

根据这个算法就可以编写函数▼

[GT30L32S4W.c]
/********************************************************************************
  * @brief  GB2312_12X12汉字字符读取
  * @param  *GBCode	汉字内码
  * @param  *BUF	缓存数组
  * @retval none
  *******************************************************************************/
void GB2312_12X12(char *GBCode, u8 *BUF)
{
	u8 i;
	u8 MSB;			//汉字内码高八位
	u8 LSB;			//汉字内码低八位
	u32 BaseAdd;	//字库基地址
	u32 Address;	//字符在芯片中的地址

	BaseAdd = BaseAdd_12X12;
	
	MSB = *GBCode;
	LSB = *(++GBCode);
	
	//计算字符地址值
	if(MSB >= 0xA1 && MSB <= 0xA9 && LSB >= 0xA1){
		Address = ((MSB - 0xA1) * 94 + (LSB - 0xA1)) * 24 + BaseAdd;
	}
	else if(MSB >= 0xB0 && MSB <= 0xF7 && LSB >= 0xA1){
		Address = ((MSB - 0xB0) * 94 + (LSB - 0xA1) + 846) * 24 + BaseAdd;
	}

	//获取字符点阵数据
	GT_CS_0;
	GenitopZk_Address(Address);
	for(i = 0; i < 24; i++){
		BUF[i] = SPI2_ReadWriteByte(0xff);
//		printf("%c", BUF[i]);
	}
	GT_CS_1;

}

这里最关键的是正确获取MSB和LSB的值,指针的操作要注意

还有就是【24】这个值
如果按照ASCII里边的计算是【(12x12) / 8bit = 18byte】
但这里并不是这样的,为了数据对齐,每两个字符之间的偏置地址是【(12x16) / 8bit = 24byte】

注意: 在ASCII码里也有这种数据对齐的现象
ASCII_5X7,实际地址偏置是【(8x8) / 8bit = 8byte】
ASCII_7X8,实际地址偏置是【(8x8) / 8bit = 8byte】
ASCII_6X12,实际地址偏置是【(6x16) / 8bit = 12byte】
因此在屏幕显示时框选的显示区域就得是对应的比例

算出地址之后的操作和ASCII是一样的

同样,在main函数测试下

[main.c]
	u8 BUF[24]
	GB2312_12X12("中", BUF);

这里需要了解下如何获取汉字机内码,一些【在线网站】可以输入文字查询机器内码
对于单片机,“中”通过编译器编译,就会编译成机器内码,大小2byte,可以仿真查看▼

在网站里查询的“中”字内码▼

可见内码是正确获取到了,至于BUF[24]里存储的数据是否正确,这里没法对比
可以自行手动对数据进行描点确认,注意点阵是【12x16】(宽度x高度)

其他大小的汉字点阵参考其写法就行,这里给一个32x32点阵的改写
其中的【128】是根据上边给的公式算出来的【(32x32) / 8bit = 128byte】▼

[GT30L32S4W.c]
/********************************************************************************
  * @brief  GB2312_32X32汉字字符读取
  * @param  *GBCode	汉字内码
  * @param  *BUF	缓存数组
  * @retval none
  *******************************************************************************/
void GB2312_32X32(char *GBCode, u8 *BUF)
{
	u8 i;
	u8 MSB;			//汉字内码高八位
	u8 LSB;			//汉字内码低八位
	u32 BaseAdd;	//字库基地址
	u32 Address;	//字符在芯片中的地址

	BaseAdd = BaseAdd_32X32;
	
	MSB = *GBCode;
	LSB = *(++GBCode);

	//计算字符地址值
	if(MSB >= 0xA1 && MSB <= 0xA9 && LSB >= 0xA1){
		Address = ((MSB - 0xA1) * 94 + (LSB - 0xA1)) * 128 + BaseAdd;
	}
	else if(MSB >= 0xB0 && MSB <= 0xF7 && LSB >= 0xA1){
		Address = ((MSB - 0xB0) * 94 + (LSB - 0xA1) + 846) * 128 + BaseAdd;
	}

	//获取字符点阵数据
	GT_CS_0;
	GenitopZk_Address(Address);
	for(i = 0; i < 128; i++){
		BUF[i] = SPI2_ReadWriteByte(0xff);
//		printf("%c", BUF[i]);
	}
	GT_CS_1;

}

3、总结

GT30L32S4W字库芯片调试大概就是这些了,关键点是:
【1】芯片内每套字库的基地址
【2】汉字机内码 / ASCII码
【3】每套字库的字符地址算法
【4】字库的点阵数据对齐
对于其他的字库芯片,这四点也是需要注意的
高通官方的数据手册不同版本内容大幅修改的问题不知道在其他型号的字库芯片上会不会是同样的情况,如果也是这样的话就得找找早期的版本了

这里分享一个结合LCD屏幕(240x240彩色)显示汉字的函数和调试照片【关于LCD屏幕见往期文章】

[gui.c]
/********************************************************************************
  * @brief  LCD显示32x32汉字字符
  * @param  *string 	汉字字符串
  * @param  (x,y)		显示位置
  * @param  color_1		字体主体颜色
  * @param  color_2		字体背景颜色
  * @retval none
  *******************************************************************************/
void LCD_Chinese_32X32(char *string, u32 x, u32 y, u16 f_color, u16 b_color)
{
	u32 i, j;
	
	u8 BUF[128];

	while(*string != 0){					//判断MSB
		GB2312_32X32(string, BUF);			//读取一个字符点阵数据
		LCD_SetRegion_Image(x, y, 32, 32);	//设定显示区域
		LCD_DC_1;
		for(i = 0; i < 128; i++){			//分解一帧点阵数据
			for(j = 0; j < 8; j++){			//1byte分解成8byte
				if(BUF[i] & 0x80){
					LCD_WR_Data16(f_color);
				}else{
					LCD_WR_Data16(b_color);
				}
				BUF[i] <<= 1;
			}
		}
		x += 32;
		string += 2;
	}
}

调试结果▼

  • 28
    点赞
  • 139
    收藏
    觉得还不错? 一键收藏
  • 20
    评论
### 回答1: 智晶30l32s4w是一款字库,它为用户提供了丰富多样的字体选择。这款字库适用于各种场合,包括办公文档、设计作品、广告宣传等等。它有着简洁清晰的外观,让文字更加易读和美观。 该字库拥有30个不同的字型,每个字型都有其独特的风格和特点,可以满足用户不同的需求和喜好。字体的风格包括了传统、现代、艺术等等,使得用户可以选择适合自己的字体风格。 此外,智晶30l32s4w字库还提供了32种不同的字号选择。用户可以根据需要的文字大小来选择合适的字号,以满足不同场合的需求。字号的选择范围广泛,从小号字体适用于细节显示,到大号字体适用于标题和重点突出,都可以轻松实现。 除了字型和字号的选择,智晶30l32s4w字库还提供了4种不同的字宽供用户使用。字宽的选择影响着文字的外观和版面的布局。用户可以根据需要的版面效果来选择合适的字宽,以达到理想的视觉效果。 总而言之,智晶30l32s4w字库是一款功能丰富的字库,提供了多样化的字型、字号和字宽供用户选择,并能满足不同场合的需求。无论是在办公、设计还是广告领域,都可以找到适合的文字风格,力求文字更加美观和易读。 ### 回答2: 智晶30l32s4w是一种字库说明书。这个字库说明书适用于智晶品牌的30l32s4w型号产品。该产品是一款智能显示屏,具有32英寸尺寸和4K分辨率。字库说明书提供了关于字库的详细信息和使用指南。 首先,字库说明书介绍了字库的作用和重要性。字库是一种包含各种字形和符号的数据库,可以用于显示文本内容。智晶30l32s4w字库包含了常见的汉字、英文字母、数字和特殊符号。这些字形和符号可以通过智晶品牌的30l32s4w型号产品显示出来。 接下来,字库说明书详细描述了如何使用该字库。用户可以通过显示屏的设置菜单来选择需要显示的字体和字形。同时,用户还可以通过连接电脑或USB设备来添加新的字库到30l32s4w字库中。字库说明书提供了详细的步骤和操作指南,帮助用户轻松使用和管理字库。 此外,字库说明书还包含了一些注意事项和常见问题解答。用户在使用30l32s4w字库时遇到问题时可以参考这些常见问题解答,快速找到解决方案。同时,字库说明书也提供了字库的更新方法和软件下载链接,保证字库始终是最新的版本。 总而言之,智晶30l32s4w字库说明书是一本详细的使用指南,针对该型号产品的字库提供了全面的介绍和操作指引。用户通过参考这个说明书,可以轻松地使用和管理30l32s4w字库,并享受到高质量的文字显示效果。
评论 20
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值