简单的记录一下使用HAL库的SPI外挂W25Q32
抽筋了,想记录一下。
-
cubeMX配置SPI
-
CS脚
-
spi.h 里添加
#define FLASH_ID 0XEF14 //指令表 #define W25X_WriteEnable 0x06 #define W25X_WriteDisable 0x04 #define W25X_ReadStatusReg 0x05 #define W25X_WriteStatusReg 0x01 #define W25X_ReadData 0x03 #define W25X_FastReadData 0x0B #define W25X_FastReadDual 0x3B #define W25X_PageProgram 0x02 #define W25X_BlockErase 0xD8 #define W25X_SectorErase 0x20 #define W25X_ChipErase 0xC7 #define W25X_PowerDown 0xB9 #define W25X_ReleasePowerDown 0xAB #define W25X_DeviceID 0xAB #define W25X_ManufactDeviceID 0x90 #define W25X_JedecDeviceID 0x9F
-
spi.c里添加
/* USER CODE BEGIN 1 */ #define SPI_FLASH_CS_H() HAL_GPIO_WritePin(GPIOE, GPIO_PIN_3, GPIO_PIN_SET) #define SPI_FLASH_CS_L() HAL_GPIO_WritePin(GPIOE, GPIO_PIN_3, GPIO_PIN_RESET) uint8_t SPI4_ReadByte(void) { uint8_t RxData; HAL_SPI_Receive(&hspi4, &RxData, 1, 20); return RxData; //返回通过SPIx最近接收的数据 } void SPI4_WriteByte(uint8_t TxData) { HAL_SPI_Transmit(&hspi4, &TxData, 1, 20); //通过外设SPIx发送一个数据 } //SPI_FLASH写使能 //将WEL置位 void SPI_FLASH_Write_Enable(void) { SPI_FLASH_CS_L(); //使能器件 SPI4_WriteByte(W25X_WriteEnable); //发送写使能 SPI_FLASH_CS_H(); //取消片选 } //SPI_FLASH写禁止 //将WEL清零 void SPI_FLASH_Write_Disable(void) { SPI_FLASH_CS_L(); //使能器件 SPI4_WriteByte(W25X_WriteDisable); //发送写禁止指令 SPI_FLASH_CS_H(); //取消片选 } //读取SPI_FLASH的状态寄存器 //BIT7 6 5 4 3 2 1 0 //SPR RV TB BP2 BP1 BP0 WEL BUSY //SPR:默认0,状态寄存器保护位,配合WP使用 //TB,BP2,BP1,BP0:FLASH区域写保护设置 //WEL:写使能锁定 //BUSY:忙标记位(1,忙;0,空闲) //默认:0x00 uint8_t SPI_Flash_ReadSR(void) { uint8_t byte=0; SPI_FLASH_CS_L(); //使能器件 SPI4_WriteByte(W25X_ReadStatusReg); //发送读取状态寄存器命令 byte = SPI4_ReadByte(); //读取一个字节 SPI_FLASH_CS_H(); //取消片选 return byte; } //等待空闲 void SPI_Flash_Wait_Busy(void) { while ((SPI_Flash_ReadSR()&0x01)==0x01); // 等待BUSY位清空 } //读取芯片ID W25X16的ID:0XEF14 uint16_t SPI_Flash_ReadID(void) { uint16_t Temp = 0; SPI_FLASH_CS_L(); SPI4_WriteByte(0x90);//发送读取ID命令 SPI4_WriteByte(0x00); SPI4_WriteByte(0x00); SPI4_WriteByte(0x00); Temp|=SPI4_ReadByte()<<8; Temp|=SPI4_ReadByte(); SPI_FLASH_CS_H(); return Temp; } //擦除整个芯片 //整片擦除时间: //W25X16:25s //W25X32:40s //W25X64:40s //等待时间超长... void SPI_Flash_Erase_Chip(void) { SPI_FLASH_Write_Enable(); //SET WEL SPI_Flash_Wait_Busy(); SPI_FLASH_CS_L(); //使能器件 SPI4_WriteByte(W25X_ChipErase); //发送片擦除命令 SPI_FLASH_CS_H(); //取消片选 SPI_Flash_Wait_Busy(); //等待芯片擦除结束 } //读取SPI FLASH //在指定地址开始读取指定长度的数据 //pBuffer:数据存储区 //ReadAddr:开始读取的地址(24bit) //NumByteToRead:要读取的字节数(最大65535) void SPI_Flash_Read(uint32_t ReadAddr,uint16_t NumByteToRead,uint8_t* pBuffer) { uint16_t i; SPI_FLASH_CS_L(); //使能器件 SPI4_WriteByte(W25X_ReadData); //发送读取命令 SPI4_WriteByte((uint8_t)((ReadAddr)>>16)); //发送24bit地址 SPI4_WriteByte((uint8_t)((ReadAddr)>>8)); SPI4_WriteByte((uint8_t)ReadAddr); for(i=0;i<NumByteToRead;i++) { pBuffer[i] = SPI4_ReadByte(); //循环读数 } SPI_FLASH_CS_H();//取消片选 } //SPI在一页(0~65535)内写入少于256个字节的数据 //在指定地址开始写入最大256字节的数据 //pBuffer:数据存储区 //WriteAddr:开始写入的地址(24bit) //NumByteToWrite:要写入的字节数(最大256),该数不应该超过该页的剩余字节数!!! void SPI_Flash_Write_Page(uint32_t WriteAddr,uint16_t NumByteToWrite,uint8_t* pBuffer) { uint16_t i; SPI_FLASH_Write_Enable(); //SET WEL SPI_FLASH_CS_L(); //使能器件 SPI4_WriteByte(W25X_PageProgram); //发送写页命令 SPI4_WriteByte((uint8_t)((WriteAddr)>>16)); //发送24bit地址 SPI4_WriteByte((uint8_t)((WriteAddr)>>8)); SPI4_WriteByte((uint8_t)WriteAddr); for(i=0;i<NumByteToWrite;i++) SPI4_WriteByte(pBuffer[i]);//循环写数 SPI_FLASH_CS_H(); //取消片选 SPI_Flash_Wait_Busy(); //等待写入结束 } /* USER CODE END 1 */
-
spi.h里添加调用函数
/* USER CODE BEGIN Prototypes */ uint16_t SPI_Flash_ReadID(void); void SPI_Flash_Erase_Chip(void); void SPI_Flash_Read(uint32_t ReadAddr,uint16_t NumByteToRead,uint8_t* pBuffer); void SPI_Flash_Write_Page(uint32_t WriteAddr,uint16_t NumByteToWrite,uint8_t* pBuffer); /* USER CODE END Prototypes */