应用程序
生成报告以及代码,编译程序。在quadspi.c文件中可以看到初始化函数。在stm32f7xx_hal_qspic.h头文件中可以看到QSPI的操作函数。分别对应轮询,中断和DMA三种控制方式。
下面为W25QXX的驱动文件。下载并添加进工程中。(操作方式参照第十一章)
stm32746g_qspi.zip
在main.c文件中添加头文件
| 1 | /* USER CODE BEGIN Includes */ |
| 3 | #include "stm32746g_qspi.h" |
| 4 | /* USER CODE END Includes */ |
声明变量: s_command为QSPI命令结构体,配置命令;pData存储读取ID值,rData,wData作为读写数据缓存
| 01 | /* USER CODE BEGIN PV */ |
| 02 | /* Private variables ---------------------------------------------------------*/ |
| 03 | QSPI_CommandTypeDef s_command; |
在main函数中添加应用程序,第一部分初始化W25Q128FV芯片,第二部分分别用单线,双线和四线三种模式读设备ID。第三部分则是读写擦除芯片操作实验。
| 001 | /* USER CODE BEGIN 2 */ |
| 002 | printf("W25Q128FV QuadSPI Test ....rnrn"); |
| 004 | /*##-1- Initialize W25Q128FV ###########################################*/ |
| 007 | /*##-2-Read Device ID Test ###########################################*/ |
| 008 | /* Read Manufacture/Device ID */ |
| 009 | s_command.InstructionMode = QSPI_INSTRUCTION_1_LINE; |
| 010 | s_command.Instruction = READ_ID_CMD; |
| 011 | s_command.AddressMode = QSPI_ADDRESS_1_LINE; |
| 012 | s_command.AddressSize = QSPI_ADDRESS_24_BITS; |
| 013 | s_command.Address = 0x000000; |
| 014 | s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; |
| 015 | s_command.DataMode = QSPI_DATA_1_LINE; |
| 016 | s_command.DummyCycles = 0; |
| 017 | s_command.NbData = 2; |
| 018 | s_command.DdrMode = QSPI_DDR_MODE_DISABLE; |
| 019 | s_command.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; |
| 020 | s_command.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; |
| 022 | if (HAL_QSPI_Command(&hqspi, &s_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) |
| 026 | if (HAL_QSPI_Receive(&hqspi, pData, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) |
| 030 | printf("SPI I/0 Read Device ID : 0x%2X 0x%2Xrn",pData[0],pData[1]); |
| 033 | /* Read Manufacture/Device ID Dual I/O*/ |
| 034 | s_command.InstructionMode = QSPI_INSTRUCTION_1_LINE; |
| 035 | s_command.Instruction = DUAL_READ_ID_CMD; |
| 036 | s_command.AddressMode = QSPI_ADDRESS_2_LINES; |
| 037 | s_command.AddressSize = QSPI_ADDRESS_24_BITS; |
| 038 | s_command.Address = 0x000000; |
| 039 | s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_2_LINES; |
| 040 | s_command.AlternateBytesSize= QSPI_ALTERNATE_BYTES_8_BITS; |
| 041 | s_command.AlternateBytes = 0; |
| 042 | s_command.DataMode = QSPI_DATA_2_LINES; |
| 043 | s_command.DummyCycles = 0; |
| 044 | s_command.NbData = 4; |
| 045 | s_command.DdrMode = QSPI_DDR_MODE_DISABLE; |
| 046 | s_command.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; |
| 047 | s_command.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; |
| 049 | if (HAL_QSPI_Command(&hqspi, &s_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) |
| 053 | if (HAL_QSPI_Receive(&hqspi, pData, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) |
| 057 | printf("Dual I/O Read Device ID : 0x%2X 0x%2Xrn",pData[0],pData[1]); |
| 059 | /* Read Manufacture/Device ID Quad I/O*/ |
| 060 | s_command.InstructionMode = QSPI_INSTRUCTION_1_LINE; |
| 061 | s_command.Instruction = QUAD_READ_ID_CMD; |
| 062 | s_command.AddressMode = QSPI_ADDRESS_4_LINES; |
| 063 | s_command.AddressSize = QSPI_ADDRESS_24_BITS; |
| 064 | s_command.Address = 0x000000; |
| 065 | s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_4_LINES; |
| 066 | s_command.AlternateBytesSize= QSPI_ALTERNATE_BYTES_8_BITS; |
| 067 | s_command.AlternateBytes = 0x00; |
| 068 | s_command.DataMode = QSPI_DATA_4_LINES; |
| 069 | s_command.DummyCycles = 4; |
| 070 | s_command.NbData = 2; |
| 071 | s_command.DdrMode = QSPI_DDR_MODE_DISABLE; |
| 072 | s_command.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; |
| 073 | s_command.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; |
| 075 | if (HAL_QSPI_Command(&hqspi, &s_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) |
| 079 | if (HAL_QSPI_Receive(&hqspi, pData, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) |
| 083 | printf("Quad I/O Read Device ID : 0x%2X 0x%2Xrn",pData[0],pData[1]); |
| 086 | s_command.InstructionMode = QSPI_INSTRUCTION_1_LINE; |
| 087 | s_command.Instruction = READ_JEDEC_ID_CMD; |
| 088 | s_command.AddressMode = QSPI_ADDRESS_NONE; |
| 089 | s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; |
| 090 | s_command.DataMode = QSPI_DATA_1_LINE; |
| 091 | s_command.DummyCycles = 0; |
| 092 | s_command.NbData = 3; |
| 093 | s_command.DdrMode = QSPI_DDR_MODE_DISABLE; |
| 094 | s_command.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; |
| 095 | s_command.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; |
| 097 | if (HAL_QSPI_Command(&hqspi, &s_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) |
| 101 | if (HAL_QSPI_Receive(&hqspi, pData, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) |
| 105 | printf("Read JEDEC ID : 0x%2X 0x%2X 0x%2Xrnrn",pData[0],pData[1],pData[2]); |
| 108 | /*##-3-QSPI Erase/Write/Read Test ###########################################*/ |
| 110 | for(i =0;i<0x100;i ++) |
| 116 | if(BSP_QSPI_Erase_Block(0) == QSPI_OK) |
| 117 | printf(" QSPI Erase Block okrn"); |
| 121 | if(BSP_QSPI_Write(wData,0x00,0x100)== QSPI_OK) |
| 122 | printf(" QSPI Write okrn"); |
| 126 | if(BSP_QSPI_Read(rData,0x00,0x100)== QSPI_OK) |
| 127 | printf(" QSPI Read okrnrn"); |
| 131 | printf("QSPI Read Data : rn"); |
| 132 | for(i =0;i<0x100;i++) |
| 133 | printf("0x%02X ",rData); |
| 136 | for(i =0;i<0x100;i++) |
| 137 | if(rData != wData)printf("0x%02X 0x%02X ",wData,rData); |
| 140 | if(memcmp(wData,rData,0x100) == 0 ) |
| 141 | printf(" W25Q128FV QuadSPI Test OKrn"); |
| 143 | printf(" W25Q128FV QuadSPI Test Falsern"); |
| 144 | /* USER CODE END 2 */ |
将W25QXX DataFlash Board模块插入到Open746I开发板I2C1中,编译程序并下载到开发板。打开串口调试助手。设置波特率为115200。串口助手上会显示如下信息。
五.程序讲解
现在以四线读设备ID为例讲解QSPI如何进行一次读写操作。如下为四线读制造商/设备ID命令(94H)
程序中先根据上面时序配置s_command命令结构体,
- 命令为1线,命令为QUAD_READ_ID_CMD,在w25q128fv.h头文件中宏定义为0x94。
- 地址为4线,地址长度为24位,地址为0x000000。
- 交替字节阶段设置为4线,长度为8位,备用字节为0x00。
- 空指令阶段为4个时钟周期
- 数据为4线,字节为两个字节。
程序中先通过HAL_QSPI_Command()将命令发送出去,然后通过HAL_QSPI_Receive()命令接收数据。即完成一次读操作,如果是写操作,同样是先配置命令结构体,然后发送命令,最后通过HAL_QSPI_Transmit()命令发送数据。
| 01 | /* Read Manufacture/Device ID Quad I/O*/ |
| 02 | s_command.InstructionMode = QSPI_INSTRUCTION_1_LINE; |
| 03 | s_command.Instruction = QUAD_READ_ID_CMD; |
| 04 | s_command.AddressMode = QSPI_ADDRESS_4_LINES; |
| 05 | s_command.AddressSize = QSPI_ADDRESS_24_BITS; |
| 06 | s_command.Address = 0x000000; |
| 07 | s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_4_LINES; |
| 08 | s_command.AlternateBytesSize= QSPI_ALTERNATE_BYTES_8_BITS; |
| 09 | s_command.AlternateBytes = 0x00; |
| 10 | s_command.DataMode = QSPI_DATA_4_LINES; |
| 11 | s_command.DummyCycles = 4; |
| 13 | s_command.DdrMode = QSPI_DDR_MODE_DISABLE; |
| 14 | s_command.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; |
| 15 | s_command.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; |
| 17 | if (HAL_QSPI_Command(&hqspi, &s_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) |
| 21 | if (HAL_QSPI_Receive(&hqspi, pData, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) |
| 25 | printf("Quad I/O Read Device ID : 0x%2X 0x%2Xrn",pData[0],pData[1]); |
应用程序
生成报告以及代码,编译程序。在quadspi.c文件中可以看到初始化函数。在stm32f7xx_hal_qspic.h头文件中可以看到QSPI的操作函数。分别对应轮询,中断和DMA三种控制方式。
下面为W25QXX的驱动文件。下载并添加进工程中。(操作方式参照第十一章)
stm32746g_qspi.zip
在main.c文件中添加头文件
| 1 | /* USER CODE BEGIN Includes */ |
| 3 | #include "stm32746g_qspi.h" |
| 4 | /* USER CODE END Includes */ |
声明变量: s_command为QSPI命令结构体,配置命令;pData存储读取ID值,rData,wData作为读写数据缓存
| 01 | /* USER CODE BEGIN PV */ |
| 02 | /* Private variables ---------------------------------------------------------*/ |
| 03 | QSPI_CommandTypeDef s_command; |
在main函数中添加应用程序,第一部分初始化W25Q128FV芯片,第二部分分别用单线,双线和四线三种模式读设备ID。第三部分则是读写擦除芯片操作实验。
| 001 | /* USER CODE BEGIN 2 */ |
| 002 | printf("W25Q128FV QuadSPI Test ....rnrn"); |
| 004 | /*##-1- Initialize W25Q128FV ###########################################*/ |
| 007 | /*##-2-Read Device ID Test ###########################################*/ |
| 008 | /* Read Manufacture/Device ID */ |
| 009 | s_command.InstructionMode = QSPI_INSTRUCTION_1_LINE; |
| 010 | s_command.Instruction = READ_ID_CMD; |
| 011 | s_command.AddressMode = QSPI_ADDRESS_1_LINE; |
| 012 | s_command.AddressSize = QSPI_ADDRESS_24_BITS; |
| 013 | s_command.Address = 0x000000; |
| 014 | s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; |
| 015 | s_command.DataMode = QSPI_DATA_1_LINE; |
| 016 | s_command.DummyCycles = 0; |
| 017 | s_command.NbData = 2; |
| 018 | s_command.DdrMode = QSPI_DDR_MODE_DISABLE; |
| 019 | s_command.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; |
| 020 | s_command.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; |
| 022 | if (HAL_QSPI_Command(&hqspi, &s_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) |
| 026 | if (HAL_QSPI_Receive(&hqspi, pData, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) |
| 030 | printf("SPI I/0 Read Device ID : 0x%2X 0x%2Xrn",pData[0],pData[1]); |
| 033 | /* Read Manufacture/Device ID Dual I/O*/ |
| 034 | s_command.InstructionMode = QSPI_INSTRUCTION_1_LINE; |
| 035 | s_command.Instruction = DUAL_READ_ID_CMD; |
| 036 | s_command.AddressMode = QSPI_ADDRESS_2_LINES; |
| 037 | s_command.AddressSize = QSPI_ADDRESS_24_BITS; |
| 038 | s_command.Address = 0x000000; |
| 039 | s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_2_LINES; |
| 040 | s_command.AlternateBytesSize= QSPI_ALTERNATE_BYTES_8_BITS; |
| 041 | s_command.AlternateBytes = 0; |
| 042 | s_command.DataMode = QSPI_DATA_2_LINES; |
| 043 | s_command.DummyCycles = 0; |
| 044 | s_command.NbData = 4; |
| 045 | s_command.DdrMode = QSPI_DDR_MODE_DISABLE; |
| 046 | s_command.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; |
| 047 | s_command.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; |
| 049 | if (HAL_QSPI_Command(&hqspi, &s_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) |
| 053 | if (HAL_QSPI_Receive(&hqspi, pData, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) |
| 057 | printf("Dual I/O Read Device ID : 0x%2X 0x%2Xrn",pData[0],pData[1]); |
| 059 | /* Read Manufacture/Device ID Quad I/O*/ |
| 060 | s_command.InstructionMode = QSPI_INSTRUCTION_1_LINE; |
| 061 | s_command.Instruction = QUAD_READ_ID_CMD; |
| 062 | s_command.AddressMode = QSPI_ADDRESS_4_LINES; |
| 063 | s_command.AddressSize = QSPI_ADDRESS_24_BITS; |
| 064 | s_command.Address = 0x000000; |
| 065 | s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_4_LINES; |
| 066 | s_command.AlternateBytesSize= QSPI_ALTERNATE_BYTES_8_BITS; |
| 067 | s_command.AlternateBytes = 0x00; |
| 068 | s_command.DataMode = QSPI_DATA_4_LINES; |
| 069 | s_command.DummyCycles = 4; |
| 070 | s_command.NbData = 2; |
| 071 | s_command.DdrMode = QSPI_DDR_MODE_DISABLE; |
| 072 | s_command.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; |
| 073 | s_command.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; |
| 075 | if (HAL_QSPI_Command(&hqspi, &s_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) |
| 079 | if (HAL_QSPI_Receive(&hqspi, pData, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) |
| 083 | printf("Quad I/O Read Device ID : 0x%2X 0x%2Xrn",pData[0],pData[1]); |
| 086 | s_command.InstructionMode = QSPI_INSTRUCTION_1_LINE; |
| 087 | s_command.Instruction = READ_JEDEC_ID_CMD; |
| 088 | s_command.AddressMode = QSPI_ADDRESS_NONE; |
| 089 | s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; |
| 090 | s_command.DataMode = QSPI_DATA_1_LINE; |
| 091 | s_command.DummyCycles = 0; |
| 092 | s_command.NbData = 3; |
| 093 | s_command.DdrMode = QSPI_DDR_MODE_DISABLE; |
| 094 | s_command.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; |
| 095 | s_command.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; |
| 097 | if (HAL_QSPI_Command(&hqspi, &s_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) |
| 101 | if (HAL_QSPI_Receive(&hqspi, pData, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) |
| 105 | printf("Read JEDEC ID : 0x%2X 0x%2X 0x%2Xrnrn",pData[0],pData[1],pData[2]); |
| 108 | /*##-3-QSPI Erase/Write/Read Test ###########################################*/ |
| 110 | for(i =0;i<0x100;i ++) |
| 116 | if(BSP_QSPI_Erase_Block(0) == QSPI_OK) |
| 117 | printf(" QSPI Erase Block okrn"); |
| 121 | if(BSP_QSPI_Write(wData,0x00,0x100)== QSPI_OK) |
| 122 | printf(" QSPI Write okrn"); |
| 126 | if(BSP_QSPI_Read(rData,0x00,0x100)== QSPI_OK) |
| 127 | printf(" QSPI Read okrnrn"); |
| 131 | printf("QSPI Read Data : rn"); |
| 132 | for(i =0;i<0x100;i++) |
| 133 | printf("0x%02X ",rData); |
| 136 | for(i =0;i<0x100;i++) |
| 137 | if(rData != wData)printf("0x%02X 0x%02X ",wData,rData); |
| 140 | if(memcmp(wData,rData,0x100) == 0 ) |
| 141 | printf(" W25Q128FV QuadSPI Test OKrn"); |
| 143 | printf(" W25Q128FV QuadSPI Test Falsern"); |
| 144 | /* USER CODE END 2 */ |
将W25QXX DataFlash Board模块插入到Open746I开发板I2C1中,编译程序并下载到开发板。打开串口调试助手。设置波特率为115200。串口助手上会显示如下信息。
五.程序讲解
现在以四线读设备ID为例讲解QSPI如何进行一次读写操作。如下为四线读制造商/设备ID命令(94H)
程序中先根据上面时序配置s_command命令结构体,
- 命令为1线,命令为QUAD_READ_ID_CMD,在w25q128fv.h头文件中宏定义为0x94。
- 地址为4线,地址长度为24位,地址为0x000000。
- 交替字节阶段设置为4线,长度为8位,备用字节为0x00。
- 空指令阶段为4个时钟周期
- 数据为4线,字节为两个字节。
程序中先通过HAL_QSPI_Command()将命令发送出去,然后通过HAL_QSPI_Receive()命令接收数据。即完成一次读操作,如果是写操作,同样是先配置命令结构体,然后发送命令,最后通过HAL_QSPI_Transmit()命令发送数据。
| 01 | /* Read Manufacture/Device ID Quad I/O*/ |
| 02 | s_command.InstructionMode = QSPI_INSTRUCTION_1_LINE; |
| 03 | s_command.Instruction = QUAD_READ_ID_CMD; |
| 04 | s_command.AddressMode = QSPI_ADDRESS_4_LINES; |
| 05 | s_command.AddressSize = QSPI_ADDRESS_24_BITS; |
| 06 | s_command.Address = 0x000000; |
| 07 | s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_4_LINES; |
| 08 | s_command.AlternateBytesSize= QSPI_ALTERNATE_BYTES_8_BITS; |
| 09 | s_command.AlternateBytes = 0x00; |
| 10 | s_command.DataMode = QSPI_DATA_4_LINES; |
| 11 | s_command.DummyCycles = 4; |
| 13 | s_command.DdrMode = QSPI_DDR_MODE_DISABLE; |
| 14 | s_command.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; |
| 15 | s_command.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; |
| 17 | if (HAL_QSPI_Command(&hqspi, &s_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) |
| 21 | if (HAL_QSPI_Receive(&hqspi, pData, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) |
| 25 | printf("Quad I/O Read Device ID : 0x%2X 0x%2Xrn",pData[0],pData[1]); |
举报