SPI 初始化结构体
typedef struct{uint16_t SPI_Direction; /*设置 SPI 的单双向模式 */uint16_t SPI_Mode; /*设置 SPI 的主/从机端模式 */uint16_t SPI_DataSize; /*设置 SPI 的数据帧长度,可选 8/16 位 */uint16_t SPI_CPOL; /*设置时钟极性 CPOL,可选高/低电平*/uint16_t SPI_CPHA; /*设置时钟相位,可选奇/偶数边沿采样 */uint16_t SPI_NSS; /*设置 NSS 引脚由 SPI 硬件控制还是软件控制*/uint16_t SPI_BaudRatePrescaler; /*设置时钟分频因子, fpclk/分频数=fSCK */uint16_t SPI_FirstBit; /*设置 MSB/LSB 先行 */uint16_t SPI_CRCPolynomial; /*设置 CRC 校验的表达式 */} SPI_InitTypeDef;
SPI读写FLASH实例
bsp_spi_flash.h
#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_GPIOA#define FLASH_SPI_CS_PORT GPIOA#define FLASH_SPI_CS_PIN GPIO_Pin_4//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 */
bsp_spi_flash.c
/********************************************************************************* @file bsp_xxx.c* @author STMicroelectronics* @version V1.0* @date 2013-xx-xx* @brief spi flash 底层应用函数bsp******************************************************************************* @attention** 实验平台:野火 F103-霸道 STM32 开发板* 论坛 :http://www.firebbs.cn* 淘宝 :https://fire-stm32.taobao.com********************************************************************************/#include "./flash/bsp_spi_flash.h"static __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引脚相关的时钟 */ // cs sck miso mosi引脚都是在GPIOA上,所以只需使能1个就行FLASH_SPI_CS_APBxClock_FUN( FLASH_SPI_CS_CLK, ENABLE );//FLASH_SPI_CS_APBxClock_FUN( FLASH_SPI_CS_CLK | FLASH_SPI_SCK_CLK, ENABLE ); 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;/* Addr=0,则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 : FLASH's 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**********************/
main.c
/**
******************************************************************************
* @file main.c
* @author fire
* @version V1.0
* @date 2013-xx-xx
* @brief 华邦 8M串行flash测试,并将测试信息通过串口1在电脑的超级终端中打印出来
******************************************************************************
* @attention
*
* 实验平台:野火 F103-霸道 STM32 开发板
* 论坛 :http://www.firebbs.cn
* 淘宝 :https://fire-stm32.taobao.com
*
******************************************************************************
*/
#include "stm32f10x.h"
#include "./usart/bsp_usart.h"
#include "./led/bsp_led.h"
#include "./flash/bsp_spi_flash.h"
typedef 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[] = "感谢您选用野火stm32开发板\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**********************/
程序文件1-W25Q64.zip
