本帖最后由 suncat0504 于 2023-4-2 13:07 编辑
#申请原创#
开发板上预置了一片W25Q128Flash芯片,128MBit,可以通过标准/两线/四线SPI控制,W25Q128的资料:
W25Q128fv管脚如上,作为标准SPI控制时,DO管脚为MISO,D1管脚为MOSI,/CS为片选NSS,CLK为时钟信号线。/WP为写保护管脚,/HOLDor
/RESET为保持或复位引脚(通过寄存器配置)。
1、标准SPI指令
W25Q128JV通过SPI兼容总线访问,该总线由四个信号组成:串行时钟 (CLK)、片选(/CS)、串行数据输入(DI)和串行数据输出(DO)。标准SPI指令 使用DI输入引脚在的上升沿向器件串行写入指令、地址或数据 CLK。DO输出引脚用于在CLK的下降沿读取器件的数据或状态。 支持SPI总线工作模式0 (0,0)和3 (1,1)。模式0和之间的主要区别 模式3涉及SPI总线主机处于待机状态且数据 不被传输到串行闪存。对于模式0,CLK信号在下降时通常为低电平 /CS的上升沿。对于模式3,CLK信号通常在/CS的下降沿和上升沿为高电平。
2、双通道SPI指令
W25Q128JV在使用“快速读取双输出”等指令时支持双SPI操作 (3Bh)”和“快速读取双I/O (BBh)”。这些指令允许数据传入或传出 设备的速度是普通串行闪存设备的两到三倍。双通道SPI读取指令包括 非常适合上电时将代码快速下载到RAM(代码阴影)或直接从SPI总线执行非速度关键型代码(XIP)。使用双通道SPI指令时,DI和DO引脚 成为双向I/O引脚:IO0和IO1。
3、四通道SPI指令
W25Q128JV在使用“快速读取四通道输出”等指令时支持四通道SPI操作 (6Bh)”和“快速读取四通道I/O (EBh)”。这些指令允许数据传入或传出 设备的速度是普通串行闪存的四到六倍。使用四通道SPI指令时,DI和 DO引脚变成双向IO0和IO1,带有附加I/O引脚:IO2、IO3。
4、软件复位和硬件/复位引脚
W25Q128JV可以通过软件复位序列复位到初始上电状态。这个序列 必须包括两个连续的指令:启用复位(66h)和复位(99h)。如果指令序列 被成功接受,设备将需要大约30 S (tRST)来复位。没有指示会 在重置期间接受。对于SOIC-16和TFBGA套件,W25Q128JV提供 专用硬件/复位引脚。将/RESET引脚拉低至少约1 S (tRESET*)将 中断任何正在进行的外部/内部操作,并将器件复位到初始通电状态。 硬件/复位引脚的优先级高于其他SPI输入信号(/CS、CLK、IOs)
主板原理图中,与W25Q128芯片相关的部分:
W25Q128将16M的容量分为256个块(Block),每个块大小为64K字节,每个块又分为16个扇区(Sector),每个扇区4K个字节。W25Qxx的最小擦除单位为一个扇区,也就是每次必须擦除4K个字节。这样我们需要给W25Qxx开辟一个至少4K的缓存区,这样对
SRAM要求比较高,要求芯片必须有4K以上SRAM才能很好的操作。
在对W25Q128 FLASH的写入数据的操作中一定要先擦除扇区,再进行写入,否则将会发生数据错误。 W25Q128 FLASH一次性最大写入只有256个字节。
SWM341的例程库中提供了操作W25Q128的工程,\SPI\SPIFlash下,需要做以下修改:
1、去掉GD25Q21.c
2、导入FlashPrg.c
3、导入FlashDev.c
4、要保证引入SWM341_sfc.c
在主函数的初始化中加入代码:
SFC_Config(4);
这是为了配置SFC接口,使工程能够读写外置W25Q128芯片。
这样在程序中,执行SFC_Read和SFC_Write就能实现读写处理。函数原型:
/******************************************************************************************************************************************
* 函数名称: SFC_Write()
* 功能说明: SPI Flash数据写入
* 输 入: uint32_t addr 数据要写入到Flash中的地址,字对齐
* uint32_t buff[] 要写入Flash中的数据
* uint32_t cnt 要写的数据的个数,以字为单位,最大64
* 输 出: 无
* 注意事项: 要写入的数据必须全部在同一页内,即addr/256 == (addr+(cnt-1)*4)/256
******************************************************************************************************************************************/
void SFC_Write(uint32_t addr, uint32_t buff[], uint32_t cnt)
{
SFC->CFG |= (1 << SFC_CFG_WREN_Pos);
for(int i = 0; i < cnt; i++)
*((volatile unsigned int *)(0x70000000+addr+i*4)) = buff;
while(SFC->SR & SFC_SR_BUSY_Msk) __NOP();
SFC->CFG &= ~SFC_CFG_WREN_Msk;
}
/******************************************************************************************************************************************
* 函数名称: SFC_Read()
* 功能说明: SPI Flash数据读取
* 输 入: uint32_t addr 要读取的数据在Flash中的地址,字对齐
* uint32_t buff[] 读取到的数据存入buff指向的内存
* uint32_t cnt 要读取的数据的个数,以字为单位
* 输 出: 无
* 注意事项: 无
******************************************************************************************************************************************/
void SFC_Read(uint32_t addr, uint32_t buff[], uint32_t cnt)
{
for(int i = 0; i < cnt; i++)
buff = *((volatile unsigned int *)(0x70000000+addr+i*4));
}
参数中addr表示的是操作的开始地址,buff是读写用的缓冲区,声明的时候可以用uint8_t *,传递给读写函数的时候要强制转为(uint32_t *),这样的话,读写的总字节数需要除以4以后作为第三个参数使用。
下面是读写时序:
程序中使用四通道SPI指令操作Flash。W25Q128JV在使用“快速读取四通道输出”等指令时支持四通道SPI操作 (6Bh)”和“快速读取四通道I/O (EBh)”。这些指令允许数据传入或传出 设备的速度是普通串行闪存的四到六倍。使用四通道SPI指令时,DI和 DO引脚变成双向IO0和IO1,带有附加I/O引脚:IO2、IO3。
需要注意的是,在进行写操作之前,需要先进行擦除处理。不执行擦除处理,写操作会出错。
擦除处理可以以扇区方式操作,我实际测试时发现,每4096个单元形成一个扇区,每个扇区包含16页。对于我复制字库,可以这样搞:地址达到4096的整数倍时,执行扇区的擦除,然后开始一页一页从LCD自带的字库中取出点阵数据,写入Flash。
关于芯片的擦除:
目前有以下几种方式:
1、芯片整体擦除
执行EraseChip();,花费时间比较长
2、擦除扇区数据,指令20H
执行EraseSector(扇区地址开始位置的绝对物理地址);
3、擦除块,指令52H
SFC_EraseEx(
参数1:要擦除的块的绝对物理地址(当 addr == 0xFFFFFFFF 时,执行片擦),
参数2:擦除命令码(,不同块大小使用不同命令码) ,
参数3:等待 Flash 完成擦除操作)
程序中用到了1和2,但1相当花时间,大概需要几秒钟。所以我最后用方法2。
由于是作为字库使用,所以片外Flash是一次性擦除进而写入,成功以后只需要读,取出对应字符的点阵数据即可。
读取字库点阵信息处理中,我利用M9,M10、M15,D14作为接口,与LCD上自带的字库ROM连接。没有用SPI模式,是因为改造之做过的程序,这样改动量少。
// 字库 I2C LCD接口
#define Rom_IN PIN9 // 棕色 字库 IC 接口定义:Rom_IN 就是字库 IC 的 SI*/ M9
#define Rom_OUT PIN10 // 橙色 字库 IC 接口定义:Rom_OUT 就是字库 IC 的 SO*/ M10
#define Rom_SCK PIN15 // 蓝色 字库 IC 接口定义:Rom_SCK 就是字库 IC 的 SCK*/ M15
#define Rom_CS PIN14 // 绿色 字库 IC 接口定义 Rom_CS 就是字库 IC 的 CS#*/ D14
通过程序验证拷贝过来的字库,发现16位的ASCII字符好像有点问题,但汉字正常。已经达到可以使用的地步了。LCD自带的字库是包含了ASCII和汉字的,有16X16,16X24,24X24,32X32等点阵数据,使用方便。使用的是24位地址,相当于占用的空间为16M,刚好就是W25Q128的容量。
实际测试过程比较一言难尽,比较繁琐,只选一个片段截图演示:
可以看到,未使用LCD字库,只用Flash作为字库,能正常显示汉字。说明可以用外置Flash作为字库使用。
另外说一下,从LCD复制字库点阵数据到W25Q128,需要几个小时的时间。如果出去验证代码以及log输出调试代码,应该会节省些时间。
|