银杏科技有限公司旗下技术文档发布平台 | |||
技术支持电话 | 0379-69926675-801 | ||
技术支持邮件 | Gingko@vip.163.com | ||
版本 | 日期 | 作者 | 修改内容 |
---|---|---|---|
V1.0 | 2019-02-25 | gingko | 初次建立 |
1.在主界面选择File–>New Project 或者直接点击ACCEE TO MCU SELECTOR。 2.出现芯片型号选择,搜索自己芯片的型号,双击型号,或者点击Start Project进入配置在搜索栏的下面,提供的各 种查找方式,可以选择芯片内核,型号,等等,可以帮助你查找芯片。本实验选取的芯片型号为:STM32H750IBKx。 3.配置RCC,使用外部时钟源。 4.时基源选择SysTick。 5.将PA10,PB7,PB8设置为GPIO_Output。 6.引脚模式配置。 7.设置串口。。 8.在NVIC Settings一栏使能接收中断。 9.配置QUADSPI。 10.时钟源设置,选择外部高速时钟源,配置为最大主频。 11.工程文件的设置, 这里就是工程的各种配置 我们只用到有限几个,其他的默认即可 IDE我们使用的是 MDK V5.27。 12.点击Code Generator,进行进一步配置。
int main(void) { int i; int temp; unsigned char write_buffer[4096]; unsigned char read_buffer[4096]; HAL_Init(); SystemClock_Config(); i2c.initialize(); axp152.initialize(); axp152.set_dcdc1(3500);//[ARM & FPGA BK1/2/6 &OTHER] axp152.set_dcdc2(1200);//[FPGA INT & PLL D] axp152.set_aldo1(2500);//[FPGA PLL A] axp152.set_dcdc4(3300);//[POWER_OUTPUT] axp152.set_dcdc3(3300);//[FPGA BK4][Adjustable] axp152.set_aldo2(3300);//[FPGA BK3][Adjustable] axp152.set_dldo1(3300);//[FPGA BK7][Adjustable] axp152.set_dldo2(3300);//[FPGA BK5][Adjustable] MX_GPIO_Init(); MX_USART2_UART_Init(); MX_QUADSPI_Init(); BSP_QSPI_Init(); usart2.initialize(115200); usart2.printf("\x0c"); //清屏 usart2.printf("\033[1;32;40m"); //设置终端字体为绿色 usart2.printf("Hello,I am iCore4T!\r\n\r\n"); temp = BSP_QSPI_FLASH_ReadID(); usart2.printf("FLASH ID: 0x%X\r\n",temp); for(i = 0;i < 4096;i ++){ write_buffer[i] = i % 256; read_buffer[i] = 0; } BSP_QSPI_Write(write_buffer,0,4096); //写数据 BSP_QSPI_Read(read_buffer,0,4096); //读数据 for(i = 0;i < 4096;i ++){ if(read_buffer[i] != write_buffer[i]){ usart2.printf("FLASH ERROR!\r\n"); while(1); } } usart2.printf("FLASH TEST OK!\r\n"); while (1) { } }
初始化好QSPI外设后,还要初始化初始化QSPI存储器,需要先复位存储器,使能写操作,配置状态寄存器才可进行数据读写操作。
uint8_t BSP_QSPI_Init(void) { QSPIHandle.Instance = QUADSPI; /* 调用DeInit函数重置驱动程序 */ if (HAL_QSPI_DeInit(&QSPIHandle) != HAL_OK) { return QSPI_ERROR; } /* 系统级初始化 */ BSP_QSPI_MspInit(&QSPIHandle, NULL); /* QSPI初始化 */ /* 时钟预分频器设置为1,因此QSPI时钟= 240MHz /(1 + 1)= 120MHz */ QSPIHandle.Init.ClockPrescaler = 1; QSPIHandle.Init.FifoThreshold = POSITION_VAL(W25Q64_FLASH_SIZE) - 1; QSPIHandle.Init.SampleShifting = QSPI_SAMPLE_SHIFTING_NONE; QSPIHandle.Init.FlashSize = POSITION_VAL(W25Q64_FLASH_SIZE) - 1; QSPIHandle.Init.ChipSelectHighTime = QSPI_CS_HIGH_TIME_6_CYCLE; QSPIHandle.Init.ClockMode = QSPI_CLOCK_MODE_0; QSPIHandle.Init.FlashID = QSPI_FLASH_ID_1; QSPIHandle.Init.DualFlash = QSPI_DUALFLASH_DISABLE; if (HAL_QSPI_Init(&QSPIHandle) != HAL_OK) { return QSPI_ERROR; } return QSPI_OK; }
要从存取器中读取数据,首先要用一个指针指向读回来的数据,并确定数据的首地址,数据大小,通过库函数HAL_QSPI_Command发送配置命令,然后调用库函数HAL_QSPI_Receive接收数据,最后等待操作完成,代码如下:
uint8_t BSP_QSPI_Read(uint8_t* pData, uint32_t ReadAddr, uint32_t Size) { QSPI_CommandTypeDef s_command; /* 初始化读取命令 */ s_command.InstructionMode = QSPI_INSTRUCTION_1_LINE; s_command.Instruction = QUAD_OUT_FAST_READ_CMD; s_command.AddressMode = QSPI_ADDRESS_1_LINE; s_command.AddressSize = QSPI_ADDRESS_24_BITS; s_command.Address = ReadAddr; s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; s_command.DataMode = QSPI_DATA_4_LINES; s_command.DummyCycles = W25Q64_DUMMY_CYCLES_READ_QUAD; s_command.NbData = Size; s_command.DdrMode = QSPI_DDR_MODE_DISABLE; s_command.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; s_command.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; /* 配置命令 */ if (HAL_QSPI_Command(&QSPIHandle, &s_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { return QSPI_ERROR; } /* 数据接收 */ if (HAL_QSPI_Receive(&QSPIHandle, pData, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { return QSPI_ERROR; } return QSPI_OK; }
pData:指向要读取的数据的指针 ReadAddr:读取起始地址 Size:要读取的数据大小
要从存取器中写入数据,首先要用一个指针指向写入的数据,并确定数据的首地址,数据大小,根据写入地址及大小判断存储器的页面,然后通过库函数HAL_QSPI_Command发送配置命令,再调用库函数HAL_QSPI_Transmit逐页写入数据,最后等待操作完成。代码如下:
uint8_t BSP_QSPI_Write(uint8_t* pData, uint32_t WriteAddr, uint32_t Size) { QSPI_CommandTypeDef s_command; uint32_t end_addr, current_size, current_addr; /* 计算写地址和页面末尾之间的大小 */ current_size = W25Q64_PAGE_SIZE - (WriteAddr % W25Q64_PAGE_SIZE); /* 检查数据大小是否小于页面中的剩余位置*/ if (current_size > Size) { current_size = Size; } /* 初始化地址变量 */ current_addr = WriteAddr; end_addr = WriteAddr + Size; /* 初始化程序命令 */ s_command.InstructionMode = QSPI_INSTRUCTION_1_LINE; s_command.Instruction = QUAD_IN_FAST_PROG_CMD; s_command.AddressMode = QSPI_ADDRESS_1_LINE; s_command.AddressSize = QSPI_ADDRESS_24_BITS; s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; s_command.DataMode = QSPI_DATA_4_LINES; s_command.DummyCycles = 0; s_command.DdrMode = QSPI_DDR_MODE_DISABLE; s_command.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; s_command.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; /* 逐页执行写入*/ do { s_command.Address = current_addr; s_command.NbData = current_size; /* 启用写操作 */ if (QSPI_WriteEnable(&QSPIHandle) != QSPI_OK) { return QSPI_ERROR; } /* 配置命令 */ if (HAL_QSPI_Command(&QSPIHandle, &s_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { return QSPI_ERROR; } /* 传输数据 */ if (HAL_QSPI_Transmit(&QSPIHandle, pData, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { return QSPI_ERROR; } /* 配置自动轮询模式以等待程序结束 */ if (QSPI_AutoPollingMemReady(&QSPIHandle, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != QSPI_OK) { return QSPI_ERROR; } /* 为下一页编程更新地址和变量大小 */ current_addr += current_size; pData += current_size; current_size = ((current_addr + W25Q64_PAGE_SIZE) > end_addr) ? (end_addr - current_addr) : W25Q64_PAGE_SIZE; } while (current_addr < end_addr); return QSPI_OK; }
pData:指向要写入的数据的指针 ReadAddr:写入起始地址 Size:要写入的数据大小
typedef struct { uint32_t Instruction; /* 设置通信指令,指定要发送到外部 SPI 设备的指令。仅可在 BUSY = 0 时修改该字段*/ uint32_t Address; /* 指定要发送到外部 Flash 的地址,BUSY = 0 或 FMODE = 11(内存映射模式)时,将忽略写入该字段。在双闪存模式下,由于地址始终为偶地址,ADDRESS[0] 自动保持为“0” */ uint32_t AlternateBytes; /* 指定要在地址后立即发送到外部 SPI 设备的可选数据,仅可在 BUSY = 0 时修改该字段。*/ uint32_t AddressSize; /* 定义地址长度,可以是8位,16位,24位或者32位 */ uint32_t AlternateBytesSize; /* 定义交替字节长度,可以是8位,16位,24位或者32位 */ uint32_t DummyCycles; /* 定义空指令阶段的持续时间,在 SDR 和 DDR 模式下,它指定 CLK 周期数 (0-31) */ uint32_t InstructionMode; /* 定义指令阶段的操作模式,00:无指令;01:单线传输指令;10:双线传输指令;11:四线传输指令*/ uint32_t AddressMode; /* 定义地址阶段的操作模式,00:无地址;01:单线传输地址;10:双线传输地址;11:四线传输地址*/ uint32_t AlternateByteMode; /* 定义交替字节阶段的操作模式00:无交替字节;01:单线传输交替字节;10:双线传输交替字节;11:四线传输交替字节 */ uint32_t DataMode; /* 定义数据阶段的操作模式,00:无数据;01:单线传输数据;10:双线传输数据;11:四线传输数据。该字段还定义空指令阶段的操作模式 */ uint32_t NbData; /* 设置数据长度,在间接模式和状态轮询模式下待检索的数据数量(值 + 1)。对状态轮询模式应使用不大于 3 的值(表示 4 字节)*/ uint32_t DdrMode; /* 为地址、交替字节和数据阶段设置 DDR 模式,0:禁止 DDR 模式;1:使能 DDR 模式 */ uint32_t DdrHoldHalfCycle; /* 设置DDR 模式下数据输出延迟 1/4 个 QUADSPI 输出时钟周期,0:使用模拟延迟来延迟数据输出;1:数据输出延迟 1/4 个 QUADSPI 输出时钟周期。仅在 DDR 模式下激活*/ uint32_t SIOOMode; /* 设置仅发送指令一次模式,IMODE = 00 时,该位不起作用。0:在每个事务中发送指令;1:仅为第一条命令发送指令 */ }QSPI_CommandTypeDef;