当前位置: 首页 > news >正文

现在还有企业做网站吗荆门市网站建设

现在还有企业做网站吗,荆门市网站建设,网站有什么类型,网站建设站main.c FLASH#xff1a;掉电后数据不丢失#xff0c;U 盘、SD 卡、SSD 固态硬盘、STM32 芯片内部用于存储程序的设备#xff0c;都是 FLASH 类型的存储器。FLASH芯片(W25Q64)是一种使用 SPI 通讯协议的 NOR FLASH 存储器。 STM32 的 NSS 引脚是一个普通的 GPIO#xff0c…main.c FLASH掉电后数据不丢失U 盘、SD 卡、SSD 固态硬盘、STM32 芯片内部用于存储程序的设备都是 FLASH 类型的存储器。FLASH芯片(W25Q64)是一种使用 SPI 通讯协议的 NOR FLASH 存储器。 STM32 的 NSS 引脚是一个普通的 GPIO程序中要使用软件控制的方式。 结果 里面的FlashID是Flash芯片ID就是W25Q64的厂商号和FLASH型号。通过Flash型号对比来看看W25Q64是否连接正常。 然后擦除FLASH扇区往FLASH里面写数据读FLASH里面的数据。检查写入的数据与读出的数据是否相等相等的话亮绿灯。 #include stm32f10x.h #include ./usart/bsp_usart.h #include ./led/bsp_led.h #include ./flash/bsp_spi_flash.htypedef enum { FAILED 0, PASSED !FAILED} TestStatus;/* 获取缓冲区的长度 */ #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/* 发送缓冲区初始化 */ uint8_t Tx_Buffer[] jymjymjym123456789\r\n; uint8_t Rx_Buffer[BufferSize];__IO uint32_t DeviceID 0; __IO uint32_t FlashID 0; __IO TestStatus TransferStatus1 FAILED;// 函数原型声明 void Delay(__IO uint32_t nCount); TestStatus Buffercmp(uint8_t* pBuffer1,uint8_t* pBuffer2, uint16_t BufferLength);/** 函数名main* 描述 主函数* 输入 无* 输出 无*/ int main(void) { LED_GPIO_Config();LED_BLUE;/* 配置串口为115200 8-N-1 */USART_Config();printf(\r\n 这是一个8Mbyte串行flash(W25Q64)实验 \r\n);/* 8M串行flash W25Q64初始化 */SPI_FLASH_Init();/* 获取 Flash Device ID */DeviceID SPI_FLASH_ReadDeviceID(); Delay( 200 );/* 获取 SPI Flash ID */FlashID SPI_FLASH_ReadID(); printf(\r\n FlashID is 0x%X,\Manufacturer Device ID is 0x%X\r\n, FlashID, DeviceID);/* 检验 SPI Flash ID */if (FlashID sFLASH_ID){ printf(\r\n 检测到串行flash W25Q64 !\r\n);/* 擦除将要写入的 SPI FLASH 扇区FLASH写入前要先擦除 */// 这里擦除4K即一个扇区擦除的最小单位是扇区SPI_FLASH_SectorErase(FLASH_SectorToErase); /* 将发送缓冲区的数据写到flash中 */// 这里写一页一页的大小为256个字节SPI_FLASH_BufferWrite(Tx_Buffer, FLASH_WriteAddress, BufferSize); printf(\r\n 写入的数据为%s \r\t, Tx_Buffer);/* 将刚刚写入的数据读出来放到接收缓冲区中 */SPI_FLASH_BufferRead(Rx_Buffer, FLASH_ReadAddress, BufferSize);printf(\r\n 读出的数据为%s \r\n, Rx_Buffer);/* 检查写入的数据与读出的数据是否相等 */TransferStatus1 Buffercmp(Tx_Buffer, Rx_Buffer, BufferSize);if( PASSED TransferStatus1 ){ LED_GREEN;printf(\r\n 8M串行flash(W25Q64)测试成功!\n\r);}else{ LED_RED;printf(\r\n 8M串行flash(W25Q64)测试失败!\n\r);}}// if (FlashID sFLASH_ID)else// if (FlashID sFLASH_ID){ LED_RED;printf(\r\n 获取不到 W25Q64 ID!\n\r);}while(1); }/** 函数名Buffercmp* 描述 比较两个缓冲区中的数据是否相等* 输入 -pBuffer1 src缓冲区指针* -pBuffer2 dst缓冲区指针* -BufferLength 缓冲区长度* 输出 无* 返回 -PASSED pBuffer1 等于 pBuffer2* -FAILED pBuffer1 不同于 pBuffer2*/ TestStatus Buffercmp(uint8_t* pBuffer1, uint8_t* pBuffer2, uint16_t BufferLength) {while(BufferLength--){if(*pBuffer1 ! *pBuffer2){return FAILED;}pBuffer1;pBuffer2;}return PASSED; }void Delay(__IO uint32_t nCount) {for(; nCount ! 0; nCount--); } /*********************************************END OF FILE**********************/spi_flash.h 里面写了SPI 硬件相关的宏定义。根据硬件连接把FLASH用的SPI号、GPIO用宏封装。定义控制 CS(NSS)引脚输出电平的宏用来控制产生起始和停止信号。 里面还定义了 FLASH 指令编码表。 #ifndef __SPI_FLASH_H #define __SPI_FLASH_H#include stm32f10x.h #include stdio.h//#define sFLASH_ID 0xEF3015 //W25X16 //#define sFLASH_ID 0xEF4015 //W25Q16 //#define sFLASH_ID 0XEF4018 //W25Q128 #define sFLASH_ID 0XEF4017 //W25Q64#define SPI_FLASH_PageSize 256 #define SPI_FLASH_PerWritePageSize 256/*命令定义-开头*******************************/ #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/* WIP(busy)标志FLASH内部正在写入 */ #define WIP_Flag 0x01 #define Dummy_Byte 0xFF /*命令定义-结尾*******************************//*SPI接口定义-开头****************************/ #define FLASH_SPIx SPI1 #define FLASH_SPI_APBxClock_FUN RCC_APB2PeriphClockCmd #define FLASH_SPI_CLK RCC_APB2Periph_SPI1//CS(NSS)引脚 片选选普通GPIO即可 #define FLASH_SPI_CS_APBxClock_FUN RCC_APB2PeriphClockCmd #define FLASH_SPI_CS_CLK RCC_APB2Periph_GPIOC #define FLASH_SPI_CS_PORT GPIOC #define FLASH_SPI_CS_PIN GPIO_Pin_0//SCK引脚 #define FLASH_SPI_SCK_APBxClock_FUN RCC_APB2PeriphClockCmd #define FLASH_SPI_SCK_CLK RCC_APB2Periph_GPIOA #define FLASH_SPI_SCK_PORT GPIOA #define FLASH_SPI_SCK_PIN GPIO_Pin_5 //MISO引脚 #define FLASH_SPI_MISO_APBxClock_FUN RCC_APB2PeriphClockCmd #define FLASH_SPI_MISO_CLK RCC_APB2Periph_GPIOA #define FLASH_SPI_MISO_PORT GPIOA #define FLASH_SPI_MISO_PIN GPIO_Pin_6 //MOSI引脚 #define FLASH_SPI_MOSI_APBxClock_FUN RCC_APB2PeriphClockCmd #define FLASH_SPI_MOSI_CLK RCC_APB2Periph_GPIOA #define FLASH_SPI_MOSI_PORT GPIOA #define FLASH_SPI_MOSI_PIN GPIO_Pin_7#define SPI_FLASH_CS_LOW() GPIO_ResetBits( FLASH_SPI_CS_PORT, FLASH_SPI_CS_PIN ) #define SPI_FLASH_CS_HIGH() GPIO_SetBits( FLASH_SPI_CS_PORT, FLASH_SPI_CS_PIN )/*SPI接口定义-结尾****************************//*等待超时时间*/ #define SPIT_FLAG_TIMEOUT ((uint32_t)0x1000) #define SPIT_LONG_TIMEOUT ((uint32_t)(10 * SPIT_FLAG_TIMEOUT))/*信息输出*/ #define FLASH_DEBUG_ON 1#define FLASH_INFO(fmt,arg...) printf(-FLASH-INFO- fmt\n,##arg) #define FLASH_ERROR(fmt,arg...) printf(-FLASH-ERROR- fmt\n,##arg) #define FLASH_DEBUG(fmt,arg...) do{\if(FLASH_DEBUG_ON)\printf(-FLASH-DEBUG- [%d]fmt\n,__LINE__, ##arg);\}while(0)void SPI_FLASH_Init(void); void SPI_FLASH_SectorErase(u32 SectorAddr); void SPI_FLASH_BulkErase(void); void SPI_FLASH_PageWrite(u8* pBuffer, u32 WriteAddr, u16 NumByteToWrite); void SPI_FLASH_BufferWrite(u8* pBuffer, u32 WriteAddr, u16 NumByteToWrite); void SPI_FLASH_BufferRead(u8* pBuffer, u32 ReadAddr, u16 NumByteToRead); u32 SPI_FLASH_ReadID(void); u32 SPI_FLASH_ReadDeviceID(void); void SPI_FLASH_StartReadSequence(u32 ReadAddr); void SPI_Flash_PowerDown(void); void SPI_Flash_WAKEUP(void);u8 SPI_FLASH_ReadByte(void); u8 SPI_FLASH_SendByte(u8 byte); u16 SPI_FLASH_SendHalfWord(u16 HalfWord); void SPI_FLASH_WriteEnable(void); void SPI_FLASH_WaitForWriteEnd(void);#endif /* __SPI_FLASH_H */ spi_flash.c 下面这个函数用于初始化 SPI 的 GPIO(配置 SPI 使用的引脚)配置 SPI 的模式。 void SPI_FLASH_Init(void)下面这两个函数分别是使用SPI发送、接收一个字节的数据。函数中不包含 SPI 起始和停止信号只是收发的主要过程。主要就是通过SPI_I2S_GetFlagStatus函数检测事件。 首先检测 TXE 标志获取发送缓冲区的状态。等待至发送缓冲区为空后通过SPI_I2S_SendData函数把要写入的数据写入数据寄存器DR。 然后检测 RXNE 标志获取接收缓冲区的状态。等待至接收缓冲区为非空通过SPI_I2S_ReceiveData函数读取 SPI 的数据寄存器 DR。 u8 SPI_FLASH_SendByte(u8 byte)u8 SPI_FLASH_ReadByte(void)对 FLASH 芯片进行操作控制 STM32 利用 SPI 总线向 FLASH 芯片发送指令FLASH 芯片收到指令后就会执行相应的操作。 W25Q64定义的各种指令的功能及指令格式如下。根据这些指令的格式要求 使用通讯协议向设备发送指令从而控制设备。 定义FLASH 指令编码表可以把 FLASH 芯片的常用指令编码使用宏来封装起来可以在发送指令编码时直接使用这些宏FLASH 指令编码表在上面的spi_flash.h里面写了。 读取Flash芯片ID 对于W25Q64芯片厂商号(M7-M0)EF h FLASH 型号(ID15-ID0)4017 h。 根据下面的时序可以编写函数这里面发送JEDEC指令用的是SPI_FLASH_SendByte函数这个函数就是根据SPI通信协议编写的那么这个指令就能够传到W25Q64芯片里面相当于使用通讯协议向设备发送指令。由于SPI_FLASH_SendByte返回接收到的数据那么继续调用它相当于接收W25Q64芯片对JEDEC指令的响应。 最后可以把该返回值与定义的宏sFLASH_ID对比判断 FLASH 芯片是否正常。 #define sFLASH_ID 0XEF4017 //W25Q64u32 SPI_FLASH_ReadID(void) {u32 Temp 0, Temp0 0, Temp1 0, Temp2 0;/* 开始通讯CS低电平 */SPI_FLASH_CS_LOW();/* 发送JEDEC指令读取ID */SPI_FLASH_SendByte(W25X_JedecDeviceID);/* 读取一个字节数据 */Temp0 SPI_FLASH_SendByte(Dummy_Byte);/* 读取一个字节数据 */Temp1 SPI_FLASH_SendByte(Dummy_Byte);/* 读取一个字节数据 */Temp2 SPI_FLASH_SendByte(Dummy_Byte);/* 停止通讯CS高电平 */SPI_FLASH_CS_HIGH();/*把数据组合起来作为函数的返回值*/Temp (Temp0 16) | (Temp1 8) | Temp2;return Temp; }FLASH写使能下面这个函数实现FLASH写使能也就是使用SPI协议向FLASH里面发了一个WriteEnable指令。 向Flash芯片存储矩阵写入数据之前要进行写使能。 void SPI_FLASH_WriteEnable(void)读取FLASH当前状态FLASH内部有一个状态寄存器这个状态寄存器第0位(busy位)为1说明FLASH芯片可能正在对内部的存储矩阵进行擦除或数据写入操作。在写操作后需要确认 FLASH 芯片空闲时才能进行再次写入。 下面这个函数实现了读取FLASH当前状态功能。发了一个ReadStatusReg指令来读FLASH的状态寄存器在while 循环里持续获得状态寄存器的内容并检验它的busy位一直等待到busy位为0(FLASH芯片已经写入完毕)才退出循环。 void SPI_FLASH_WaitForWriteEnd(void)FLASH扇区擦除向FLASH写入数据前要对目标存储区进行擦除操作这是因为FLASH存储器只能把1数据位改成0那么如果要存储1但如果目标存储区的数据位是0那就没法存储1了。所以擦除操作要对目标存储区中的数据位全部擦成1。 FLASH扇区擦除函数如下其实也就是对FLASH发送几个指令指令后边要加上SPI_FLASH_WaitForWriteEnd函数用来等待扇区操作完成。发送发送擦除地址时高位在前调用扇区擦除指令时输入的地址要对齐到 4KB。下图是FLASH芯片的扇区(Sector 4KB)和块(Block 64KB)的存储结构。 /*** brief 擦除FLASH扇区* param SectorAddr要擦除的扇区地址* retval 无*/ void SPI_FLASH_SectorErase(u32 SectorAddr) {/* 发送FLASH写使能命令 */SPI_FLASH_WriteEnable();SPI_FLASH_WaitForWriteEnd();/* 擦除扇区 *//* 选择FLASH: CS低电平 */SPI_FLASH_CS_LOW();/* 发送扇区擦除指令*/SPI_FLASH_SendByte(W25X_SectorErase);/*发送擦除扇区地址的高位*/SPI_FLASH_SendByte((SectorAddr 0xFF0000) 16);/* 发送擦除扇区地址的中位 */SPI_FLASH_SendByte((SectorAddr 0xFF00) 8);/* 发送擦除扇区地址的低位 */SPI_FLASH_SendByte(SectorAddr 0xFF);/* 停止信号 FLASH: CS 高电平 */SPI_FLASH_CS_HIGH();/* 等待擦除完毕*/SPI_FLASH_WaitForWriteEnd(); }FLASH页写入 FLASH芯片有页写入命令使用页写入命令最多可以一次向FLASH传输 256 个字节的数据(这个单位为页大小)。时序图如下。 由图可知发送完写指令再发送写地址(从高位到低位发)再发要写入的内容(一个字节一个字节的发最多256个字节)。发送完结束通信然后等待Flash内部写入结束。下面这个是页写入函数。(调用这个函数写入数据前需要先擦除扇区) /*** brief 对FLASH按页写入数据调用本函数写入数据前需要先擦除扇区* param pBuffer要写入数据的指针* param WriteAddr写入地址* param NumByteToWrite写入数据长度必须小于等于SPI_FLASH_PerWritePageSize* retval 无*/ void SPI_FLASH_PageWrite(u8* pBuffer, u32 WriteAddr, u16 NumByteToWrite)下面这个函数是不定量数据写入。 /*** brief 对FLASH写入数据调用本函数写入数据前需要先擦除扇区* param pBuffer要写入数据的指针* param WriteAddr写入地址* param NumByteToWrite写入数据长度* retval 无*/ void SPI_FLASH_BufferWrite(u8* pBuffer, u32 WriteAddr, u16 NumByteToWrite)从Flash读数据使用读取指令ReadData。 /*** brief 读取FLASH数据* param pBuffer存储读出数据的指针* param ReadAddr读取地址* param NumByteToRead读取数据长度* retval 无*/ void SPI_FLASH_BufferRead(u8* pBuffer, u32 ReadAddr, u16 NumByteToRead)函数首先发送读指令再发送读地址的高位到地位再读数据读完就发送停止信号。 全部代码 #include ./flash/bsp_spi_flash.hstatic __IO uint32_t SPITimeout SPIT_LONG_TIMEOUT; static uint16_t SPI_TIMEOUT_UserCallback(uint8_t errorCode);/*** brief SPI_FLASH初始化* param 无* retval 无*/ void SPI_FLASH_Init(void) {SPI_InitTypeDef SPI_InitStructure;GPIO_InitTypeDef GPIO_InitStructure;/* 使能SPI时钟 */FLASH_SPI_APBxClock_FUN ( FLASH_SPI_CLK, ENABLE );/* 使能SPI引脚相关的时钟 */FLASH_SPI_CS_APBxClock_FUN ( FLASH_SPI_CS_CLK|FLASH_SPI_SCK_CLK|FLASH_SPI_MISO_PIN|FLASH_SPI_MOSI_PIN, ENABLE );/* 配置SPI的 CS引脚普通IO即可 */GPIO_InitStructure.GPIO_Pin FLASH_SPI_CS_PIN;GPIO_InitStructure.GPIO_Speed GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Mode GPIO_Mode_Out_PP;GPIO_Init(FLASH_SPI_CS_PORT, GPIO_InitStructure);/* 配置SPI的 SCK引脚*/GPIO_InitStructure.GPIO_Pin FLASH_SPI_SCK_PIN;GPIO_InitStructure.GPIO_Mode GPIO_Mode_AF_PP;GPIO_Init(FLASH_SPI_SCK_PORT, GPIO_InitStructure);/* 配置SPI的 MISO引脚*/GPIO_InitStructure.GPIO_Pin FLASH_SPI_MISO_PIN;GPIO_Init(FLASH_SPI_MISO_PORT, GPIO_InitStructure);/* 配置SPI的 MOSI引脚*/GPIO_InitStructure.GPIO_Pin FLASH_SPI_MOSI_PIN;GPIO_Init(FLASH_SPI_MOSI_PORT, GPIO_InitStructure);/* 停止信号 FLASH: CS引脚高电平*/SPI_FLASH_CS_HIGH();/* SPI 模式配置 */// FLASH芯片 支持SPI模式0及模式3据此设置CPOL CPHASPI_InitStructure.SPI_Direction SPI_Direction_2Lines_FullDuplex;SPI_InitStructure.SPI_Mode SPI_Mode_Master;SPI_InitStructure.SPI_DataSize SPI_DataSize_8b;SPI_InitStructure.SPI_CPOL SPI_CPOL_High;SPI_InitStructure.SPI_CPHA SPI_CPHA_2Edge;SPI_InitStructure.SPI_NSS SPI_NSS_Soft;SPI_InitStructure.SPI_BaudRatePrescaler SPI_BaudRatePrescaler_4;SPI_InitStructure.SPI_FirstBit SPI_FirstBit_MSB;SPI_InitStructure.SPI_CRCPolynomial 7;SPI_Init(FLASH_SPIx , SPI_InitStructure);/* 使能 SPI */SPI_Cmd(FLASH_SPIx , ENABLE);}/*** brief 擦除FLASH扇区* param SectorAddr要擦除的扇区地址* retval 无*/ void SPI_FLASH_SectorErase(u32 SectorAddr) {/* 发送FLASH写使能命令 */SPI_FLASH_WriteEnable();SPI_FLASH_WaitForWriteEnd();/* 擦除扇区 *//* 选择FLASH: CS低电平 */SPI_FLASH_CS_LOW();/* 发送扇区擦除指令*/SPI_FLASH_SendByte(W25X_SectorErase);/*发送擦除扇区地址的高位*/SPI_FLASH_SendByte((SectorAddr 0xFF0000) 16);/* 发送擦除扇区地址的中位 */SPI_FLASH_SendByte((SectorAddr 0xFF00) 8);/* 发送擦除扇区地址的低位 */SPI_FLASH_SendByte(SectorAddr 0xFF);/* 停止信号 FLASH: CS 高电平 */SPI_FLASH_CS_HIGH();/* 等待擦除完毕*/SPI_FLASH_WaitForWriteEnd(); }/*** brief 擦除FLASH扇区整片擦除* param 无* retval 无*/ void SPI_FLASH_BulkErase(void) {/* 发送FLASH写使能命令 */SPI_FLASH_WriteEnable();/* 整块 Erase *//* 选择FLASH: CS低电平 */SPI_FLASH_CS_LOW();/* 发送整块擦除指令*/SPI_FLASH_SendByte(W25X_ChipErase);/* 停止信号 FLASH: CS 高电平 */SPI_FLASH_CS_HIGH();/* 等待擦除完毕*/SPI_FLASH_WaitForWriteEnd(); }/*** brief 对FLASH按页写入数据调用本函数写入数据前需要先擦除扇区* param pBuffer要写入数据的指针* param WriteAddr写入地址* param NumByteToWrite写入数据长度必须小于等于SPI_FLASH_PerWritePageSize* retval 无*/ void SPI_FLASH_PageWrite(u8* pBuffer, u32 WriteAddr, u16 NumByteToWrite) {/* 发送FLASH写使能命令 */SPI_FLASH_WriteEnable();/* 选择FLASH: CS低电平 */SPI_FLASH_CS_LOW();/* 写页写指令*/SPI_FLASH_SendByte(W25X_PageProgram);/*发送写地址的高位*/SPI_FLASH_SendByte((WriteAddr 0xFF0000) 16);/*发送写地址的中位*/SPI_FLASH_SendByte((WriteAddr 0xFF00) 8);/*发送写地址的低位*/SPI_FLASH_SendByte(WriteAddr 0xFF);if(NumByteToWrite SPI_FLASH_PerWritePageSize){NumByteToWrite SPI_FLASH_PerWritePageSize;FLASH_ERROR(SPI_FLASH_PageWrite too large!); }/* 写入数据*/while (NumByteToWrite--){/* 发送当前要写入的字节数据 */SPI_FLASH_SendByte(*pBuffer);/* 指向下一字节数据 */pBuffer;}/* 停止信号 FLASH: CS 高电平 */SPI_FLASH_CS_HIGH();/* 等待写入完毕*/SPI_FLASH_WaitForWriteEnd(); }/*** brief 对FLASH写入数据调用本函数写入数据前需要先擦除扇区* param pBuffer要写入数据的指针* param WriteAddr写入地址* param NumByteToWrite写入数据长度* retval 无*/ void SPI_FLASH_BufferWrite(u8* pBuffer, u32 WriteAddr, u16 NumByteToWrite) {u8 NumOfPage 0, NumOfSingle 0, Addr 0, count 0, 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 (Addr 0){/* NumByteToWrite SPI_FLASH_PageSize */if (NumOfPage 0) {SPI_FLASH_PageWrite(pBuffer, WriteAddr, NumByteToWrite);}else /* NumByteToWrite SPI_FLASH_PageSize */{ /*先把整数页都写了*/while (NumOfPage--){SPI_FLASH_PageWrite(pBuffer, WriteAddr, SPI_FLASH_PageSize);WriteAddr SPI_FLASH_PageSize;pBuffer SPI_FLASH_PageSize;}/*若有多余的不满一页的数据把它写完*/SPI_FLASH_PageWrite(pBuffer, WriteAddr, NumOfSingle);}}/* 若地址与 SPI_FLASH_PageSize 不对齐 */else {/* NumByteToWrite SPI_FLASH_PageSize */if (NumOfPage 0){/*当前页剩余的count个位置比NumOfSingle小一页写不完*/if (NumOfSingle count) {temp NumOfSingle - count;/*先写满当前页*/SPI_FLASH_PageWrite(pBuffer, WriteAddr, count);WriteAddr count;pBuffer count;/*再写剩余的数据*/SPI_FLASH_PageWrite(pBuffer, WriteAddr, temp);}else /*当前页剩余的count个位置能写完NumOfSingle个数据*/{SPI_FLASH_PageWrite(pBuffer, WriteAddr, NumByteToWrite);}}else /* NumByteToWrite SPI_FLASH_PageSize */{/*地址不对齐多出的count分开处理不加入这个运算*/NumByteToWrite - count;NumOfPage NumByteToWrite / SPI_FLASH_PageSize;NumOfSingle NumByteToWrite % SPI_FLASH_PageSize;/* 先写完count个数据为的是让下一次要写的地址对齐 */SPI_FLASH_PageWrite(pBuffer, WriteAddr, count);/* 接下来就重复地址对齐的情况 */WriteAddr count;pBuffer count;/*把整数页都写了*/while (NumOfPage--){SPI_FLASH_PageWrite(pBuffer, WriteAddr, SPI_FLASH_PageSize);WriteAddr SPI_FLASH_PageSize;pBuffer SPI_FLASH_PageSize;}/*若有多余的不满一页的数据把它写完*/if (NumOfSingle ! 0){SPI_FLASH_PageWrite(pBuffer, WriteAddr, NumOfSingle);}}} }/*** brief 读取FLASH数据* param pBuffer存储读出数据的指针* param ReadAddr读取地址* param NumByteToRead读取数据长度* retval 无*/ void SPI_FLASH_BufferRead(u8* pBuffer, u32 ReadAddr, u16 NumByteToRead) {/* 选择FLASH: CS低电平 */SPI_FLASH_CS_LOW();/* 发送 读 指令 */SPI_FLASH_SendByte(W25X_ReadData);/* 发送 读 地址高位 */SPI_FLASH_SendByte((ReadAddr 0xFF0000) 16);/* 发送 读 地址中位 */SPI_FLASH_SendByte((ReadAddr 0xFF00) 8);/* 发送 读 地址低位 */SPI_FLASH_SendByte(ReadAddr 0xFF);/* 读取数据 */while (NumByteToRead--) /* while there is data to be read */{/* 读取一个字节*/*pBuffer SPI_FLASH_SendByte(Dummy_Byte);/* 指向下一个字节缓冲区 */pBuffer;}/* 停止信号 FLASH: CS 高电平 */SPI_FLASH_CS_HIGH(); }/*** brief 读取FLASH ID* param 无* retval FLASH ID*/ u32 SPI_FLASH_ReadID(void) {u32 Temp 0, Temp0 0, Temp1 0, Temp2 0;/* 开始通讯CS低电平 */SPI_FLASH_CS_LOW();/* 发送JEDEC指令读取ID */SPI_FLASH_SendByte(W25X_JedecDeviceID);/* 读取一个字节数据 */Temp0 SPI_FLASH_SendByte(Dummy_Byte);/* 读取一个字节数据 */Temp1 SPI_FLASH_SendByte(Dummy_Byte);/* 读取一个字节数据 */Temp2 SPI_FLASH_SendByte(Dummy_Byte);/* 停止通讯CS高电平 */SPI_FLASH_CS_HIGH();/*把数据组合起来作为函数的返回值*/Temp (Temp0 16) | (Temp1 8) | Temp2;return Temp; }/*** brief 读取FLASH Device ID* param 无* retval FLASH Device ID*/ u32 SPI_FLASH_ReadDeviceID(void) {u32 Temp 0;/* Select the FLASH: Chip Select low */SPI_FLASH_CS_LOW();/* Send RDID instruction */SPI_FLASH_SendByte(W25X_DeviceID);SPI_FLASH_SendByte(Dummy_Byte);SPI_FLASH_SendByte(Dummy_Byte);SPI_FLASH_SendByte(Dummy_Byte);/* Read a byte from the FLASH */Temp SPI_FLASH_SendByte(Dummy_Byte);/* Deselect the FLASH: Chip Select high */SPI_FLASH_CS_HIGH();return Temp; } /******************************************************************************* * Function Name : SPI_FLASH_StartReadSequence * Description : Initiates a read data byte (READ) sequence from the Flash. * This is done by driving the /CS line low to select the device, * then the READ instruction is transmitted followed by 3 bytes * address. This function exit and keep the /CS line low, so the * Flash still being selected. With this technique the whole * content of the Flash is read with a single READ instruction. * Input : - ReadAddr : FLASHs internal address to read from. * Output : None * Return : None *******************************************************************************/ void SPI_FLASH_StartReadSequence(u32 ReadAddr) {/* Select the FLASH: Chip Select low */SPI_FLASH_CS_LOW();/* Send Read from Memory instruction */SPI_FLASH_SendByte(W25X_ReadData);/* Send the 24-bit address of the address to read from -----------------------*//* Send ReadAddr high nibble address byte */SPI_FLASH_SendByte((ReadAddr 0xFF0000) 16);/* Send ReadAddr medium nibble address byte */SPI_FLASH_SendByte((ReadAddr 0xFF00) 8);/* Send ReadAddr low nibble address byte */SPI_FLASH_SendByte(ReadAddr 0xFF); }/*** brief 使用SPI读取一个字节的数据* param 无* retval 返回接收到的数据*/ u8 SPI_FLASH_ReadByte(void) {return (SPI_FLASH_SendByte(Dummy_Byte)); }/*** brief 使用SPI发送一个字节的数据* param byte要发送的数据* retval 返回接收到的数据*/ u8 SPI_FLASH_SendByte(u8 byte) {SPITimeout SPIT_FLAG_TIMEOUT;/* 等待发送缓冲区为空TXE事件 */while (SPI_I2S_GetFlagStatus(FLASH_SPIx , SPI_I2S_FLAG_TXE) RESET){if((SPITimeout--) 0) return SPI_TIMEOUT_UserCallback(0);}/* 写入数据寄存器把要写入的数据写入发送缓冲区 */SPI_I2S_SendData(FLASH_SPIx , byte);SPITimeout SPIT_FLAG_TIMEOUT;/* 等待接收缓冲区非空RXNE事件 */while (SPI_I2S_GetFlagStatus(FLASH_SPIx , SPI_I2S_FLAG_RXNE) RESET){if((SPITimeout--) 0) return SPI_TIMEOUT_UserCallback(1);}/* 读取数据寄存器获取接收缓冲区数据 */return SPI_I2S_ReceiveData(FLASH_SPIx ); }/*** brief 使用SPI发送两个字节的数据* param byte要发送的数据* retval 返回接收到的数据*/ u16 SPI_FLASH_SendHalfWord(u16 HalfWord) {SPITimeout SPIT_FLAG_TIMEOUT;/* 等待发送缓冲区为空TXE事件 */while (SPI_I2S_GetFlagStatus(FLASH_SPIx , SPI_I2S_FLAG_TXE) RESET){if((SPITimeout--) 0) return SPI_TIMEOUT_UserCallback(2);}/* 写入数据寄存器把要写入的数据写入发送缓冲区 */SPI_I2S_SendData(FLASH_SPIx , HalfWord);SPITimeout SPIT_FLAG_TIMEOUT;/* 等待接收缓冲区非空RXNE事件 */while (SPI_I2S_GetFlagStatus(FLASH_SPIx , SPI_I2S_FLAG_RXNE) RESET){if((SPITimeout--) 0) return SPI_TIMEOUT_UserCallback(3);}/* 读取数据寄存器获取接收缓冲区数据 */return SPI_I2S_ReceiveData(FLASH_SPIx ); }/*** brief 向FLASH发送 写使能 命令* param none* retval none*/ void SPI_FLASH_WriteEnable(void) {/* 通讯开始CS低 */SPI_FLASH_CS_LOW();/* 发送写使能命令*/SPI_FLASH_SendByte(W25X_WriteEnable);/*通讯结束CS高 */SPI_FLASH_CS_HIGH(); }/* WIP(busy)标志FLASH内部正在写入 */ #define WIP_Flag 0x01/*** brief 等待WIP(BUSY)标志被置0即等待到FLASH内部数据写入完毕* param none* retval none*/ void SPI_FLASH_WaitForWriteEnd(void) {u8 FLASH_Status 0;/* 选择 FLASH: CS 低 */SPI_FLASH_CS_LOW();/* 发送 读状态寄存器 命令 */SPI_FLASH_SendByte(W25X_ReadStatusReg);/* 若FLASH忙碌则等待 */do{/* 读取FLASH芯片的状态寄存器 */FLASH_Status SPI_FLASH_SendByte(Dummy_Byte); }while ((FLASH_Status WIP_Flag) SET); /* 正在写入标志 *//* 停止信号 FLASH: CS 高 */SPI_FLASH_CS_HIGH(); }//进入掉电模式 void SPI_Flash_PowerDown(void) { /* 通讯开始CS低 */SPI_FLASH_CS_LOW();/* 发送 掉电 命令 */SPI_FLASH_SendByte(W25X_PowerDown);/*通讯结束CS高 */SPI_FLASH_CS_HIGH(); } //唤醒 void SPI_Flash_WAKEUP(void) {/*选择 FLASH: CS 低 */SPI_FLASH_CS_LOW();/* 发送 上电 命令 */SPI_FLASH_SendByte(W25X_ReleasePowerDown);/* 停止信号 FLASH: CS 高 */SPI_FLASH_CS_HIGH(); } /*** brief 等待超时回调函数* param None.* retval None.*/ static uint16_t SPI_TIMEOUT_UserCallback(uint8_t errorCode) {/* 等待超时后的处理,输出错误信息 */FLASH_ERROR(SPI 等待超时!errorCode %d,errorCode);return 0; }/*********************************************END OF FILE**********************/
http://www.pierceye.com/news/62124/

相关文章:

  • 昆明凡科建站公司公司网站高端
  • 网站建设与维护ppt模板下载品牌高端网站制作
  • 有个性的个人网站工人找活平台
  • 厦门专业网站天长网站建设天长
  • 网站建设和优化那本书好安徽安庆旅游必去十大景点
  • nginx做网站网站想做个链接怎么做
  • 崇明网站怎么做seo深圳品牌展会
  • 网站开发面试自我介绍上杭县建设局网站
  • 技术支持 昆明网站建设房产资讯的网站怎么做
  • 网站seo优化的重要性红点设计官网
  • 外贸网站建设方法响应式门户网站
  • 网站开发怎么学习wordpress自定义上传图片
  • 做装修网站公司北京搜索引擎推广服务
  • 建设新农村网站做微信小程序的公司
  • 中山网站建设哪家强电子商务网站建设的基本构成
  • 做化妆品网站怎样郑州数码网站建设服务公司
  • 建站公司的服务器网上做调查赚钱的网站
  • 网站右侧信息跟随左侧菜单栏变化备案信息查询官网
  • 个人游戏网站备案做阿里巴巴网站卖货咋样
  • 宁波网站开发服务石家庄网站制作公司排名前十
  • 用asp做宠物网站页面网站建设的局限性
  • 南沙哪有做网站的甘肃做高端网站的公司
  • 如何查看vs中建设好的网站天津网站建设优化企业
  • 模块化网站开发重庆网站建设jccit
  • 与安网站建设网站导航的重要性
  • 天河区做网站公司之江建设工程质量安全监督网站
  • 民宿网站开发数据流图科技是第一生产力
  • 建设网站只南京设计网站
  • 加强心理咨询网站的建设方案南宁网站建设清单
  • 工艺品网站域名dw做的网站如何用手机看