欢迎光临
我们一直在努力

采用SPI Flash存储中文字符库(转)

平常在TFT屏上显示数量多的汉字步骤是先制作一个GB2312字库,将制作好的字库放在SD卡里,然后通过SD卡将字库文件复制到外部FLASH芯片W25Q16里,这样W25Q16就相当于一个汉字字库芯片了。但是这种方法需要外挂一个SD卡,当我们的板子上没有SD卡卡槽时,可以通过下面这种方法将字库文件写入外部FLASH中:  通过串口的方式将字库写入flash。

在嵌入式系统中,有时候需要中文字符来表示我们的某些信息,但是中文字符库本身占据空间比较大,因此有时候仅仅对系统中需要的字符进行编码,其它的则省掉,但是这样对于编程调用字符时是比较麻烦的,只能一个一个进行调用然户显示。然而,有时候在比较大的系统中需要很多的中文字符,如果还是对需要的进行一个个编码将显得非常费时,此时有必要采用一个字库来完成我们的工作。在嵌入式系统中,用得比较多的是GBK2312B编码的字库(还有一个是Unicode编码),编码后得到的是一个字符数组,每一个中文字符对应多个字节(具体字节数看取模的大小),需要显示某个字符只需取得该字符的GBK内码,然后找到该字符对应数组中的地址,最后将这个字符对应的所有字节按照预定的格式写入液晶屏即可。这样操作带来的简便就是,你想显示某个字符只需以字符串的格式输入该字符然后调用显示函数就行了。这时有个问题出现了,7千多个字符编码后得占用多大空间啊?大概有200KB,但是对于现在的MCU,本身自带的rom就很宝贵,另外MCU的ROM越大其成本就越高。所以,如果将200kb的字库写入MCU将不太划算。不将字库存入MCU,就得存入另外一种介质中,这种介质可能是SD卡,SPI Flash。对于SD卡我没有试过,虽然容量大,但据说读取速度比较慢,另外封装较大,占板子面积,感觉适用与大的系统吧,比如MP3;而SPI flash, 体积小,容量也还可以,我所了解的也有8M的,可能还有更大容量的。好了,废话了这么多,那么本文接下来就绍如何用SPI flash做中文字库:    第一步,当然需要你将你所用的SPIflasn的初始化以及读写函数写好(我使用的W25X16,2M,传输速率最大74MHZ,很快的;板子主芯片STM32F103RBT6)。写函数:voidW25X_Write_Bytes(uint32_t addr,u8* pBuffer, u16 nBytes) 注:W25X16写时,需要先擦除。读函数:voidW25X_Read_Bytes(uint32_t addr, u8* pBuffer, u16 nBytes)    第二步,编写串口传输函数,采用串口中断的方式,波特率设置为(测试没有问题),接收外部输入的一个字节后立马将其写入SPI FLASH。与之前两个字符表示一个字节的方法速度提升一倍。

u32 pAddr=0;

void USART1_IRQHandler(void)

if(USART_GetITStatus(USART1,USART_IT_RXNE)!=RESET)

result =USART_ReceiveData(USART1);

W25X_Write_Bytes(pAddr++,&result,1);

USART_ClearITPendingBit(USART1, USART_IT_RXNE);                   // 清除串口接受中断

第三步,设置一个按键进行擦除操作,通过串口或者LCD进行交互,以提示是否擦除完成。可以进行写FLASH。  也可以在main函数中初始化时使用芯片擦除函数进行擦除,最好可以设置一个动作提示擦除动作完成。

第四步,制作中文字库,GB3212库包含6768个简体中文,首先打开“取点阵.exe”软件,然后在软件中打开“字符库.txt”文件

然后选择取模方式,可以设置字体样式、大小和方向设置等。注意“方向设置“选项,这里为了对应工程中的显示程序,选择——横向取模,高位在坐。其它选项只要适当修改显示程序就可以。然后点击“输出“按钮,将在该目录下得到字模数组文件(temp.txt)。

第五步,整理字库文件。上一步得到的字模数组文件还不能直接使用,需要进行整理以适合串口发送,去除各种注释符和标点字符,只保留两位字符组成的十六进制格式。接着将“temp.txt”改名为“HzLib.txt”,然后运行“整理字库.exe”,此时将得到整理好的字库“OutHzLib.txt”然后就可以直接将该字库通过串口发送到MCU了,串口助手的波特率要和程序中设置的一致,同时勾选“启用文件数据源”和“按16进制发送”,程序中可以设置一个串口接收完成提醒来提示字库写入完成。

这里取模的大小为16*16,写入成功后就可以从外部Flash中取汉字来显示, 一个汉字占两个自己,在GB2312字库编码中第一个自己为“区码”,第二个字节为“位码”。想要显示汉字需要先找到这个汉字在字库中的位置, 对于16*16字库的汉字来说  偏移值 = (94 * (区码 - 0xb0) + (位码 - a1)) * 32

注解: 0xb0 0xa1是因为GB2312的第一个字体为”啊“,它的地址为0xb0a1;

94是指每个区有94个汉字     32是表示一个16*16的汉字占32个字节

/*******************************************************************************

* Function Name  : GetGBKCode

* Description    : 取GBK内码 数据

* Input          : - *c: 输入的GBK内码,如'我'

* Output         : - *pBuffer: 存放数据的指针

* Return         : None

* Attention : 输入一个GBK内码,取得它的32Byte显示代码并将其存放到一个32byte的显示缓冲pBuffer[]中

*******************************************************************************/

void GetGBKCode(unsigned char* pBuffer,unsigned char * c)

unsigned char High8bit,Low8bit;

High8bit=*c;

Low8bit=*(c+1);

GD25_FlashRead((94*(High8bit-0xb0)+(Low8bit-0xa0-1))*32, pBuffer,  32);

下面是在TFT屏上通过从FLASH中取字库的方式显示汉字,汉字大小为16*16

void PutChinese(uint16_t x,uint16_t y,uint8_t *str,uint16_t fcolor,uint16_t bkColor)

uint8_t i=0,j=0,t;

uint8_t buffer[32];

uint8_t ccd,x0;

GetGBKCode(buffer,str);  /* 取字模数据 */

赞(8)
分享到: 更多

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址