STM32H743使用QSPI驱动W25Q128JV芯片(正点原子例程修改)

论坛 期权论坛 编程之家     
选择匿名的用户   2021-6-2 20:03   3052   0

当前项目中需要使用到STM32H743和外部SPI FLASH,在评估过程中使用的是正点原子的阿波罗开发板

但是好巧不巧的画原理图和制板的同事在选型的时候虽说保留了QSPI相同的借口,但是芯片改选了W25Q128,(可能是为了成本考虑),但是在实际调试过程中遇到了问题

仍旧使用原子哥的例程,但是写入数据后再读取会出现丢前3字节的情况。上网查了相关资料,发现W25Q256的4字节地址,128是3字节地址,则在w25qxx.c作了如下修改:

//QPI,写扇区擦除指令,地址为0,无数据_24位地址_4线传输地址_4线传输指令,无空周期,0个字节数据
QSPI_Send_CMD(W25X_SectorErase,Dst_Addr,0,QSPI_INSTRUCTION_4_LINES,QSPI_ADDRESS_4_LINES,QSPI_ADDRESS_24_BITS,QSPI_DATA_NONE);
   
//QPI,页写指令,地址为WriteAddr,4线传输数据_24位地址_4线传输地址_4线传输指令,无空周期,NumByteToWrite个数据 
QSPI_Send_CMD(W25X_QuadPageProgram,WriteAddr,0,QSPI_INSTRUCTION_4_LINES,QSPI_ADDRESS_4_LINES,QSPI_ADDRESS_24_BITS,QSPI_DATA_4_LINES); 

//QPI,快速读数据,地址为ReadAddr,4线传输数据_24位地址_4线传输地址_4线传输指令,8空周期,NumByteToRead个数据
QSPI_Send_CMD(W25X_FastReadQual,ReadAddr,8,QSPI_INSTRUCTION_4_LINES,QSPI_ADDRESS_4_LINES,QSPI_ADDRESS_24_BITS,QSPI_DATA_4_LINES); 
 
//SPI,读id,地址为0,单线传输数据_24位地址_单线传输地址_单线传输指令,无空周期,2个字节数据
QSPI_Send_CMD(W25X_ManufactDeviceID,0,0,QSPI_INSTRUCTION_1_LINE,QSPI_ADDRESS_1_LINE,QSPI_ADDRESS_24_BITS,QSPI_DATA_1_LINE);   
 

在所有需要配置地址长度的位置都要将 QSPI_ADDRESS_32_BITS -> QSPI_ADDRESS_24_BITS

但是还是无法正常工作,于是开始仔细看手册,这个地方我由于自己的疏忽,看错了手册,W25Q128FV和W25Q128JV的手册完全不同,

FV的手册内的指令与256有些相似,例如写入(Page Program (02h))指令,如下:

W25Q128FV和W25Q256的Page Program时序图
W25Q128FV和W25Q256的Page Program时序图

W25Q128FV和W25Q256有两种写入模式,均可以通过02h这条指令发送,1线和4线模式均可使用。

而W25Q128JV与他们的区别就是它的02h指令,仅支持1线模式,而如果想使用4线模式,需要使用Quad Input Page Program (32h)指令,时序图如下:

在时序图中可以看出来,就算是4线模式写入指令,指令和地址也都是单线发送,与W25Q128FV和W25Q256有区别,所以要修改程序:

//QPI,快速读数据,地址为ReadAddr,4线传输数据_24位地址_1线传输地址_1线传输指令,8空周期,NumByteToRead个数据
QSPI_Send_CMD(W25X_FastReadQual,ReadAddr,8,QSPI_INSTRUCTION_1_LINE,QSPI_ADDRESS_1_LINE,QSPI_ADDRESS_24_BITS,QSPI_DATA_4_LINES); 
 
//QPI,页写指令,地址为WriteAddr,4线传输数据_24位地址_1线传输地址_1线传输指令,无空周期,NumByteToWrite个数据
QSPI_Send_CMD(W25X_QuadPageProgram,WriteAddr,0,QSPI_INSTRUCTION_1_LINE,QSPI_ADDRESS_1_LINE,QSPI_ADDRESS_24_BITS,QSPI_DATA_4_LINES); 
 

所有相关的指令都要一一对着手册改好。

//读取W25QXX的状态寄存器,W25QXX一共有3个状态寄存器
u8 W25QXX_ReadSR(u8 regno)   
{  
 u8 byte=0,command=0; 
    switch(regno)
    {
        case 1:
            command=W25X_ReadStatusReg1;    //读状态寄存器1指令
            break;
        case 2:
            command=W25X_ReadStatusReg2;    //读状态寄存器2指令
            break;
        case 3:
            command=W25X_ReadStatusReg3;    //读状态寄存器3指令
            break;
        default:
            command=W25X_ReadStatusReg1;    
            break;
    }   
 QSPI_Send_CMD(command,0,0,QSPI_INSTRUCTION_1_LINE,QSPI_ADDRESS_NONE,QSPI_ADDRESS_8_BITS,QSPI_DATA_1_LINE);    //SPI,写command指令,地址为0,单线传数据_8位地址_无地址_单线传输指令,无空周期,1个字节数据
 QSPI_Receive(&byte,1);         
 return byte;   
}  

(这里并没有把所有需要修改的位置都列出来)

然后就没问题啦!!!!!

分享到 :
0 人收藏
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:3875789
帖子:775174
精华:0
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP