中国建设监督网站,表格网站怎么做,外贸出口工艺品怎么做外贸网站,网站建设运营岗位职责1、硬件电路 需要系统性的看一下W25Q256芯片手册 2、设置RCC#xff0c;选择高速外部时钟HSE,时钟设置为180MHz 3、配置SPI 4、生成工程配置 5、相关代码
#define sFLASH_ID 0XEF4019 // W25Q256#define SPI_FLASH_PageSize 256
#define SPI_FLASH_PerWritePageSize 256#def…1、硬件电路 需要系统性的看一下W25Q256芯片手册 2、设置RCC选择高速外部时钟HSE,时钟设置为180MHz 3、配置SPI 4、生成工程配置 5、相关代码
#define sFLASH_ID 0XEF4019 // W25Q256#define SPI_FLASH_PageSize 256
#define SPI_FLASH_PerWritePageSize 256#define W25Q256_WriteEnable 0x06 // 写使能指令
#define W25Q256_WriteDisable 0x04 // 写屏蔽指令
#define W25Q256_ReadStatusReg 0x05 // 读取状态寄存器1
#define W25Q256_WriteStatusReg 0x01 // 写入状态寄存器1
//#define W25Q256_ReadData 0x03 // 3字节模式读取数据指令
#define W25Q256_ReadData 0x13 // 4字节模式读取数据指令
#define W25Q256_FastReadData 0x0B //
#define W25Q256_FastReadDual 0x3B
#define W25Q256_PageProgram 0x02 // 页写入指令
#define W25Q256_BlockErase 0xD8
#define W25Q256_SectorErase 0x20
#define W25Q256_ChipErase 0xC7
#define W25Q256_PowerDown 0xB9
#define W25Q256_ReleasePowerDown 0xAB
#define W25Q256_DeviceID 0xAB
#define W25Q256_ManufactDeviceID 0x90
#define W25Q256_JedecDeviceID 0x9F
#define W25Q256_Enter4ByteMode 0xB7 // 4字节地址模式指令
#define W25Q256_ReadStatusRegister3 0x15
#define W25Q256_WriteStatusRegister3 0x11 //写状态寄存器3指令
#define WIP_Flag 0x01
#define Dummy_Byte 0xFF#define FLASH_WriteAddress 0x00000
#define FLASH_ReadAddress FLASH_WriteAddress
#define FLASH_SectorToErase FLASH_WriteAddress/* 获取缓冲区的长度 */
#define TxBufferSize1 (countof(TxBuffer1) - 1)
#define RxBufferSize1 (countof(TxBuffer1) - 1)
#define countof(a) (sizeof(a) / sizeof(*(a)))
#define BufferSize (countof(Tx_Buffer) - 1)#define FLASH_WriteAddress 0x00000
#define FLASH_ReadAddress FLASH_WriteAddress
#define FLASH_SectorToErase FLASH_WriteAddress/* 发送缓冲区初始化 */
extern uint8_t ReadBuff[4096];
extern uint8_t WriteBuff[4096]; /*** brief 拉低片选线* param 无* retval 无*/
void SPI_FLASH_NSS_LOW(void)
{HAL_GPIO_WritePin(SPI5_NSS_GPIO_Port, SPI5_NSS_Pin, GPIO_PIN_RESET);
}/*** brief 拉高片选线* param 无* retval 无*/
void SPI_FLASH_NSS_HIGH(void)
{HAL_GPIO_WritePin(SPI5_NSS_GPIO_Port, SPI5_NSS_Pin, GPIO_PIN_SET);
}/*** brief 获取 FLASH ID* param 无* retval FLASH ID*/
uint32_t SPI_FLASH_ReadID(void)
{uint32_t temp 0;uint32_t temp0 0;uint32_t temp1 0;uint32_t temp2 0;// 拉低片选线开始通信SPI_FLASH_NSS_LOW();// 发送获取W25Q256芯片ID指令SPI_FLASH_SendByte(W25Q256_JedecDeviceID);// 接收数据temp0 SPI_FLASH_ReadByte();temp1 SPI_FLASH_ReadByte();temp2 SPI_FLASH_ReadByte();// 拉高片选线结束通信SPI_FLASH_NSS_HIGH();temp temp0 16 | temp1 8 | temp2;return temp;
}/*** brief 发送一个字节* param 无* retval 无*/
void SPI_FLASH_SendByte(uint8_t ch)
{HAL_SPI_Transmit(hspi5, ch, 1, 500);
}/*** brief 发送n个字节* param pData发送数据首地址* param data_number发送数据个数以字节为单位* retval 无*/
void SPI_FLASH_SendnByte(uint8_t *pData, uint32_t data_number)
{HAL_SPI_Transmit(hspi5, pData, data_number, 500);
}/*** brief 接收一个字节* param 无* retval 接收的数据*/
uint8_t SPI_FLASH_ReadByte(void)
{uint8_t rxData 0;HAL_SPI_Receive(hspi5, rxData, 1, 500);return rxData;
}/*** brief 接收n个字节* param pData接收数据首地址* param data_number接收数据个数以字节为单位* retval 无*/
void SPI_FLASH_ReadnByte(uint8_t *pData, uint32_t data_number)
{HAL_SPI_Receive(hspi5, pData, data_number, 500);
}/*** brief 使能写命令* param 无* param 无* retval 无*/
void SPI_FLASH_WriteEnable(void)
{// 拉低片选线开始通信SPI_FLASH_NSS_LOW();// 发送写使能指令SPI_FLASH_SendByte(W25Q256_WriteEnable);// 拉高片选线结束通信SPI_FLASH_NSS_HIGH();
}/*** brief 等待写入、擦除等操作完成* param 无* param 无* retval 无*/
void SPI_FLASH_WaitForWriteEnd(void)
{uint8_t FLASH_Status 0;// 拉低片选线开始通信SPI_FLASH_NSS_LOW();// 发送写状态寄存器1指令SPI_FLASH_SendByte(W25Q256_ReadStatusReg);do{// 获取写状态寄存器1的值并做判断。0空闲、1忙碌FLASH_Status SPI_FLASH_ReadByte();} while (SET (FLASH_Status WIP_Flag));// 拉高片选线结束通信SPI_FLASH_NSS_HIGH();
}/*** brief 擦除扇区* param SectorAddr擦除扇区首地址* retval 无*/
void SPI_FLASH_SectorErase(uint32_t SectorAddr)
{// uint8_t ADDR[4] {0x00,0x00,0x00,0x00};// 使能写命令SPI_FLASH_WriteEnable();// 拉低片选线开始通信SPI_FLASH_NSS_LOW();// 发送擦除扇区命令SPI_FLASH_SendByte(W25Q256_SectorErase);// 发送擦除地址24 ~ 31bitSPI_FLASH_SendByte((SectorAddr 0xFF000000) 24);// 发送擦除地址16 ~ 23bitSPI_FLASH_SendByte((SectorAddr 0xFF0000) 16);// 发送擦除地址8 ~ 15bitSPI_FLASH_SendByte((SectorAddr 0xFF00) 8);// 发送擦除地址0 ~ 7bitSPI_FLASH_SendByte(SectorAddr 0xFF);// 拉高片选线结束通信SPI_FLASH_NSS_HIGH();// HAL_Delay(3000);// 等待擦除操作结束SPI_FLASH_WaitForOperaEnd();
}/*** brief 配置4字节模式* param 无* retval 无*/
void SPI_FLASH_FOUR_MODE(void)
{uint8_t temp 0;// 使能写命令SPI_FLASH_WriteEnable();// 拉低片选线开始通信SPI_FLASH_NSS_LOW();// 发送写状态寄存器3命令SPI_FLASH_SendByte(W25Q256_WriteStatusRegister3);// 发送要写的数据SPI_FLASH_SendByte(0x02);// 拉高片选线结束通信SPI_FLASH_NSS_HIGH();// 拉低片选线开始通信SPI_FLASH_NSS_LOW();// 发送读状态寄存器3命令SPI_FLASH_SendByte(W25Q256_ReadStatusRegister3);// 读取数据temp SPI_FLASH_ReadByte();// 拉高片选线结束通信SPI_FLASH_NSS_HIGH();if (1 (0x02 temp)){// 拉低片选线开始通信SPI_FLASH_NSS_LOW();// 发送配置四字节模式指令SPI_FLASH_SendByte(W25Q256_Enter4ByteMode);// 拉高片选线结束通信SPI_FLASH_NSS_HIGH();}SPI_FLASH_WaitForOperaEnd();
}/*** brief 对 FLASH 按页写入数据调用本函数写入数据前需要先擦除扇区* param pBuffer要写入数据的指针* param WriteAddr写入数据地址* param NumByteToWrite写入数据长度。必须小于等于SPI_FLASH_PerWritePageSize* retval 无*/
void SPI_FLASH_PageWrite(uint8_t *pBuffer, uint32_t WriteAddr, uint16_t NumByteToWrite)
{// 使能写命令SPI_FLASH_WriteEnable();// 拉低片选线开始通信SPI_FLASH_NSS_LOW();// 发送页写入指令SPI_FLASH_SendByte(W25Q256_PageProgram);// 发送写入地址[24,31]bitSPI_FLASH_SendByte((WriteAddr 0xFF000000) 24);// 发送写入地址[16,23]bitSPI_FLASH_SendByte((WriteAddr 0xFF0000) 16);// 发送写入地址[8,15]bitSPI_FLASH_SendByte((WriteAddr 0xFF00) 8);// 发送写入地址[0,7]bitSPI_FLASH_SendByte(WriteAddr 0xFF);if (NumByteToWrite SPI_FLASH_PerWritePageSize){NumByteToWrite SPI_FLASH_PerWritePageSize;printf(256\r\n);}for (int i 0; i NumByteToWrite; i){SPI_FLASH_SendByte(pBuffer[i]);}// 拉高片选线结束通信SPI_FLASH_NSS_HIGH();
}/*** brief FALSH不定量数据写入函数调用本函数写入数据前需要先擦除扇区* param pBuffer要写入数据的指针* param WriteAddr写入数据地址* param NumByteToWrite写入数据长度* retval 无*/
void SPI_FLASH_BufferWrite(uint8_t *pBuffer, uint32_t WriteAddr, uint16_t NumByteToWrite)
{uint8_t NumOfPage 0;uint8_t NumOfSingle 0;uint8_t Addr 0;uint8_t count 0;uint8_t temp 0;/*mod 运算求余若 writeAddr 是 SPI_FLASH_PageSize 整数倍运算结果 Addr 值为0*/Addr WriteAddr % SPI_FLASH_PageSize;/* 差 count 个数据值刚好可以对齐到页地址 */count SPI_FLASH_PageSize - Addr;/* 计算出要写多少整数页 */NumOfPage NumByteToWrite / SPI_FLASH_PageSize;/*mod 运算求余计算出剩余不满一页的字节数 */NumOfSingle NumByteToWrite % SPI_FLASH_PageSize;/* Addr0, 则 WriteAddr 刚好按页对齐 aligned */if (0 Addr){/*NumByteToWrite SPI_FLASH_PageSize*/if (0 NumOfPage){SPI_FLASH_PageWrite(pBuffer, WriteAddr, NumByteToWrite);SPI_FLASH_WaitForOperaEnd(); // 等待操作完成}else{/* 先把整数页都写了 */for (int i 0; i NumOfPage; i){SPI_FLASH_PageWrite(pBuffer, WriteAddr, NumByteToWrite);SPI_FLASH_WaitForOperaEnd(); // 等待操作完成WriteAddr SPI_FLASH_PageSize;pBuffer SPI_FLASH_PageSize;}/* 若有多余的不满一页的数据把它写完 */SPI_FLASH_PageWrite(pBuffer, WriteAddr, NumOfSingle);SPI_FLASH_WaitForOperaEnd(); // 等待操作完成}}else /* 若地址与 SPI_FLASH_PageSize 不对齐 */{/*NumByteToWrite SPI_FLASH_PageSize*/if (0 NumOfPage){/* 当前页剩余的 count 个位置比 NumOfSingle 小写不完 */if (NumOfSingle count){temp NumOfSingle - count;/* 先写满当前页 */SPI_FLASH_PageWrite(pBuffer, WriteAddr, count);SPI_FLASH_WaitForOperaEnd(); // 等待操作完成WriteAddr count;pBuffer count;/* 再写剩余的数据 */SPI_FLASH_PageWrite(pBuffer, WriteAddr, temp);SPI_FLASH_WaitForOperaEnd(); // 等待操作完成}else /* 当前页剩余的 count 个位置能写完 NumOfSingle 个数据 */{SPI_FLASH_PageWrite(pBuffer, WriteAddr, NumByteToWrite);SPI_FLASH_WaitForOperaEnd(); // 等待操作完成}}else /*NumByteToWrite SPI_FLASH_PageSize*/{/*先把距离页地址的count个数据减去计算需要写的页数和NumOfSingle然后写数据时先把原来减去的count个数据写入写满当前页*//*再写剩余数据即计算好的NumOfPage和NumOfSingle*/NumByteToWrite - count;NumOfPage NumByteToWrite / SPI_FLASH_PageSize;NumOfSingle NumByteToWrite % SPI_FLASH_PageSize;SPI_FLASH_PageWrite(pBuffer, WriteAddr, count);SPI_FLASH_WaitForOperaEnd(); // 等待操作完成WriteAddr count;pBuffer count;/* 把整数页都写了 */for (int i 0; i NumOfPage; i){SPI_FLASH_PageWrite(pBuffer, WriteAddr, SPI_FLASH_PageSize);SPI_FLASH_WaitForOperaEnd(); // 等待操作完成WriteAddr SPI_FLASH_PageSize;pBuffer SPI_FLASH_PageSize;}if (0 ! NumOfSingle){SPI_FLASH_PageWrite(pBuffer, WriteAddr, NumOfSingle);SPI_FLASH_WaitForOperaEnd(); // 等待操作完成}}}
}/*** brief 读取FLASH数据* param pBuffer存储读出数据的指针* param WriteAddr读取地址* param NumByteToRead读取数据长度* retval 无*/
void SPI_FLASH_BufferRead(uint8_t *pBuffer, uint32_t ReadAddr, uint16_t NumByteToRead)
{// 拉低片选线开始通信SPI_FLASH_NSS_LOW();// 发送读取数据指令SPI_FLASH_SendByte(W25Q256_ReadData);// 发送读取地址[24,31]bitSPI_FLASH_SendByte((ReadAddr 0xFF000000) 24);// 发送读取地址[16,23]bitSPI_FLASH_SendByte((ReadAddr 0xFF0000) 16);// 发送读取地址[8,15]bitSPI_FLASH_SendByte((ReadAddr 0xFF00) 8);// 发送读取地址[0,7]bitSPI_FLASH_SendByte(ReadAddr 0xFF);// 读取数据for (int i 0; i NumByteToRead; i){// 读取一个字节数据pBuffer[i] SPI_FLASH_ReadByte();}// 拉高片选线结束通信SPI_FLASH_NSS_HIGH();SPI_FLASH_WaitForOperaEnd(); // 等待操作完成
}/*** brief 等待写入、擦除等操作结束* param none* param none* param none* retval none*/
void SPI_FLASH_WaitForOperaEnd(void)
{uint8_t FLASH_Status 0;// 拉低片选线开始通信SPI_FLASH_NSS_LOW();// 发送读状态寄存器1指令SPI_FLASH_SendByte(W25Q256_ReadStatusReg);do{// 接收读取状态寄存器1寄存器内容FLASH_Status SPI_FLASH_ReadByte();} while (SET (FLASH_Status WIP_Flag));// 拉高片选线结束通信SPI_FLASH_NSS_HIGH();
}
int main(void)
{/* USER CODE BEGIN 1 *//* USER CODE END 1 *//* MCU Configuration--------------------------------------------------------*//* Reset of all peripherals, Initializes the Flash interface and the Systick. */HAL_Init();/* USER CODE BEGIN Init *//* USER CODE END Init *//* Configure the system clock */SystemClock_Config();/* USER CODE BEGIN SysInit *//* USER CODE END SysInit *//* Initialize all configured peripherals */MX_GPIO_Init();MX_SPI5_Init();MX_USART1_UART_Init();/* USER CODE BEGIN 2 */// 进入4字节地址模式SPI_FLASH_FOUR_MODE();printf(W25Q256 SPI readwrite test!!!\r\n);device_ID SPI_FLASH_ReadID();printf(device_ID 0x%x\r\n, device_ID);SPI_FLASH_SectorErase(0x00); // 擦除扇区数据// 读取擦除后的数据SPI_FLASH_BufferRead(ReadBuff, 0x00, 4096);printf(*****************读取擦出后的数据*****************\r\n);for (int i 0; i 4096; i){printf(ReadBuff[%d] 0x%02x\t, i, ReadBuff[i]);if (0 (i 1) % 8 (i 1) 8){printf(\r\n);}}for (int i 0; i 256; i){WriteBuff[i] i;}SPI_FLASH_BufferWrite(WriteBuff, 0xFF, 256);SPI_FLASH_WaitForOperaEnd(); // 等待操作完成// 读数据SPI_FLASH_BufferRead(ReadBuff, 0xFF, 256);SPI_FLASH_WaitForOperaEnd(); // 等待操作完成printf(*****************读取写入后的数据*****************\r\n);for (int i 0; i 256; i){printf(ReadBuff[%d] 0x%02x\t, i, ReadBuff[i]);if (0 (i 1) % 8 (i 1) 8){printf(\r\n);}}/* USER CODE END 2 *//* Infinite loop *//* USER CODE BEGIN WHILE */while (1){/* USER CODE END WHILE *//* USER CODE BEGIN 3 */LED_TIME();}/* USER CODE END 3 */
} 6、实验现象