STM32外部SPI-FLASH字库实践

背景

使用STM32使用液晶屏时,对于一些点阵屏,预先需定义好相应的字模,对于12864的话,使用的自身的FLASH空间就可以存放下所需的字模,几十KB的空间。
如果使用大的点阵屏,或者点阵密度较大时,且使用到的字体较多,如果只是用STM32自身的FLASH,对于一些小空间的芯片就不太够有空间去存放字模了。
当前在使用的一块320x170的屏幕,用到的字体又有好几种,显示的内容就不少,对自身的FLASH空间不足于存放相应的字库,因此需要将字库存放于其他位置。
外部SPI-FLASH就是其中一种,也可以存放于NOR-FLASH,NAND-FLASH,EEPROM等,此文使用外部SPI-FLASH,W25Q128。

原理构图

这里罗列了大致的操作流程

  • FLASH字库数据烧录
  • MCU字库数据读取
  • MCU屏幕显示

各个环节的具体实际操作

烧录行为

外部SPI-FLASH,数据烧录方式

  1. 通过直接向芯片烧录,需要专门的芯片烧录工具,且在板上后无法修改
  2. 通过SWD烧录,只要保留SWD烧录口,就可以随时通过SWD更新SPI-FLASH内的数据
    此文使用STM32CubeProgrammer通过SWD接口向SPI-FLASH更新数据

字库制作

使用PCtoLCD2002完美版这个软件,当然用其他的软件也没有问题
字模选项的设置,软件内有说明,哪种方式都是可以的,只是选择了相应的设置,在显示数据的时候,驱动的代码需要做相应的适配
image
设置完字模选项,与字体后,可以通过软件的生成字库功能直接生成相应的字库,ASCII码字库与GB2312字库
image
生成所需的字库二进制文件后,可以将多个文件拼成一个文件,并记录所需每个文件的相对偏移量,这个偏移量在MCU读取SPI-FLASH字库的时候,是被需要的
拼接成的字库文件有几MB,对于STM32自身的FLASH就无法存放这么多的数据

索引      文件名                                   大小              偏移量
 1      E:\Font\ascii_16.bin                    0x00000800        0x00000000 
 2      E:\Font\ascii_24.bin                    0x00001800        0x00000800 
 3      E:\Font\ascii_32.bin                    0x00002000        0x00002000 
 4      E:\Font\ascii_48.bin                    0x00004800        0x00004000 
 5      E:\Font\ascii_64.bin                    0x00008000        0x00008800 
 6      E:\Font\gb2312_16.bin                   0x0003FE40        0x00010800 
 7      E:\Font\gb2312_24.bin                   0x0008FC10        0x00050640 
 8      E:\Font\gb2312_32.bin                   0x000FF900        0x000E0250 
 9      E:\Font\gb2312_48.bin                   0x0023F040        0x001DFB50 
 10     E:\Font\gb2312_64.bin                   0x003FE400        0x0041EB90 

字库内部偏移量计算

当找到每种字体的起始地址后,我们通过字符自身的编码去计算相应的单个字模数据存放地址
计算公式如下
GB2312编码

offsetAddr = ((CodeH - 0xA1) * 94 + (CodeL - 0xA1)) * FONT_HEIGHT * FONT_WIDTH / 8;

// 16 x 16 字体
offsetAddr = ((CodeH - 0xA1) * 94 + (CodeL - 0xA1)) * 16 * 16 / 8

那这个公式是如何得出来的呢,那就跟GB2312的编码相关
GB2312的编码的两个字节都是从0xA1到0xFE,总共是94的编码,这个就是上述的94的由来,
而字库生成的时候只根据存在的字符生成点阵字库,可以用计算公式得到对应的偏移量换算
GB2312默认包含的字符是从0xA1A1开始生成,默认的GB2312编码生成的字库,其中也包含了很多无用的空格,只是为了保证编码与计算公式的连续性。但我们使用到的中文可以从0xB0A1开始,如果为了减少字库的大小,可以考虑删除一些字,重新调整偏移计算公式也是可以的
image

ASCII编码的字库则不同,根据ASCII码的偏移计算地址
GB2312内也可以生成英文与数字,不过跟直接用英文生成的字库形状会不一样,英文生成的只占GB2312一半的点阵

STM32CUBEPROGRAMMER烧录数据

字库的生成后通SWD接口往外部SPI-FLASH中烧录数据
STM32CUBEPROGRAMMER,需要根据当前线路板的硬件进行调整来进行数据烧录,这个调整即所谓的烧录算法
适配当前硬件的烧录算法,也采用根据官方提供的例子进行修改,此文基于M25P64_STM3210E-EVAL进行修改
image
M25P64与W25Q128的驱动基本相似,只是W25Q128支持的操作命令更多,但使用M25Q64的命令也可以完成相应的读写操作
基于这个工程,只要重新配置SPI及FLASH的空间参数设定好,就可以用于STM32CubeProgrammer进行烧录
修改如下:
重新配置SPI

#define sFLASH_SPI_SCK_PIN               GPIO_Pin_3                  /* PA.03 */
#define sFLASH_SPI_SCK_GPIO_PORT         GPIOB                       /* GPIOB */
#define sFLASH_SPI_SCK_GPIO_CLK          RCC_APB2Periph_GPIOB
#define sFLASH_SPI_MISO_PIN              GPIO_Pin_4                  /* PA.04 */
#define sFLASH_SPI_MISO_GPIO_PORT        GPIOB                       /* GPIOB */
#define sFLASH_SPI_MISO_GPIO_CLK         RCC_APB2Periph_GPIOB
#define sFLASH_SPI_MOSI_PIN              GPIO_Pin_5                  /* PA.05 */
#define sFLASH_SPI_MOSI_GPIO_PORT        GPIOB                       /* GPIOB */
#define sFLASH_SPI_MOSI_GPIO_CLK         RCC_APB2Periph_GPIOB
#define sFLASH_CS_PIN                    GPIO_Pin_6                  /* PB.06 */
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
	GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE);
	GPIO_PinRemapConfig(GPIO_Remap_SPI1, ENABLE);

Dev_Inf.c

#if defined (__ICCARM__)
__root struct StorageInfo const StorageInfo  =  {
#else
struct StorageInfo const StorageInfo  =  {
#endif
   "W25Q128_STM32F103CB", 	 	 // Device Name + version number
   SPI_FLASH,                  					 // Device Type
   0x00000000,                						 // Device Start Address
   0x01000000,                 						 // Device Size in Bytes (16MBytes/128Mbits)
   0x00000100,                 						 // Programming Page Size 256Bytes
   0xFF,                       						 // Initial Content of Erased Memory
// Specify Size and Address of Sectors (view example below)
   0x00000100, 0x00010000,     				 // Sector Num : 256 ,Sector Size: 64KBytes 
   0x00000000, 0x00000000,
}; 

这样生成的W25Q128_STM32F103CB.stldr,这个烧录算法,就可以跟当前的硬件相适配。
从烧录算法的源文件中,并没有找到MAIN函数这样的程序入口,不知道SWD如果具体运行这样的算法,直接烧录程序到自身FLASH,也是通过这样的方式,暂时没有找到相关说明资料
算法生成后,将文件复制到STM32CubeProgrammer的目录下
C:\Program Files\STMicroelectronics\STM32Cube\STM32CubeProgrammer\bin\ExternalLoader
再打开STM32CubeProgrammer,就可以找到相应的算法选项
image
image
选择相应的二进制文件烧录数据即可,数据可以正常烧录,不过烧录的速度并不快。

实际效果

image

总结

可以实现外部SPI-FLASH的字库用于显示不同的字体,来节省空间
个别具体细节还不太了解,比如SWD具体是如何实现烧录算法的加载与操作,没有MAIN函数这样的入口,暂时没有找到相关的资料

参考资料

posted @ 2024-12-25 11:18  cau_par  阅读(76)  评论(0编辑  收藏  举报