项目中需要用到一片SPIFlash,我用的是SST25VF016B,用单片机自带的SPI接口几天一直没弄通,索性就直接用IO来模拟,以下是代码,也欢迎用SPI接口弄通的兄弟指教。#include "hc32_ddl.h"
#define uchar unsigned char
#define uint unsigned int
#define ulong unsigned long
///////////引脚定义
#define SPI_CLK_Port (PortC)
#define SPI_CLK_Pin (Pin03)
#define SPI_MISO_Port (PortC)
#define SPI_MISO_Pin (Pin02)
#define SPI_MISI_Port (PortC)
#define SPI_MISI_Pin (Pin01)
#define SPI_CS_Port (PortC)
#define SPI_CS_Pin (Pin00)
#define SPI_WR_Port (PortC)
#define SPI_WR_Pin (Pin15)
char dat[10]={1,2,3,4,5,6,7,8,9,1};
char add[3]={1,0,1};
char R_dat[10];
char num;
void Flash_init() ; /* 程序功能: 用来将时钟线初始化为低. 必须在将设备设置为模式0之前调用*/
void Flash_WRSR(uchar byte) ;//写状态寄存器
uchar Flash_Read_Status_Register(void); //读状态寄存器的值
void Flash_WREN_Check(void) ; /* 功能: 检查擦写操作前WEL位是否为1 */
void Flash_WREN(void) ; //写使能命令
void Flash_Sector_Erase(ulong Dst) ; /* 功能: Sector Erases the Chip. 4K */
void Flash_Wait_Busy(void) ;//等待 FLASH空闲
void Flash_Chip_Erase(void) ; /* 功能: 擦除整个芯片 */
void Flash_Block_Erase_32K(ulong Dst) ; /* 功能: Block Erases 32 KByte of the Chip. */
void Flash_Block_Erase_64K(ulong Dst) ;
void Flash_EWSR(void) ; //;使能改写状态寄存器
void Flash_WRDI(void) ;// 禁止写使能
void Flash_Send_Byte(uchar dat) ;//发送一个数据char 型 的 从51到FLASH
uchar Flash_Get_Byte(void);// 接收一个char型的数据 51接收
uchar Flash_Read(ulong Dst);//读取一个措定地址内的一个数据 作为函数返回值
void Flash_Write(ulong Dst,uchar dat); //向flash 内的一个地址内写入一个数据
void Flash_Write_data(uchar add[],uchar dat[],uchar size); //向flash 内的一个基地址 add[3],add[0]放地址高八位 内写入size个数据。
//向从flash 内的一个基地址 add[3],add[0]放地址高八位 内读出size个数据。 放到dat[]中
void Flash_Read_data(uchar add[],uchar R_dat[],uchar size);
//向从flash 内的一个基地址 add, 内读出size个数据。 放到dat[]中
void Flash_Read_data_add(ulong Dst,uchar R_dat[],uchar size);
void Flash_Write_data_add(ulong Dst,uchar dat[],uchar size);//向flash 内的一个基地址 add
////////////////////////////////////SPI读写驱动////////////////////////////////////////////////////////////////////////////////
void Flash_Send_Byte(uchar dat) //发送一个数据char 型 的 从51到FLASH
{
uchar i;
PORT_ResetBits(SPI_CLK_Port,SPI_CLK_Pin);
PORT_ResetBits(SPI_CS_Port,SPI_CS_Pin);
for(i=0;i<8;i++)
{
if(dat & 0x80)
{
PORT_SetBits(SPI_MISI_Port,SPI_MISI_Pin);
}
else
PORT_ResetBits(SPI_MISI_Port,SPI_MISI_Pin);
dat<<=1;
PORT_SetBits(SPI_CLK_Port,SPI_CLK_Pin); //信号拉高读进数据
Ddl_Delay1us(1);
PORT_ResetBits(SPI_CLK_Port,SPI_CLK_Pin); //将信号拉低
Ddl_Delay1us(1) ;
}
PORT_ResetBits(SPI_CLK_Port,SPI_CLK_Pin);
}
uchar Flash_Get_Byte(void) //接收一个char型的数据
{
uchar i;
uchar one_data=0;
PORT_ResetBits(SPI_CS_Port,SPI_CS_Pin);
// PORT_SetBits(SPI_CLK_Port,SPI_CLK_Pin;
for(i=0;i<8;i++)
{
one_data=one_data<<1;
PORT_ResetBits(SPI_CLK_Port,SPI_CLK_Pin);
Ddl_Delay1us(1);
Ddl_Delay1us(1);
if(PORT_GetBit(SPI_MISO_Port,SPI_MISO_Pin)==1)
{
one_data=one_data | 0x01;
}
PORT_SetBits(SPI_CLK_Port,SPI_CLK_Pin);
Ddl_Delay1us(1) ;
}
PORT_ResetBits(SPI_CLK_Port,SPI_CLK_Pin);
//CS=1;
return one_data;
}
/************************************************************************/
/* 名称: Read */
/* 功能: 读取一个地址内一个字节的数据.返回读取的数据*/
/* 输入: Dst: Destination Address 000000H - 1FFFFFH */
/* 返回: byte */
/************************************************************************/
uchar Flash_Read(ulong Dst)
{
uchar byte = 0;
PORT_SetBits(SPI_CLK_Port,SPI_CLK_Pin);
PORT_ResetBits(SPI_CS_Port,SPI_CS_Pin);
/* enable device */
Flash_Send_Byte(0x03); /* read command */
Flash_Send_Byte(((Dst & 0xFFFFFF) >> 16)); /* send 3 address bytes */
Flash_Send_Byte(((Dst & 0xFFFF) >> 8));
Flash_Send_Byte(Dst & 0xFF);
byte = Flash_Get_Byte();
PORT_SetBits(SPI_CS_Port,SPI_CS_Pin); /* disable device */
return byte; /* return one byte read */
}
////////////////////////////////////////////////////////////////////////////////////////////////
void Flash_Write(ulong Dst,uchar dat) //向flash 内的一个地址内写入一个数据。
{
PORT_ResetBits(SPI_CS_Port,SPI_CS_Pin);
Flash_Send_Byte(0x02); /* read command */
Flash_Send_Byte(((Dst & 0xFFFFFF) >> 16)); /* send 3 address bytes */
Flash_Send_Byte(((Dst & 0xFFFF) >> 8));
Flash_Send_Byte(Dst & 0xFF);
Flash_Send_Byte(dat);///secd data to flash
PORT_SetBits(SPI_CS_Port,SPI_CS_Pin);
}
void Flash_Write_data(uchar add[],uchar dat[],uchar size) //向flash 内的一个基地址 add[3],add[0]放地址高八位 内写入size个数据。
{
uchar i;
ulong Dst=0;
for(i=0;i<2;i++)
{
Dst|=add[i];
Dst=Dst<<8;
}
Dst|=add[2];
for(i=0;i<size;i++)
{
Flash_WREN();
PORT_ResetBits(SPI_CS_Port,SPI_CS_Pin) ;
Flash_Send_Byte(0x02); /* read command */
Flash_Send_Byte(((Dst & 0xFFFFFF) >> 16)); /* send 3 address bytes */
Flash_Send_Byte(((Dst & 0xFFFF) >> 8));
Flash_Send_Byte(Dst & 0xFF);
Flash_Send_Byte(dat[i]);///secd data to flash
Dst++;
PORT_SetBits(SPI_CS_Port,SPI_CS_Pin);
Flash_WRDI();
}
//CS=1;
}
//向从flash 内的一个基地址 add[3],add[0]放地址高八位 内读出size个数据。 放到dat[]中
void Flash_Read_data(uchar add[],uchar R_dat[],uchar size)
{
uchar i;
PORT_ResetBits(SPI_CS_Port,SPI_CS_Pin);
Flash_Send_Byte(0x03); /* read command */
for(i=0;i<3;i++)
{
Flash_Send_Byte(add[i]);
}
for(i=0;i<size;i++)
{
R_dat[i]=Flash_Get_Byte(); ///secd data to flash
}
PORT_SetBits(SPI_CS_Port,SPI_CS_Pin);
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void Flash_init() /* 程序功能: 用来将时钟线初始化为低. 必须在将设备设置为模式0之前调用*/
{
stc_port_init_t stcPortInit;
/* configuration structure initialization */
MEM_ZERO_STRUCT(stcPortInit);
stcPortInit.enPinMode = Pin_Mode_Out;
stcPortInit.enExInt = Enable;
stcPortInit.enPullUp = Enable;
PORT_Init(SPI_CLK_Port, SPI_CLK_Pin, &stcPortInit);
PORT_Init(SPI_MISI_Port, SPI_MISI_Pin, &stcPortInit);
PORT_Init(SPI_CS_Port, SPI_CS_Pin, &stcPortInit);
PORT_Init(SPI_WR_Port, SPI_WR_Pin, &stcPortInit);
stc_port_init_t stcPortInit_in;
/* configuration structure initialization */
MEM_ZERO_STRUCT(stcPortInit_in);
stcPortInit_in.enPinMode = Pin_Mode_In;
stcPortInit_in.enExInt = Enable;
stcPortInit_in.enPullUp = Enable;
PORT_Init(SPI_MISO_Port, SPI_MISO_Pin, &stcPortInit_in);
char i;
// P7 |= 0x7f; /* 设置SCK为低电平初始化状态 */
PORT_ResetBits(SPI_CLK_Port,SPI_CLK_Pin);
for(i=255;i>0;i--);
// P7 &= 0x80;
PORT_SetBits(SPI_CLK_Port,SPI_CLK_Pin);
}
void Flash_WREN_Check(void) /* 功能: 检查擦写操作前WEL位是否为1 */
{
uchar byte;
byte = Flash_Read_Status_Register(); /* 读取状态register */
if ((byte&0x02) != 0x02) /* 检查WEL位置位 */
{
Flash_WREN();
//如果未置1进行相应处理,如对其进行写使得操作
}
}
void Flash_Chip_Erase(void) /* 功能: 擦除整个芯片 */
{
Flash_EWSR();
Flash_WRSR(0);//(Read_Status_Register())&0x83 );
Flash_WREN_Check();
PORT_ResetBits(SPI_CS_Port,SPI_CS_Pin);
Flash_Send_Byte(0xc7); /* 发送 Chip Erase命令 (60h or C7h) */
PORT_SetBits(SPI_CS_Port,SPI_CS_Pin);
Flash_Wait_Busy();
//CE =1;
}
void Flash_Sector_Erase(ulong Dst) /* 功能: Sector Erases the Chip. 4K */
{
uchar i;
Flash_WREN_Check();
Flash_init();
PORT_ResetBits(SPI_CS_Port,SPI_CS_Pin);
Flash_Send_Byte(0x20); /* 发送Sector Erase 命令 */
Flash_Send_Byte(((Dst & 0xFFFFFF) >> 16)); /* 发送地址 */
Flash_Send_Byte(((Dst & 0xFFFF) >> 8));
Flash_Send_Byte(Dst & 0xFF);
for(i=100;i>0;i--);
PORT_SetBits(SPI_CS_Port,SPI_CS_Pin);
Flash_Wait_Busy();
// CS=1;
}
|
|