一共四个文件:myspi.c ,myspi.h ,W25Q64.c ,W25Q64.h
1.myspi.c文件
#include "myspi.h"
void MySPI_SS(uint8_t BitValue)
{
GPIO_WriteBit(GPIOA,GPIO_Pin_4,(BitAction)BitValue);
}
void MySPI_MOSI(uint8_t BitValue)
{
GPIO_WriteBit(GPIOA,GPIO_Pin_7,(BitAction)BitValue);
}
void MySPI_CLK(uint8_t BitValue)
{
GPIO_WriteBit(GPIOA,GPIO_Pin_5,(BitAction)BitValue);
}
uint8_t MySPI_MISO(void)
{
return GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_6);
}
/*
*软件SPI初始化
接线:
*CS:PA4
*DO:PA6
*SLK:PA5
*DI:PA7
*/
void MySPI_Init(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_7;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU;
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_6;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_InitStructure);
MySPI_SS(1);
MySPI_CLK(0);
}
void MySPI_Start(void)
{
MySPI_SS(0);
}
void MySPI_Stop(void)
{
MySPI_SS(1);
}
uint8_t MySPI_W_R_one_Byte(uint8_t ByteData)
{
for(uint8_t i=0;i<8;i++)
{
MySPI_MOSI(ByteData&0X80);
ByteData<<=1;
MySPI_CLK(1);
ByteData|=(0X00|MySPI_MISO());
MySPI_CLK(0);
}
return ByteData;
}
2.myspi.h
#ifndef __MYSPI_H
#define __MYSPI_H
#include "stm32f10x.h" // Device header
void MySPI_Init(void);
void MySPI_Start(void);
void MySPI_Stop(void);
uint8_t MySPI_W_R_one_Byte(uint8_t ByteData);
#endif
3.W25Q64.c
#include "W25Q64.h"
void W25Q64_Init(void)
{
MySPI_Init();
}
/**
* @brief 读取从设备ID
* @param1 存入厂商ID
* @param2 存入设备ID
* @retval None
*/
void W25Q64_ReadID(uint8_t *MID,uint16_t *DID)
{
MySPI_Start();
MySPI_W_R_one_Byte(JEDEC_ID);
*MID=MySPI_W_R_one_Byte(DUMMY_BYTE);
*DID=MySPI_W_R_one_Byte(DUMMY_BYTE);
*DID<<=8;
*DID|=MySPI_W_R_one_Byte(DUMMY_BYTE);
MySPI_Stop();
}
/**
* @brief 写使能
* @retval None
*/
void W25Q64_Write_Enable(void)
{
MySPI_Start();
MySPI_W_R_one_Byte(Write_Enable);
MySPI_Stop();
}
/**
* @brief 设备在擦除或写入数据是处于BUSY状态,需等待设备完成
* @retval 1:设备正常;0:设备卡死
*/
uint8_t W25Q64_Wait_Busy(void)
{
uint32_t TimeOUT=100000;
MySPI_Start();
MySPI_W_R_one_Byte(Read_Status_Register_1);
while(MySPI_W_R_one_Byte(DUMMY_BYTE)&0x01)//读取BUSY位等待Flash空闲
{
TimeOUT--;
if(TimeOUT==0)//等待时间过长认为卡死 直接退出
{
MySPI_Stop();
return 0;
}
}
MySPI_Stop();
return 1;
}
/**
* @brief 写数据(同时最多写入256Byte)
* @param1 首地址,取值范围:0X000000~~0X7FFFFF
* @param2 被写入的数据
* @param3 数据长度,单位:字节
* @retval None
*/
void W25Q64_WriteData(uint32_t BaseAddr,uint8_t *DataArr,uint8_t count)
{
W25Q64_Write_Enable();
MySPI_Start();
MySPI_W_R_one_Byte(Page_Program);
MySPI_W_R_one_Byte((uint8_t)(BaseAddr>>16));
MySPI_W_R_one_Byte((uint8_t)(BaseAddr>>8));
MySPI_W_R_one_Byte((uint8_t)BaseAddr);
for(uint8_t i=0;i<count;i++)
{
MySPI_W_R_one_Byte(DataArr[i]);
}
MySPI_Stop();
W25Q64_Wait_Busy();
}
/**
* @brief 擦除内存数据
* @param1 首地址,取值范围:0X000000~~0X7FFFFF
* @param2 擦除模式:
* 0:芯片擦除
* 1:扇区擦除(4KB)
* 2:块擦除(32KB)
* 3:块擦除(64KB)
* @retval 擦除状态:
*1:擦除成功
*0:擦除失败
*/
uint8_t W25Q64_Erase(uint32_t BaseAddr,uint8_t mode)
{
W25Q64_Write_Enable();
MySPI_Start();
switch(mode)
{
case 0:MySPI_W_R_one_Byte(Chip_Erase);break;
case 1:MySPI_W_R_one_Byte(Sector_Erase_4KB);break;
case 2:MySPI_W_R_one_Byte(Block_Erase_32KB);break;
case 3:MySPI_W_R_one_Byte(Block_Erase_64KB);break;
default:MySPI_Stop();return 0;
}
if(mode==1||mode==2||mode==3)
{
MySPI_W_R_one_Byte((BaseAddr>>16));
MySPI_W_R_one_Byte((BaseAddr>>8));
MySPI_W_R_one_Byte(BaseAddr);
}
MySPI_Stop();
W25Q64_Wait_Busy();
return 1;
}
/**
* @brief 读取数据
* @param1 首地址,取值范围:0X000000~~0X7FFFFF
* @param2 数据缓冲区
* @param2 读取长度 取值范围:0X000000~~0X7FFFFF
* @retval 读取状态:
*1:读取成功
*/
uint8_t W25Q64_ReadData(uint32_t BaseAddr,uint8_t *DataArr,uint32_t count)
{
MySPI_Start();
MySPI_W_R_one_Byte(Read_Data);
MySPI_W_R_one_Byte((uint8_t)(BaseAddr>>16));
MySPI_W_R_one_Byte((uint8_t)(BaseAddr>>8));
MySPI_W_R_one_Byte((uint8_t)BaseAddr);
for(uint32_t i=0;i<count;i++)
{
DataArr[i]=MySPI_W_R_one_Byte(DUMMY_BYTE);
}
MySPI_Stop();
return 1;
}
4.W25Q64.h
#ifndef __W25Q64_H
#define __W25Q64_H
#include "stm32f10x.h" // Device header
#include "myspi.h"
void W25Q64_Init(void);
void W25Q64_ReadID(uint8_t *MID,uint16_t *DID);
uint8_t W25Q64_Erase(uint32_t BaseAddr,uint8_t mode);
void W25Q64_WriteData(uint32_t BaseAddr,uint8_t *DataArr,uint8_t count);
uint8_t W25Q64_ReadData(uint32_t BaseAddr,uint8_t *DataArr,uint32_t count);
#define Write_Enable 0X06
#define Write_Disable 0X04
#define Read_Status_Register_1 0X05
#define Read_Status_Register_2 0X35
#define Write_Status_Register 0X01
#define Page_Program 0X02
#define Quad_Page_Program 0X32
#define Block_Erase_64KB 0XD8
#define Block_Erase_32KB 0X52
#define Sector_Erase_4KB 0X20
#define Chip_Erase 0XC7//或者0X60
#define Erase_Suspend 0X75
#define Erase_Resume 0X7A
#define Power_down 0XB9
#define High_Performance_Mode 0XA3
#define Continuous_Read_Mode_Reset 0XFF
#define Release_Power_down_or_HPM_Device_ID 0XAB
#define Manufacturer_Device_ID 0X90
#define Read Unique_ID 0X4B
#define JEDEC_ID 0X9F
#define Read_Data 0X03
#define Fast_Read 0X0B
#define Fast_Read_Dual_Output 0X3B
#define Fast_Read_Dual_IO 0XBB
#define Fast_Read_Quad_Output 0X6B
#define Fast_Read_Quad_IO 0XEB
#define Octal_Word_Read_Quad_IO 0XE3
#define DUMMY_BYTE 0XFF//无用数据
#endif
来自江科大[狗头][狗头][狗头]