自己做了一块板子,FLASH(W25Qxx)都是空的,自己写了段简洁的代码用FAT从SD卡写到FLASH中。
有两种方式写入字库。一种把FAT系统做到FLASH里,第二种是直接写入FLASH后一段地址空间里。相比之下,我选择后者。为什么呢?FATFS太大了!你要是每次显示几个汉字就去移植,再去编译下载,那可真慢。。所以后者直接移植一个FLASH驱动就可以了。代码不多,用到什么写什么嘛,实现小功能就小代码呗。
下面贴代码了,大概讲一下
地址定义
//W25Q128! -> 总空间:16M
#define SPI_FONT_START 12 //从12M开始写入,其余是文件系统
#define FONT16x16_SPI_ADDR (SPI_FONT_START*1024/16 * 4096) //16x16字库
#define FONT16x16_SPI_SIZE 282752 //使用空间Byte
#define FONT16x16_SPI_TOTAL_SIZE (280*1024) //占用空间
#define FONT24x24_SPI_ADDR (FONT16x16_SPI_ADDR+FONT16x16_SPI_TOTAL_SIZE)
#define FONT24x24_SPI_SIZE 636192 //使用空间Byte
#define FONT24x24_SPI_TOTAL_SIZE (624*1024) //占用空间
#define FONT32x32_SPI_ADDR (FONT24x24_SPI_ADDR+FONT24x24_SPI_TOTAL_SIZE)
#define FONT32x32_SPI_SIZE 1131008 //使用空间Byte
#define FONT32x32_SPI_TOTAL_SIZE (1108*1024) //占用空间
特别注意一点,文件空间和占用空间不一样,和Window一样,一个扇区4KB,哪怕超了1bit也要占用一个扇区。
这里根据自己需要定义要存的位置。但是自己要计算好空间够不够。
实现代码
代码由于是我自己写的,所以我从简,我也挺烦一大串复杂冗余的代码。
u8 exchangeBuf[4096] __attribute__((at(0XC0000000)));
FRESULT f_res;
FIL fil;
UINT spi_btr;
//ph: 16x16字库文件路径 绝对路径!
void Update_SPI_FONT16x16(const TCHAR* ph)
{
u16 NumtoRead = 0;
u16 ByteCnt = 0;
u16 spi_offset = 0;
u16 Data_Reserve = 0;
f_res = f_open(&fil,ph,FA_OPEN_EXISTING|FA_READ);
NumtoRead = FONT16x16_SPI_TOTAL_SIZE/4096-1; //完整扇区读写
Data_Reserve = FONT16x16_SPI_SIZE -(FONT16x16_SPI_TOTAL_SIZE - 4096); //剩余扇区读写
if(f_res == FR_OK)
{
printf("\r\n打开文件成功");
printf("\r\n开始写入SPI FLASH");
while(NumtoRead != 0)
{
f_res = f_lseek(&fil,4096*spi_offset);
f_res = f_read(&fil,exchangeBuf,4096,&spi_btr);
if(f_res == FR_OK)
{
SPI_FLASH_BufferWrite(exchangeBuf,FONT16x16_SPI_ADDR+4096*spi_offset,4096);
ByteCnt+=4;
spi_offset++;
printf("\r\n已写入 %d 个字节",ByteCnt);
if(f_res == FR_OK)
NumtoRead--;
else
{
printf("\r\nSD卡文件偏移失败!!");
return;
}
}
else
{
printf("\r\n读取失败退出写入!!");
return;
}
}
f_res = f_read(&fil,exchangeBuf,Data_Reserve,&spi_btr); //剩余数据写入
if(f_res == FR_OK)
{
SPI_FLASH_BufferWrite(exchangeBuf,FONT16x16_SPI_ADDR+4096*spi_offset,Data_Reserve);
printf("\r\n已经完成SPI FLASH 16x16的读写!");
f_res = f_close(&fil);
if(f_res == FR_OK) printf("\r\n"),printf("\r\n成功完成读写过程!");
}
else
{
printf("\r\n写入数据不完整!!需要重新写入");
}
}
else
{
printf("\r\n打开文件失败");
}
}
我从SDRAM开了片4KB空间给缓冲区(因为FLASH一个扇区4KB)
什么?要SDRAM?
慢着!别走这是我图快。。不用SDRAM完全可以的。
你只要从STM32内存里分配256个也可以。只是需要多写几次罢了,记得地址每次要偏移256B!但是有SRAM/SDRAM的朋友就不会觉得那么麻烦了(也就是代码麻烦)。。
这是16x16的字库,文件比较小。对于24x24、32x32一样的代码,把宏改一下。
字库使用
对于没接触过字库文件的的确很懵,我也是总觉得那玩意前面有个文件头、信息头啥的,还要加偏移。。但是字库这玩意的确没有,按GBK编码寻址就行了,这里大概说一下,毕竟不是主题
u32 Get_GBK_OffSet_Addr(const u16 Hz)
{
u8 CodeH = 0,CodeL=0;
u32 Addr;
CodeH = (u8)(Hz >> 8);
CodeL = (u8)(Hz & 0x00FF);
Addr = (((CodeH - 0xA0 - 1)*94) + (CodeL-0xA0 - 1)) * (Font_Size * Font_Size / 8);
return Addr;
}
这是按GB2312的编码来的,0XA0就是ASCII最后一个码,其他算法没去具体了解。按这个计算公式
你要调用?
Get_GBK_OffSet_Addr('汉');
得到偏移地址代入SPIFLASH字库基地址就可以显示了
本人学习笔记,热爱分享
<完>