基于STM32的μC/GUI外置spi flash字库研究与实现
2015-05-10杨立身张安伟
杨立身,张安伟,王 磊,魏 兰
(河南理工大学 计算机科学与技术学院,河南 焦作 454000)
1 引 言
随着嵌入式系统应用与研究的不断深入,嵌入式产品越来越向着智能化、集成化、人性化发展,支持中文的图形化界面人机接口以其良好的用户体验和直观的视觉感受也越来越受到重视。图形用户界面μC/GUI以其小巧、高效、可裁剪度高等特点在工业控制、通讯、医学等相关的嵌入式领域应用也越来越广泛。μC/GUI默认只支持英文,不支持中文显示,通常兼容中文的做法就是将汉字字库文件通过编译写入到MCU内部存储空间,然而常用的汉字7千多,就常用的GB2312编码而言大小就为200k[1],这样做势必会增加开发的成本,浪费原本宝贵的MCU内部存储空间,从而限制程序本身的大小,对程序功能的完整性造成一定的影响。
文章针对字库文件与MCU内部存储之间的矛盾,利用SPI接口的高数据传输速率,研究了将汉字字库存储于外置spi flash芯片的实现方法,通过修改μC/GUI内核的调用函数实现μC/GUI对外置字库的成功调用和显示,这样既避免了字库文件对MCU存储空间的占用,同时也兼顾了从外置字库读取数据的速度。
2 系统软硬件平台及开发环境
μC/GUI是美国Micrium公司出品的一种针对嵌入式系统的图形支持软件[2],其最小系统只需很小的内存空间就可运行,节省嵌入式芯片内部有限的存储空间[3-4]。移植方面,由文献[5-7]可知μC/GUI移植重点在于对操作系统系统配置文件、LCD底层驱动等的修改,具体过程文章不再详述。
平台核心芯片选用的是STM32F103RBT6,自带20KSRAM、3个SPI接口、3个USART异步串行总线接口[8],同时实验板载有16Mbit的外部flash芯片,型号为W25X16,通过SPI接口与MCU通信。液晶显示模块选用的是显尚光电的DST2001PH TFT-LCD,采用的控制器为ILI9320、26万色的 TFT-LCD屏[9-10]。编译环境采用 Keil uVision v4.10集成开发环境,实时操作系统采用uC/SO_II V2.86 版本,μC/GUI选用版本为V3.90a,硬件框图如图1所示。
图1 系统硬件框图Fig.1 System hardware structure
3 SPI_FLASH驱动程序设计
3.1 硬件连接
系统选用W25X16FLASH芯片存放外置字库,该芯片容量为16Mb,共分为32个块,每块又分为16个扇区,每个扇区4K字节。需要注意,W25X16的最少擦除单位为一个扇区,也就是说每次必须擦除4K个字节,所以需要给其开辟一个大小至少为4KB的缓存区。W25X16通过标准的SPI接口与STM32通信,最大的SPI时钟可以达到75Mhz。W25X16与STM32的系统硬件连线图如图2所示。
图2 系统连线图Fig.2 Connection diagram of system
3.2 STM32的SPI接口初始化
W25X16通过SPI接口与STM32通信,为了保证SPI接口正常工作,需要对SPI接口的工作模式、数据模式、数据大小、波特率等参数进行初始化配置。本文使用的为SPI1接口,相关初始化函数为SPI_Init(),寄存器配置代码如下:
SPI_Init()
{
……
SPI1->CR1|=0<<10;//工作模式为全双工
SPI1->CR1|=1<<9;//软件NSS管理
SPI1->CR1|=1<<2;//设置为SPI主设备
SPI1->CR1|=0<<11;//使用8位数据帧
SPI1->CR1|=0<<10;//空闲模式下SCK为高电平
SPI1->CR1|=7<<3;//波特率设置为256分频
SPI1->CR1|=0<<7;//先发送 MSB
SPI1->CR1|=1<<0;//第二个时钟沿开始数据采样
SPI1->CR1|=1<<6;//使能SPI1
}
3.3 读写FLASH函数
驱动设计部分需要为W25X16编写读写芯片状态寄存器函数,读flash函数,写flash页函数,芯片擦除函数和擦除扇区函数等,其中核心部分为读写flash函数和写flash页函数的编写,本文中这3个函数分别为 Flash_Read()、Flash_Write()和Flash_Write_Page(),功能分别为从指定地址读取指定长度的数据、向指定地址写入指定长度的数据以及向指定的flash地址中写入一页内容,其中Flash_Write_Page()是通过调用Flash_Write()函数从而将内容按页写进flash中的,程序执行流程图如图3所示。需要注意的是在调用写flash页函数时,所要写入的字节数不应超过每页的大小,即不应超过256字节。
4 μC/GUI汉字显示原理
4.1 μC/GUI字体类型
μC/GUI支持 ASCII、ISO8859-1、Unicode等编码方式,提供了4种有效字体:等宽字体(Monospacde Font)、均衡字体(Proportional Font)、内置2位光滑效果字体、内置4位光滑效果字体,后两种字体主要用在μC/GUI抗锯齿功能开启后,等宽字体的宽度和高度都是相同的,所以所有的点阵数据都存放在一个数组中。而对于均衡字体,由于每个字都有自己独自的宽度和高度,则需要通过定义单独的数组来实现每个字,对于既支持中文和英文的显示,一般选用的是均衡字体。本文主要针对等宽字体和均衡字体进行研究和分析。
图3 读写FLASH流程图Fig.3 Flow chart of reading and writing flash
4.2 字体数据结构
数据结构GUI_FONT同时记录了等宽字体、均衡字体的属性以及相关的驱动函数,该结构体定义了字体大小和GUI_FONT_PROP结构体的入口地址。等宽字体和均衡字体等宽字体对应的字模数据结构分别为GUI_FONT_MONO和GUI_FONT_PROP。与等宽字体不一样的是,均衡字体由于每个字都是单独的数组来表示,所以还需要另外一个结构来存储相应的字符信息,这个数据结构就是GUI_CHARINFO。GUI_FONT_PROP中包含了字母在字库中的编码和所对应的GUI_CHARINFO结构体入口地址,同时GUI_CHARINFO结构体pNext字段指针指向下一个GUI_FONT_PROP结构体,这样所有的结构体就形成了一个单项链表,解决了字模数据连续存储的问题。μC/GUI底层显示函数可以通过以上数据结构之间的关系找到所要显示字符的字模显示出来,整体的字库结构如图4所示。
4.3 μC/GUI汉字的显示
图4 字库结构图Fig.4 Organization chart of font library
μC/GUI显示字符一般以点阵方式显示,所谓点阵就是一个汉字用多少个像素点来描述。如一个16×16的点阵字符,即256个像素点来描述一个字符。此时用32个字节来表示此点阵字符,每行用两个字节记录这16个像素点的显示情况。显示汉字和显示字符原理一样,此时重点需要了解普通英文字符和汉字如何区别。一个ASCII字符占一个字节,编码从0到0XA1。对于GB2312编码的汉字来讲一个汉字占两个字节,且每个字节都是从0XA1开始,即汉字编码从0XA1A1开始[11-13]。μC/GUI显示字符时先分析得到待显示字符编码,判断字符为ASCII字母还是GB2312编码的汉字,然后利用GUI_FONT_DROP、GUI_FONT_MONO和GUI_CHARINFO从字库中取得字符的字模,然后调用GUICharP.c中的GUIPROP_DispChar()函数,最后调用μC/GUI底层的画位图函数LCD_DrawBitmap()函数,最后完成显示。
5 外置字库实现及测试
μC/GUI的字符显示函数一般是直接从内部程序存储器读取数据,将字库文件存储在外部flash后则需要在原始的显示代码中增加一个地址接口,使其指向外置flash,同时需要在GUI.h中声明,给μC/GUI的顺利调用指明方向。最后需要对GUICharP.c中显示字符的底层函数进行修改。
5.1 W25X16字库的写入
系统选用的字库为嵌入式系统中使用较多的GB2312编码字库,包含有6 768个简体中文。首先使能串口接收中断,利用PC取点阵软件,按照设定的点阵尺寸(本文为16×16)对字库文件中的汉字进行取模操作,得到对应的字模数组文件。然后利用PC串口调试软件将之前得到的字模数组文件按位发送至STM32的串口缓冲区,同时利用串口接收中断,每接收到1字节数据就通过中断处理函数中的Flash_Write_Page()函数写入到W25X16芯片中,需要注意的是在写入之前需要先对W25X16芯片进行擦除操作。字库写入流程如图5所示。串口中断处理函数USART1_IRQHan-dler()代码如下:
图5 字库写入流程图Fig.5 Flow chart of writing word stock
5.2 内核文件修改
添加外置字库后,需要在GUI.h文件中声明字库在flash中的首地址,以及相应的字库声明。内核文件修改主要集中在GUICharP.c文件的GUIPROP_DispChar()函数,这个函数为其他显示字符的函数所调用,文章增加了该函数对字符进行汉字和字母进行判断并分开处理的步骤,读取汉字信息时需要用到W25X16读取函数,即上述的Flash_Read()函数。同时在修改 GUIPROP_Disp-Char()函数时需要注意汉字和字母的判断方法,在GB2312编码时,汉字编码是从0XA1A1开始,在进行字节流解析时编码小于0XA1的认为是普通ASCII码,大于或者等于0XA1A1的则是汉字编码,汉字和字母的字模获取方式不同。文章中字母的模是直接在μC/GUI所给的C文件中获取,而汉字的模则是按照事先计算出的编译地址读取存放在外置flash中的字模,最后执行画位图函数LCD_DrawBitmap()将汉字及字符显示出来,流程图如图6所示。
图6 字符显示流程图Fig.6 Flow chart of character display
其中从μC/GUI和 W25X16取模的过程是这个文件修改的重点,需根据字符是字母还是汉字选择用不同的取模方式取模,部分实现代码如下:
base=(U32)pPROP->paCharInfo->pData;
//找出字库对应的首地址
BytesPerFont=GUI_Context.pAFont->YSize*pProp->paCharInfo->BytesPerLine;
//每个字模的数据字节数
if(BytePerFont>BYTES_PER_FONT)
{ BytesPerFont=BYTES_PER_FONT;}
if(c<0x80)//说明是ASCII编码字母
{for(i=0;i<16;i++)
{GUI_FontDataBuf[i]=acFont8x16[c-0x20][i]}}
else
{oft=base+ (((c> >8)-0xa1)*94+((c&0xff)-0xa1))*BytePerFont;
Flash_Read(oft,GUI_FontDataBuf,ByteP-erFont);}
5.3 外置字库平台测试
文章利用字库生成工具将常用汉字通过串口中断服务程序按照GB2312编码顺序存储到W25X16芯片中,之后在测试程序中调用GUI_DispStringAt()函数在液晶屏幕上显示“河南理工大学HPU”等字样,字符显示正常,说明外置字库顺利被调用。液晶显示效果如图7所示。
图7 液晶显示效果图Fig.7 LCD effect picture
6 结 论
通过将μC/GUI字库文件存储于外置spi flash中,在兼顾读取速度的同时解决了字库文件过大造成的对MCU存储空间浪费的问题,实验结果表明外置字库能被μC/GUI正常调用和显示,为嵌入式图形应用提供了一个价格低廉、同时支持中文显示的开发平台。下一步将考虑为常用汉字设置一个单独的缓冲区,从而进一步提高μC/GUI从外置flash中读取字库信息的速度,增强μC/GUI中文显示的能力。
[1] 黄健.基于 MiniGUI的 UCDOS字库接口实现[J].计算机工程,2011,37(1):273-279.Huang J.Implementation of UCDOS font interface based on MiniGUI[J].Computer Engineering,2011,37(1):273-279.(in Chinese)
[2] 葛欣,孟凡荣.使用μC/GUI开发图形用户界面[J].计算机工程与设计,2005,26(1):1-3.Ge X,Meng F R.UsingμC/GUI to develop graphical user interface [J].Computer Engineering and Design,2005,26(1):1-3.(in Chinese)
[3] 田志宏,徐军.嵌入式μC/GUI的移植与平台开发[J].自动化与仪表,2007(3):76-79.Tian Z H,Xu J.Transplant of embeddedμC/GUI and development of platform [J].Automation &Instrumentation,2007(3):76-79.(in Chinese)
[4] 刘滨,刘兵,赵艳华.基于μC/GUI的嵌入式图形界面设计[J].液晶与显示,2005,20(6):558-662.Liu B,Liu B,Zhao Y H.Embedded graphical interface design based onμC/GUI[J].Chinese Journal of Liquid Crystals and Displays,2005,20(6):558-662.(in Chinese)
[5] 吴燕燕,贺锋涛,孙林军.基于LPC214X平台的μC/GUI移植研究[J].液晶与显示,2012,27(3):338-341.Wu Y Y,He F T,Sun L J.Transferability ofμC/GUI on LPC214Xplatform [J].Chinese Journal of Liquid Crystals and Displays,2012,27(3):338-341.(in Chinese)
[6] 张兵,陈光.基于SOPC的μC/GUI移植开发[J].光电子技术,2012,32(3):195-199.Zhang B,Chen G.Transplant ofμC/GUI based on SOPC builder[J].Optoelectroinc Technology,2012,32(3):195-199.(in Chinese)
[7] 王海霞,武一.基于SOPC的LCD显示模块的设计[J].液晶与显示,2012,27(4):508-514.Wang H X,Wu Y.Design and implementation of LCD module based on SOPC [J].Chinese Journal of Liquid Crystals and Displays,2012,27(4):508-514.(in Chinese)
[8] 罗卫兵,胡健生.基于STM32+ucGUI的北斗导航定位系统设计[J].液晶与显示,2014,29(2):195-201.Luo W B,Hu J S.Design of Beidou navigation system based on STM32&ucGUI[J].Chinese Journal of Liquid Crystals and Displays,2014,29(2):195-201.(in Chinese)
[9] 童超,金庆辉,赵建龙.一种用于POCT的嵌入式实时图像采集处理系统[J].光学精密工程,2008,16(4):720-725.Tong C,Jin Q H,Zhao J L.Novel real time image collection system for point-of-care test[J].Optics and Precision Engineering,2008,16(4):720-725.(in Chinese)
[10] 王晓东,刘文耀,金月寒,等.基于DSP和CPLD的激光雷达图像采集和显示集成系统[J].光学精密工程,2004,12(2):190-194.Wang Y D,Liu W Y,Jin Y H,et al.Laser radar image acquisition and display integrated system based on DSP and CPLD [J].Optics and Precision Engineering,2004,12(2):190-194.(in Chinese)
[11] 覃爱娜,汪晓问,桂卫华.基于LCM 与字库芯片的中英文字符显示技术[J].信息技术,2012(8):28-32.Tan H N,Wang X W,Gui W H.Technology of displaying Chinese and western characters based on LCM and font chip[J].Information Technology,2012(8):28-32.(in Chinese)
[12] 冯月芹,汤小龙.高通字库芯片 GT23H32S4W 的应用[J].单片机与嵌入式系统应用,2013(12):45-47.Feng Y Q,Tang X L.Application of GT23H32S4WChinese character library chip[J].Microcontrollers & Embedded Systems,2013(12):45-47.(in Chinese)
[13] 宋玉贵,尹艳玲.基于LPC1788Emwin中文显示的设计与研究[J].工具技术,2013,47(7):24-26.Song Y G,Yin Y L.Design of displaying in Chinese based on LPC1788Emwin[J].Tool Engineering,2013,47(7):24-26.(in Chinese)