简单的记录一下使用HAL库的SPI外挂W25Q32

简单的记录一下使用HAL库的SPI外挂W25Q32

抽筋了,想记录一下。

  1. cubeMX配置SPI
    在这里插入图片描述

  2. CS脚
    在这里插入图片描述

  3. 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 
    
  4. 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 */
    
  5. 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 */
    
  • 1
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
下面是使用STM32F4 HAL库进行SPI读写W25Q32的示例代码: ```c #include "stm32f4xx_hal.h" #include <string.h> /* 定义SPI接口 */ SPI_HandleTypeDef hspi1; /* 定义W25Q32的命令码 */ #define W25Q32_CMD_WRITE_ENABLE 0x06 #define W25Q32_CMD_WRITE_DISABLE 0x04 #define W25Q32_CMD_READ_STATUS_REG1 0x05 #define W25Q32_CMD_READ_STATUS_REG2 0x35 #define W25Q32_CMD_READ_DATA 0x03 #define W25Q32_CMD_PAGE_PROGRAM 0x02 #define W25Q32_CMD_ERASE_SECTOR 0x20 #define W25Q32_CMD_ERASE_CHIP 0xC7 /* 定义W25Q32的状态寄存器 */ typedef struct { uint8_t busy:1; uint8_t write_enable_latch:1; uint8_t block_protection:3; uint8_t reserved:1; uint8_t page_size:2; } w25q32_status_reg1_t; /* 初始化SPI接口 */ void MX_SPI1_Init(void) { /* SPI1 parameter configuration */ hspi1.Instance = SPI1; hspi1.Init.Mode = SPI_MODE_MASTER; hspi1.Init.Direction = SPI_DIRECTION_2LINES; hspi1.Init.DataSize = SPI_DATASIZE_8BIT; hspi1.Init.CLKPolarity = SPI_POLARITY_LOW; hspi1.Init.CLKPhase = SPI_PHASE_1EDGE; hspi1.Init.NSS = SPI_NSS_SOFT; hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_256; hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB; hspi1.Init.TIMode = SPI_TIMODE_DISABLE; hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE; hspi1.Init.CRCPolynomial = 10; if (HAL_SPI_Init(&hspi1) != HAL_OK) { Error_Handler(); } } /* 读取W25Q32的状态寄存器1 */ void w25q32_read_status_reg1(w25q32_status_reg1_t *status_reg) { uint8_t cmd = W25Q32_CMD_READ_STATUS_REG1; uint8_t data[2]; HAL_GPIO_WritePin(SPI_CS_GPIO_Port, SPI_CS_Pin, GPIO_PIN_RESET); HAL_SPI_Transmit(&hspi1, &cmd, 1, HAL_MAX_DELAY); HAL_SPI_Receive(&hspi1, data, sizeof(data), HAL_MAX_DELAY); HAL_GPIO_WritePin(SPI_CS_GPIO_Port, SPI_CS_Pin, GPIO_PIN_SET); status_reg->busy = (data[0] & 0x01); status_reg->write_enable_latch = ((data[0] >> 1) & 0x01); status_reg->block_protection = ((data[0] >> 2) & 0x07); status_reg->reserved = ((data[0] >> 5) & 0x01); status_reg->page_size = ((data[1] >> 6) & 0x03); } /* 写入W25Q32的状态寄存器1 */ void w25q32_write_status_reg1(w25q32_status_reg1_t *status_reg) { uint8_t cmd = W25Q32_CMD_WRITE_ENABLE; HAL_GPIO_WritePin(SPI_CS_GPIO_Port, SPI_CS_Pin, GPIO_PIN_RESET); HAL_SPI_Transmit(&hspi1, &cmd, 1, HAL_MAX_DELAY); HAL_GPIO_WritePin(SPI_CS_GPIO_Port, SPI_CS_Pin, GPIO_PIN_SET); cmd = W25Q32_CMD_PAGE_PROGRAM; uint8_t data[2] = {0}; data[0] |= (status_reg->busy & 0x01); data[0] |= (status_reg->write_enable_latch & 0x01) << 1; data[0] |= (status_reg->block_protection & 0x07) << 2; data[0] |= (status_reg->reserved & 0x01) << 5; data[1] |= (status_reg->page_size & 0x03) << 6; HAL_GPIO_WritePin(SPI_CS_GPIO_Port, SPI_CS_Pin, GPIO_PIN_RESET); HAL_SPI_Transmit(&hspi1, &cmd, 1, HAL_MAX_DELAY); HAL_SPI_Transmit(&hspi1, data, sizeof(data), HAL_MAX_DELAY); HAL_GPIO_WritePin(SPI_CS_GPIO_Port, SPI_CS_Pin, GPIO_PIN_SET); } /* 写入W25Q32的一页数据 */ void w25q32_write_page(uint32_t addr, uint8_t *data, uint32_t len) { uint8_t cmd = W25Q32_CMD_WRITE_ENABLE; HAL_GPIO_WritePin(SPI_CS_GPIO_Port, SPI_CS_Pin, GPIO_PIN_RESET); HAL_SPI_Transmit(&hspi1, &cmd, 1, HAL_MAX_DELAY); HAL_GPIO_WritePin(SPI_CS_GPIO_Port, SPI_CS_Pin, GPIO_PIN_SET); cmd = W25Q32_CMD_PAGE_PROGRAM; uint8_t addr_buf[3]; addr_buf[0] = (addr >> 16) & 0xFF; addr_buf[1] = (addr >> 8) & 0xFF; addr_buf[2] = addr & 0xFF; HAL_GPIO_WritePin(SPI_CS_GPIO_Port, SPI_CS_Pin, GPIO_PIN_RESET); HAL_SPI_Transmit(&hspi1, &cmd, 1, HAL_MAX_DELAY); HAL_SPI_Transmit(&hspi1, addr_buf, sizeof(addr_buf), HAL_MAX_DELAY); HAL_SPI_Transmit(&hspi1, data, len, HAL_MAX_DELAY); HAL_GPIO_WritePin(SPI_CS_GPIO_Port, SPI_CS_Pin, GPIO_PIN_SET); } /* 读取W25Q32的一页数据 */ void w25q32_read_page(uint32_t addr, uint8_t *data, uint32_t len) { uint8_t cmd = W25Q32_CMD_READ_DATA; uint8_t addr_buf[3]; addr_buf[0] = (addr >> 16) & 0xFF; addr_buf[1] = (addr >> 8) & 0xFF; addr_buf[2] = addr & 0xFF; HAL_GPIO_WritePin(SPI_CS_GPIO_Port, SPI_CS_Pin, GPIO_PIN_RESET); HAL_SPI_Transmit(&hspi1, &cmd, 1, HAL_MAX_DELAY); HAL_SPI_Transmit(&hspi1, addr_buf, sizeof(addr_buf), HAL_MAX_DELAY); HAL_SPI_Receive(&hspi1, data, len, HAL_MAX_DELAY); HAL_GPIO_WritePin(SPI_CS_GPIO_Port, SPI_CS_Pin, GPIO_PIN_SET); } /* 擦除W25Q32的一个扇区 */ void w25q32_erase_sector(uint32_t addr) { uint8_t cmd = W25Q32_CMD_WRITE_ENABLE; HAL_GPIO_WritePin(SPI_CS_GPIO_Port, SPI_CS_Pin, GPIO_PIN_RESET); HAL_SPI_Transmit(&hspi1, &cmd, 1, HAL_MAX_DELAY); HAL_GPIO_WritePin(SPI_CS_GPIO_Port, SPI_CS_Pin, GPIO_PIN_SET); cmd = W25Q32_CMD_ERASE_SECTOR; uint8_t addr_buf[3]; addr_buf[0] = (addr >> 16) & 0xFF; addr_buf[1] = (addr >> 8) & 0xFF; addr_buf[2] = addr & 0xFF; HAL_GPIO_WritePin(SPI_CS_GPIO_Port, SPI_CS_Pin, GPIO_PIN_RESET); HAL_SPI_Transmit(&hspi1, &cmd, 1, HAL_MAX_DELAY); HAL_SPI_Transmit(&hspi1, addr_buf, sizeof(addr_buf), HAL_MAX_DELAY); HAL_GPIO_WritePin(SPI_CS_GPIO_Port, SPI_CS_Pin, GPIO_PIN_SET); } /* 擦除W25Q32的整个芯片 */ void w25q32_erase_chip(void) { uint8_t cmd = W25Q32_CMD_WRITE_ENABLE; HAL_GPIO_WritePin(SPI_CS_GPIO_Port, SPI_CS_Pin, GPIO_PIN_RESET); HAL_SPI_Transmit(&hspi1, &cmd, 1, HAL_MAX_DELAY); HAL_GPIO_WritePin(SPI_CS_GPIO_Port, SPI_CS_Pin, GPIO_PIN_SET); cmd = W25Q32_CMD_ERASE_CHIP; HAL_GPIO_WritePin(SPI_CS_GPIO_Port, SPI_CS_Pin, GPIO_PIN_RESET); HAL_SPI_Transmit(&hspi1, &cmd, 1, HAL_MAX_DELAY); HAL_GPIO_WritePin(SPI_CS_GPIO_Port, SPI_CS_Pin, GPIO_PIN_SET); } int main(void) { /* 初始化HAL库 */ HAL_Init(); /* 初始化SPI接口 */ MX_SPI1_Init(); /* 定义状态寄存器并读取 */ w25q32_status_reg1_t status_reg; w25q32_read_status_reg1(&status_reg); /* 写入一页数据 */ uint8_t data[256]; memset(data, 0xFF, sizeof(data)); w25q32_write_page(0x000000, data, sizeof(data)); /* 读取一页数据 */ uint8_t read_data[256]; w25q32_read_page(0x000000, read_data, sizeof(read_data)); /* 擦除一个扇区 */ w25q32_erase_sector(0x000000); /* 擦除整个芯片 */ w25q32_erase_chip(); while (1) { } } ``` 需要注意的是,上述代码中的W25Q32的命令码和状态寄存器的定义仅适用于W25Q32型号的Flash芯片,如果需要使用其他型号的Flash芯片,需要根据数据手册自行修改。同时,还需要根据实际硬件连接情况修改SPI接口的初始化代码。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值