
本帖最后由 hpdell 于 2016-12-15 10:03 编辑 大侠们好,现在折腾 N25Q512 这个芯片,现在能够正常读取 芯片 ID 号了,而且也是正确的 芯片工作模式设置为 QUAD 与 4字节模式,读取标志寄存器查看是否设置成功,结果设置是正确的 读取到的芯片 ID 号: ![]() 资料介绍的 芯片ID 号: ![]() 读取到的id号与资料介绍的是完全一致的 现在就是读取数据错误,全部都为 0x88 ![]() 测试读数据前先把读取的一个扇区已经擦除了,再直接读取数据全部都为 0x88,正常来说应该是0xff才对 测试擦除一个扇区大概需要240ms左右,这个擦除时间应该算是正常的了,现在问题就出在数据读取上了 有哪位知道请指点指点几下啊 ????????!!!!! |
使用的硬件的 QSPI ,芯片是N25Q512A的,估计就是时钟频率与 Dummy
Clock Cycles 的周期没有搞对造成的,
再加上 芯片 N25Q512的资料也没有完全明白
static QSPI_StaticTypeDef QSPI_SendCmdData( uint8_t __Instruction, // 发送指令
uint32_t __InstructionMode, // 指令模式
uint32_t __AddressMode, // 地址模式
uint32_t __AddressSize, // 地址长度
uint32_t __DataMode, // 数据模式
uint32_t __NbData, // 数据读写字节数
uint32_t __DummyCycles, // 设置空指令周期数
uint32_t __Address, // 发送到的目的地址
uint8_t *_pBuf, // 待发送的数据
__SEND_CMD_DATA_T _SendCmdDat
)
{
QSPI_CommandTypeDef sCommand;
sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; //每次都发送指令
sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; //无交替字节
sCommand.DdrMode = QSPI_DDR_MODE_DISABLE; //关闭DDR模式
sCommand.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY;
sCommand.Instruction = __Instruction; //指令
sCommand.DummyCycles = __DummyCycles; //设置空指令周期数
sCommand.Address = __Address; //发送到的目的地址
// sCommand.NbData = __NbData; //这个地方不使用
sCommand.InstructionMode = __InstructionMode; //指令模式
sCommand.AddressMode = __AddressMode; //地址模式
sCommand.AddressSize = __AddressSize; //地址长度
sCommand.DataMode = __DataMode; //数据模式
if (HAL_QSPI_Command(&hqspi, &sCommand, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
{
return QSPI_ERROR;
}
if( _SendCmdDat == QSPI_SEND_DAT)
{
if(QSPI_Transmit( ( uint8_t * )_pBuf, __NbData) != QSPI_OK)
{
return QSPI_ERROR;
}
}
return QSPI_OK;
}
/**
* @brief This function configure the dummy cycles on memory side.
* @param hqspi: QSPI handle
* @retval None
*/
QSPI_StaticTypeDef QSPI_DummyCyclesCfg(QSPI_HandleTypeDef *hqspi)
{
QSPI_CommandTypeDef sCommand;
uint8_t reg;
if(W25QxxQpiMode) // qpi
{
sCommand.InstructionMode = QSPI_INSTRUCTION_4_LINES;
sCommand.DataMode = QSPI_DATA_4_LINES;
}
else
{
sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE;
sCommand.DataMode = QSPI_DATA_1_LINE;
}
/* Read Volatile Configuration register --------------------------- */
// sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE;
sCommand.Instruction = QSPI_READ_VOL_CFG_REG_CMD;
sCommand.AddressMode = QSPI_ADDRESS_NONE;
sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
// sCommand.DataMode = QSPI_DATA_1_LINE;
sCommand.DummyCycles = 0;
sCommand.DdrMode = QSPI_DDR_MODE_DISABLE;
sCommand.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY;
sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD;
sCommand.NbData = 1;
if (HAL_QSPI_Command( hqspi , &sCommand, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
{
return QSPI_ERROR;
}
if (HAL_QSPI_Receive( hqspi , ®, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
{
return QSPI_ERROR;
}
/* Enable write operations ---------------------------------------- */
QSPI_WriteEnable( hqspi );
/* Write Volatile Configuration register (with new dummy cycles) -- */
sCommand.Instruction = QSPI_WRITE_VOL_CFG_REG_CMD;
MODIFY_REG(reg, 0xF0, (10<< POSITION_VAL(0xF0)));
if (HAL_QSPI_Command(hqspi, &sCommand, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
{
return QSPI_ERROR;
}
if (HAL_QSPI_Transmit(hqspi, ®, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
{
return QSPI_ERROR;
}
return QSPI_OK;
}
QSPI_StaticTypeDef QSPI_ReadBuff(uint8_t* data, uint32_t address, uint32_t size)
{
uint8_t _RegVal = 0;
QSPI_DummyCyclesCfg(&hqspi);
//QPI,快速读数据,地址为ReadAddr,4线传输数据_32位地址_4线传输地址_4线传输指令,8空周期,NumByteToRead个数据
if(QSPI_SendCmdData( QSPI_QUAD_INOUT_FAST_READ_CMD /*QSPI_QUAD_INOUT_FAST_READ_CMD*/ /*QSPI_QUAD_INOUT_FAST_READ_CMD*/ , // _Instruction, 发送指令
QSPI_INSTRUCTION_4_LINES, // _InstructionMode, 指令模式
QSPI_ADDRESS_4_LINES, // _AddressMode, 地址模式
QSPI_ADDRESS_32_BITS, // _AddressSize, 地址长度
QSPI_DATA_4_LINES, // _DataMode, 数据模式
size, // _NbData, 数据读写字节数
10 , // _DummyCycles, 设置空指令周期数 与 QSPI_SET_READ_PARAM 这个指令设置的值一致
address, // _Address, 发送到的目的地址
&_RegVal, // *_pBuf, 待发送的数据
QSPI_SEND_CMD // __SEND_CMD_DATA_T _SendCmdDat
) != QSPI_OK )
{
return QSPI_ERROR;
}
if(QSPI_Receive( data, size) != QSPI_OK)
return QSPI_ERROR;
return QSPI_OK;
}
使用的硬件的 QSPI ,芯片是N25Q512A的,估计就是时钟频率与 Dummy
Clock Cycles 的周期没有搞对造成的,
再加上 芯片 N25Q512的资料也没有完全明白
static QSPI_StaticTypeDef QSPI_SendCmdData( uint8_t __Instruction, // 发送指令
uint32_t __InstructionMode, // 指令模式
uint32_t __AddressMode, // 地址模式
uint32_t __AddressSize, // 地址长度
uint32_t __DataMode, // 数据模式
uint32_t __NbData, // 数据读写字节数
uint32_t __DummyCycles, // 设置空指令周期数
uint32_t __Address, // 发送到的目的地址
uint8_t *_pBuf, // 待发送的数据
__SEND_CMD_DATA_T _SendCmdDat
)
{
QSPI_CommandTypeDef sCommand;
sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; //每次都发送指令
sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; //无交替字节
sCommand.DdrMode = QSPI_DDR_MODE_DISABLE; //关闭DDR模式
sCommand.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY;
sCommand.Instruction = __Instruction; //指令
sCommand.DummyCycles = __DummyCycles; //设置空指令周期数
sCommand.Address = __Address; //发送到的目的地址
// sCommand.NbData = __NbData; //这个地方不使用
sCommand.InstructionMode = __InstructionMode; //指令模式
sCommand.AddressMode = __AddressMode; //地址模式
sCommand.AddressSize = __AddressSize; //地址长度
sCommand.DataMode = __DataMode; //数据模式
if (HAL_QSPI_Command(&hqspi, &sCommand, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
{
return QSPI_ERROR;
}
if( _SendCmdDat == QSPI_SEND_DAT)
{
if(QSPI_Transmit( ( uint8_t * )_pBuf, __NbData) != QSPI_OK)
{
return QSPI_ERROR;
}
}
return QSPI_OK;
}
/**
* @brief This function configure the dummy cycles on memory side.
* @param hqspi: QSPI handle
* @retval None
*/
QSPI_StaticTypeDef QSPI_DummyCyclesCfg(QSPI_HandleTypeDef *hqspi)
{
QSPI_CommandTypeDef sCommand;
uint8_t reg;
if(W25QxxQpiMode) // qpi
{
sCommand.InstructionMode = QSPI_INSTRUCTION_4_LINES;
sCommand.DataMode = QSPI_DATA_4_LINES;
}
else
{
sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE;
sCommand.DataMode = QSPI_DATA_1_LINE;
}
/* Read Volatile Configuration register --------------------------- */
// sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE;
sCommand.Instruction = QSPI_READ_VOL_CFG_REG_CMD;
sCommand.AddressMode = QSPI_ADDRESS_NONE;
sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
// sCommand.DataMode = QSPI_DATA_1_LINE;
sCommand.DummyCycles = 0;
sCommand.DdrMode = QSPI_DDR_MODE_DISABLE;
sCommand.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY;
sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD;
sCommand.NbData = 1;
if (HAL_QSPI_Command( hqspi , &sCommand, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
{
return QSPI_ERROR;
}
if (HAL_QSPI_Receive( hqspi , ®, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
{
return QSPI_ERROR;
}
/* Enable write operations ---------------------------------------- */
QSPI_WriteEnable( hqspi );
/* Write Volatile Configuration register (with new dummy cycles) -- */
sCommand.Instruction = QSPI_WRITE_VOL_CFG_REG_CMD;
MODIFY_REG(reg, 0xF0, (10<< POSITION_VAL(0xF0)));
if (HAL_QSPI_Command(hqspi, &sCommand, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
{
return QSPI_ERROR;
}
if (HAL_QSPI_Transmit(hqspi, ®, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
{
return QSPI_ERROR;
}
return QSPI_OK;
}
QSPI_StaticTypeDef QSPI_ReadBuff(uint8_t* data, uint32_t address, uint32_t size)
{
uint8_t _RegVal = 0;
QSPI_DummyCyclesCfg(&hqspi);
//QPI,快速读数据,地址为ReadAddr,4线传输数据_32位地址_4线传输地址_4线传输指令,8空周期,NumByteToRead个数据
if(QSPI_SendCmdData( QSPI_QUAD_INOUT_FAST_READ_CMD /*QSPI_QUAD_INOUT_FAST_READ_CMD*/ /*QSPI_QUAD_INOUT_FAST_READ_CMD*/ , // _Instruction, 发送指令
QSPI_INSTRUCTION_4_LINES, // _InstructionMode, 指令模式
QSPI_ADDRESS_4_LINES, // _AddressMode, 地址模式
QSPI_ADDRESS_32_BITS, // _AddressSize, 地址长度
QSPI_DATA_4_LINES, // _DataMode, 数据模式
size, // _NbData, 数据读写字节数
10 , // _DummyCycles, 设置空指令周期数 与 QSPI_SET_READ_PARAM 这个指令设置的值一致
address, // _Address, 发送到的目的地址
&_RegVal, // *_pBuf, 待发送的数据
QSPI_SEND_CMD // __SEND_CMD_DATA_T _SendCmdDat
) != QSPI_OK )
{
return QSPI_ERROR;
}
if(QSPI_Receive( data, size) != QSPI_OK)
return QSPI_ERROR;
return QSPI_OK;
}
你好,我现在把 N25Q512的程序全部上传,包括进入 QUAD 及4字节模式
全部都在附近里面
另外说明一下如果是使用 quad 模式,读取id就是下面的指令
if(QSPI_Read_ID(QSPI_MULTIPLE_IO_READ_ID_CMD, (uint8_t *) & QspiReadID, 3) != QSPI_OK)
return QSPI_ERROR;
如果是spi模式, 需要吧 QSPI_MULTIPLE_IO_READ_ID_CMD 这个改成 QSPI_READ_ID_CMD 这个指令即可
1、资料介绍的 Dummy Clock
但是没有找到他们之间的对应关系具体该如何设置 ??
下面的这个图片对应的是 MX25L51245G 这个芯片的,别人的貌似写得的比较详细,一看就明白了
// 读写测试函数
void QSPI_ReadWriteDemo(void)
{
static uint8_t qspi_tx_buff[256], qspi_rx_buff[256];
uint32_t RWDataSize = 256;
// uint8_t * qspi_tx_buff = (uint8_t *)mymalloc(SRAMEX, RWDataSize );
// uint8_t * qspi_rx_buff = (uint8_t *)mymalloc(SRAMEX, RWDataSize );
uint8_t i = 0;
uint32_t cc = 0;
uint32_t QspiAddr_RW;
uint32_t TimeBegin, TimeEnd;
// if(( !qspi_tx_buff) || ( !qspi_rx_buff )) // 内存申请失败
// printf("QSPI SDRAM mymalloc Error ... ... \r\n");
for(cc=0;cc < ( RWDataSize );cc++)
{
qspi_tx_buff[cc] = i * 1 ;
qspi_rx_buff[cc] = 0 ;
i ++;
}
{
TimeBegin = HAL_GetTick();
if(QSPI_EraseSector(0) != QSPI_OK) //擦除这个扇区
return ;
TimeEnd = HAL_GetTick();
printf("QSPI QSPI Erase Sector ... ... %dms, %d\r\n" , TimeEnd - TimeBegin, cc); // 擦除一个扇区大概是240ms左右
}
QspiAddr_RW = (0 * 4096) + 0;
QSPI_ReadBuff( &qspi_rx_buff[0], (uint32_t)(QspiAddr_RW ), RWDataSize); // 擦除完成后就直接读取,但是读回来的数据全部都是 0x88 ???
TimeBegin = HAL_GetTick();
QSPI_WritePageByte( &qspi_tx_buff[0], (uint32_t)(QspiAddr_RW ), RWDataSize);
TimeEnd = HAL_GetTick();
printf("QSPI Write 8192 * 4 End ... ... %dms\r\n\r\n" , TimeEnd - TimeBegin);
TimeBegin = HAL_GetTick();
QSPI_ReadBuff( &qspi_rx_buff[0], (uint32_t)(QspiAddr_RW ), RWDataSize);
TimeEnd = HAL_GetTick();
printf("QSPI Read 8192 * 4 End ... ... %dms\r\n\r\n" , TimeEnd - TimeBegin);
if( Buffercmp_8(&qspi_tx_buff[0], &qspi_rx_buff[0], RWDataSize) == 0)
printf("QSPI Data Read Write 8192 * 4 Test OK ... DD \r\n\r\n");
else
printf("QSPI Data Read Write 8192 * 4 Test Error ... EE \r\n\r\n");
// myfree(SRAMEX, qspi_tx_buff);
// myfree(SRAMEX, qspi_rx_buff);
}
评分
查看全部评分
结果也还是一样的啊,
移植官网的 驱动 想测试一下,结果 程序死掉了,哎,
刚刚重新更换了一片 N25Q256A QSPI 芯片,结果神奇般的好了,怎么512的就不行,也不知道是不是512芯片搞到假货了【淘宝搞的,不过价格也不便宜啊,23大洋啊】
256的芯片一次读写32KByte 的数据也都没有问题
手册看了半天也没有看明白,跟256的手册对比看,貌似也都差不多啊
你好,在手册上也没有找到啊,同样的程序,在 N25Q256A qspi 的芯片上使用的挺好的,
你好,在手册上也没有找到有什么不同啊,另外我吧 官网提供的 HAL 移植过来也不行
评分
查看全部评分