程序如下:
void SPI2_Init(void)
{
SPI_InitTypeDef SPI_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2 ,ENABLE);
RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB, ENABLE ); //PORTB时钟使能
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 |GPIO_Pin_14| GPIO_Pin_15;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_SetBits(GPIOB,GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15); //PB13/14/15上拉
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12; //PB12:CS片选信号
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB,&GPIO_InitStructure);
GPIO_SetBits(GPIOB,GPIO_Pin_12);
SPI_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_2;
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
SPI_InitStructure.SPI_CRCPolynomial = 7;
SPI_Init(SPI2, &SPI_InitStructure);
//打开SPI2
SPI_Cmd(SPI2, ENABLE);
//SPI2_ReadWriteByte(0xff);//启动传输
}
//SPI写入一个字节
u8 SPI_FLASH_SendByte(u8 byte)
{
/* Loop while DR register in not emplty */
while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET);
/* Send byte through the SPI1 peripheral */
SPI_I2S_SendData(SPI2, byte);
/* Wait to receive a byte */
while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET);
/* Return the byte read from the SPI bus */
return SPI_I2S_ReceiveData(SPI2);
}
#define SPI_FLASH_PageSize 256
u16 SPI_FLASH_TYPE=W25Q32;//默认就是25Q32
//4Kbytes为一个Sector
//8个扇区为1个Block
//W25Q32
//容量为4M字节,共有64个Block,1024个Sector
//初始化SPI FLASH的IO口
void SPI_Flash_Init(void)
{
SPI2_Init(); //初始化SPI
SPI_FLASH_CS=1; //取消片选
}
//SPI_FLASH写使能
//将WEL置位
void SPI_FLASH_Write_Enable(void)
{
SPI_FLASH_CS=0; //使能器件
SPI_FLASH_SendByte(W25X_WriteEnable); //发送写使能
SPI_FLASH_CS=1; //取消片选
}
//SPI_FLASH写禁止
//将WEL清零
void SPI_FLASH_Write_Disable(void)
{
SPI_FLASH_CS=0; //使能器件
SPI_FLASH_SendByte(W25X_WriteDisable); //发送写禁止指令
SPI_FLASH_CS=1; //取消片选
}
void SPI_FLASH_WaitForWriteEnd(void)
{
u8 byte=0;
SPI_FLASH_CS=0;
SPI_FLASH_SendByte(W25X_ReadStatusReg); //发送读取状态寄存器命令
do
{
byte=SPI_FLASH_SendByte(0X00);
} while((byte & W25X_WriteStatusReg)==SET);
SPI_FLASH_CS=1; //取消片选
}
//读取SPI_FLASH的状态寄存器
u8 SPI_Flash_ReadSR(void)
{
u8 byte=0;
SPI_FLASH_CS=0; //使能器件
SPI_FLASH_SendByte(W25X_ReadStatusReg); //发送读取状态寄存器命令
byte=SPI_FLASH_SendByte(0X00); //发送一个字节
SPI_FLASH_CS=1; //取消片选
return byte & 0x01 ;
}
//擦除扇区
void SPI_Flash_Erase_Sector(u32 SectorAddr)
{
SPI_FLASH_Write_Enable(); //SET WEL
SPI_FLASH_CS=0; //使能器件
SPI_FLASH_SendByte(W25X_SectorErase); //发送扇区擦除指令
/* Send SectorAddr high nibble address byte */
SPI_FLASH_SendByte((SectorAddr & 0xFF0000) >> 16);
/* Send SectorAddr medium nibble address byte */
SPI_FLASH_SendByte((SectorAddr & 0xFF00) >> 8);
/* Send SectorAddr low nibble address byte */
SPI_FLASH_SendByte(SectorAddr & 0xFF);
SPI_FLASH_CS=1; //取消片选
}
//写1个字节
void SPI_FLASH_ByteWrite(u8 Buffer, u32 WriteAddr)
{
/* Wait the end of Flash writing */
SPI_FLASH_WaitForWriteEnd();
/* Enable the write access to the FLASH */
SPI_FLASH_Write_Enable();
/* Select the FLASH: Chip Select low */
SPI_FLASH_CS=0;
/* Send "Write to Memory " instruction */
SPI_FLASH_SendByte(W25X_PageProgram);
/* Send WriteAddr high nibble address byte to write to */
SPI_FLASH_SendByte((WriteAddr & 0xFF0000) >> 16);
/* Send WriteAddr medium nibble address byte to write to */
SPI_FLASH_SendByte((WriteAddr & 0xFF00) >> 8);
/* Send WriteAddr low nibble address byte to write to */
SPI_FLASH_SendByte(WriteAddr & 0xFF);
/* Send the current byte */
SPI_FLASH_SendByte(Buffer);
/* Point on the next byte to be written */
/* Deselect the FLASH: Chip Select high */
SPI_FLASH_CS=1;
}
//写1页
void SPI_FLASH_PageWrite(u8* pBuffer, u32 WriteAddr, u16 NumByteToWrite)
{
/* Enable the write access to the FLASH */
SPI_FLASH_Write_Enable();
/* Select the FLASH: Chip Select low */
SPI_FLASH_CS=0;
/* Send "Write to Memory " instruction */
SPI_FLASH_SendByte(W25X_PageProgram );
/* Send WriteAddr high nibble address byte to write to */
SPI_FLASH_SendByte((WriteAddr & 0xFF0000) >> 16);
/* Send WriteAddr medium nibble address byte to write to */
SPI_FLASH_SendByte((WriteAddr & 0xFF00) >> 8);
/* Send WriteAddr low nibble address byte to write to */
SPI_FLASH_SendByte(WriteAddr & 0xFF);
/* while there is data to be written on the FLASH */
while(NumByteToWrite--)
{
/* Send the current byte */
SPI_FLASH_SendByte(*pBuffer);
/* Point on the next byte to be written */
pBuffer++;
}
/* Deselect the FLASH: Chip Select high */
SPI_FLASH_CS=1;
/* Wait the end of Flash writing */
SPI_FLASH_WaitForWriteEnd();
}
/*******************************************************************************
* Function Name : SPI_FLASH_BufferWrite
* Description : Writes block of data to the FLASH. In this function, the
* number of WRITE cycles are reduced, using Page WRITE sequence.
* Input : - pBuffer : pointer to the buffer containing the data to be
* written to the FLASH.
* - WriteAddr : FLASH's internal address to write to.
* - NumByteToWrite : number of bytes to write to the FLASH.
* Output : None
* Return : None
*******************************************************************************/
void SPI_FLASH_BufferWrite(u8* pBuffer, u32 WriteAddr, u16 NumByteToWrite)
{
u8 NumOfPage = 0, NumOfSingle = 0, Addr = 0, count = 0, temp = 0;
Addr = WriteAddr % SPI_FLASH_PageSize;
count = SPI_FLASH_PageSize - Addr;
NumOfPage = NumByteToWrite / SPI_FLASH_PageSize;
NumOfSingle = NumByteToWrite % SPI_FLASH_PageSize;
if(Addr == 0) /* WriteAddr is SPI_FLASH_PageSize aligned */
{
if(NumOfPage == 0) /* NumByteToWrite < SPI_FLASH_PageSize */
{
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);
}
}
else /* WriteAddr is not SPI_FLASH_PageSize aligned */
{
if(NumOfPage== 0) /* NumByteToWrite < SPI_FLASH_PageSize */
{
if(NumOfSingle > count) /* (NumByteToWrite + WriteAddr) > SPI_FLASH_PageSize */
{
temp = NumOfSingle - count;
SPI_FLASH_PageWrite(pBuffer, WriteAddr, count);
WriteAddr += count;
pBuffer += count;
SPI_FLASH_PageWrite(pBuffer, WriteAddr, temp);
}
else
{
SPI_FLASH_PageWrite(pBuffer, WriteAddr, NumByteToWrite);
}
}
else /* NumByteToWrite > SPI_FLASH_PageSize */
{
NumByteToWrite -= count;
NumOfPage = NumByteToWrite / SPI_FLASH_PageSize;
NumOfSingle = NumByteToWrite % SPI_FLASH_PageSize;
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);
}
}
}
}
//读取SPI FLASH
void SPI_FLASH_StartReadSequence(u32 ReadAddr)
{
SPI_FLASH_CS=0; //使能器件
SPI_FLASH_SendByte(W25X_ReadData); //发送读取命令
SPI_FLASH_SendByte((ReadAddr & 0xFF0000) >> 16); //发送24bit地址
SPI_FLASH_SendByte((ReadAddr& 0xFF00) >> 8);
SPI_FLASH_SendByte(ReadAddr & 0xFF);
}
//读取一个字节
u8 SPI_FLASH_ReadByte(void)
{
return (SPI_FLASH_SendByte(0x00));
}
//关掉SPI FLASH操作
void SPI_FLASH_ReadOff(void)
{
SPI_FLASH_CS=1;
}
//读取数据块的FLASH
void SPI_FLASH_BufferRead(u8* pBuffer, u32 ReadAddr, u16 NumByteToRead)
{
/* Select the FLASH: Chip Select low */
SPI_FLASH_CS=0;
/* Send "Read from Memory " instruction */
SPI_FLASH_SendByte(W25X_FastReadData);
/* Send ReadAddr high nibble address byte to read from */
SPI_FLASH_SendByte((ReadAddr & 0xFF0000) >> 16);
/* Send ReadAddr medium nibble address byte to read from */
SPI_FLASH_SendByte((ReadAddr& 0xFF00) >> 8);
/* Send ReadAddr low nibble address byte to read from */
SPI_FLASH_SendByte(ReadAddr & 0xFF);
SPI_FLASH_SendByte(0x00);
while(NumByteToRead--) /* while there is data to be read */
{
/* Read a byte from the FLASH */
*pBuffer= SPI_FLASH_SendByte(0x00);
/* Point to the next location where the byte read will be saved */
pBuffer++;
}
/* Deselect the FLASH: Chip Select high */
SPI_FLASH_CS=1;
}
//读取芯片ID
//返回值如下:
//0XEF13,表示芯片型号为W25Q80
//0XEF14,表示芯片型号为W25Q16
//0XEF15,表示芯片型号为W25Q32
//0XEF16,表示芯片型号为W25Q64
u16 SPI_Flash_ReadID(void)
{
u16 Temp = 0;
SPI_FLASH_CS=0;
SPI_FLASH_SendByte(0x90);//发送读取ID命令
SPI_FLASH_SendByte(0x00);
SPI_FLASH_SendByte(0x00);
SPI_FLASH_SendByte(0x00);
Temp|=SPI_FLASH_SendByte(0xFF)<<8;
Temp|=SPI_FLASH_SendByte(0xFF);
SPI_FLASH_CS=1;
return Temp;
}
//擦除整个芯片
//等待时间超长...
//W25X16:25s
//W25X32:40s
//W25X64:40s
void SPI_Flash_Erase_Chip(void)
{
SPI_FLASH_CS=0;
SPI_FLASH_Write_Enable(); //SET WEL
SPI_FLASH_CS=1;
SPI_Flash_Wait_Busy();
SPI_FLASH_CS=0; //使能器件
SPI_FLASH_SendByte(W25X_ChipErase); //发送片擦除命令
SPI_FLASH_CS=1; //取消片选
SPI_Flash_Wait_Busy(); //等待芯片擦除结束
}
//等待空闲
void SPI_Flash_Wait_Busy(void)
{
while((SPI_Flash_ReadSR()&0x01)==0x01); // 等待BUSY位清空
}
//进入掉电模式
void SPI_Flash_PowerDown(void)
{
SPI_FLASH_CS=0; //使能器件
SPI_FLASH_SendByte(W25X_PowerDown); //发送掉电命令
SPI_FLASH_CS=1; //取消片选
delay_us(3); //等待TPD
}
//唤醒
void SPI_Flash_WAKEUP(void)
{
SPI_FLASH_CS=0; //使能器件
SPI_FLASH_SendByte(W25X_ReleasePowerDown); // send W25X_PowerDown command 0xAB
SPI_FLASH_CS=1; //取消片选
delay_us(3); //等待TRES1
}
#define K1 GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_13)
/*要写入到W25Q32的字符串数组*/
const u8 TEXT_Buffer[]={0x00,0x01,0x02};
#define SIZE sizeof(TEXT_Buffer)
/*************主函数**************************/
int main(void)
{
u8 i;
u8 flag=0;
u8 datatemp[SIZE];
delay_init(24);
RCC_Configuration();
PortInit();
USART_Configuration();
NVIC_Configuration();
ADC_DMA_init();
SPI_Flash_Init(); //SPI FLASH 初始化
while(1)
{
if(GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_13)==0)
{
delay_ms(200);
if(K1 ==0)
{
SPI_Flash_Erase_Chip();
printf("
开始写入W25Q32 SPI FLASH芯片....");
SPI_FLASH_BufferWrite((u8*)TEXT_Buffer,100,SIZE);//从100字节处开始写
printf("
写入完成!");//提示传送完成
flag=1;
}
}
if(flag)
{
printf("
开始从W25Q32 SPI FLASH芯片读取数据.... ");
SPI_FLASH_BufferRead(datatemp,100,SIZE);//从100地址处开始读
printf("
读取完成,读出的数据为: %s ", datatemp);//提示传送完成
flag=0;
}
i++;
delay_ms(20);
if(i==20)
{
//提示系统正在运行
GPIO_SetBits(GPIOB, GPIO_Pin_2);
delay_ms(200);
GPIO_ResetBits(GPIOB, GPIO_Pin_2);;
i=0;
}
}
}
一直高电平,我换了一块MCU就OK了!谢谢
一周热门 更多>