当前位置:首页 >> 信息与通信 >>

SPI读写flash程序


SPI读写程序修正版(SST25Vf010芯片flash可用)默认分类 2010-08-22 23:27:26 阅读95 评论0 字号:大中小 订阅 .

一、经过大约3周的时间终于搞定flash芯片SST25Vf010读写问题,为了便于使用,进行了大修改,分享如下,主要函数,可以定义为SPI_Init.c,内容:

#incl

ude <c8051f020.h> // SFR declarations
#include <stdio.h>
#include<intrins.h>
#include "model_spi.h" //自定义的头文件,包含了下列函数声明,在下面有定义
void SendSPIByte(unsigned char SPI_byte)
{
uchar SPI_count;
for(SPI_count = 8;SPI_count > 0;SPI_count--)
{
// _nop_();_nop_();
SPICLK = 0;
if(SPI_byte&0x80)
SPIMOSI = 1;
else
SPIMOSI = 0;
// _nop_();_nop_();
// _nop_();_nop_();
// _nop_();_nop_();
SPICLK = 1;
SPI_byte<<=1;
// _nop_();_nop_();
}
}

unsigned char GetSPIByte(void)
{
uchar SPI_count;
unsigned char SPI_byte;
for(SPI_count = 8;SPI_count > 0;SPI_count--)
{
SPICLK = 0;
_nop_();_nop_();
_nop_();_nop_();
SPICLK = 1;
_nop_();_nop_();
_nop_();_nop_();
SPI_byte<<=1;
SPI_byte |= SPIMISO;
_nop_();_nop_();

}
return SPI_byte;
}

unsigned char GetSPIByte2(void)
{
uchar SPI_count;
unsigned char SPI_byte;
for(SPI_count = 8;SPI_count > 0;SPI_count--)
{
SPICLK = 0;
_nop_();_nop_();
_nop_();_nop_();
SPI_byte<<=1;
SPI_byte |= SPIMISO;
SPICLK = 1;
_nop_();_nop_();
_nop_();_nop_();
_nop_();_nop_();

}
return SPI_byte;
}

/************************************************************************/
/* 名称: Wait_Busy */
/* 功能: 等待芯片空闲(在执行Byte-Program, Sector-Erase, Block-Erase, Chip-Erase操作后)*/
/* 输入: None */
/* 返回: Nothing */
/************************************************************************/
void Wait_Busy()
{
while ((Read_State_Register())&0x01 == 0x01); /* waste time until not busy */
// Read_State_Register();
}
//读Flash
void FlashRead(unsigned long star_addr,unsigned int len, unsigned char *buffer) //从缓冲区1的指定位置(0-263)中读入指定字节
{
unsigned int i;
DF_CHIP_SELECT;
// _nop_();_nop_(); // enable DataFlash
SendSPIByte(FLASH_READ); //Flash 读命令0x03
SendSPIByte((unsigned char)(star_addr>>16));
SendSPIByte((unsigned char)(star_addr>>8));
SendSPIByte((unsigned char)star_addr);
for (i=0;i<len;i++)
{
buffer[i] = GetSPIByte(); // read data from SPI
}
// byte = GetSPIByte();
// byte = GetSPIByte2();
_nop_();
DF_CHIP_NOSELECT;
// _nop_();_nop_();_nop_(); _nop_();
}

uchar FlashRead_BYTE(unsigned long star_addr)
{
// unsigned int i;
uchar byte;
DF_CHIP_SELECT;
// _nop_();_nop_(); // enable DataFlash
SendSPIByte(FLASH_READ); //Flash 读命令0x03
SendSPIByte((unsigned char)(star_addr>>16));
SendSPIByte((unsigned char)(star_addr>>8));
SendSPIByte((unsigned char)star_addr);
byte = GetSPIByte(); // read data from SPI
// byte = GetSPIByte();
// byte = GetSPIByte2();
_nop_();
DF_CHIP_NOSELECT;
return(byte);
// _nop_();_nop_();_nop_(); _nop_();
}
//读状态寄存器
unsigned char Read_State_Register(void)
{
unsigned char Read_date;
DF_CHIP_SELECT;
_nop_();_nop_();
SendSPIByte(0x05); //写使能命令
Read_date = GetSPIByte();
_nop_();
DF_CHIP_NOSELECT;
_nop_();_nop_();_nop_();_nop_();
return(Read_date);
}
/************************************************************************/
/* 名称: WREN_Check */
/* 功能: 检查擦写操作前WEL位是否为1 */
/* 输入: None */
/* 返回: Nothing */
/************************************************************************/
void WREN_Check()
{
uchar byte;
byte = Read_State_Register(); /* 读取状态register */
if ((byte&0x02) != 0x02) /* 检查WEL位置位 */
{
Write_EN();
//如果未置1进行相应处理,如对其进行写使得操作
}
}
//写使能信号
void Write_EN(void) //
{
// DF_RDY_BUSY; // check if flash is busy
DF_CHIP_SELECT;
_nop_();_nop_(); //80ns
SendSPIByte(0x06); //写使能命令
_nop_();_nop_();
DF_CHIP_NOSELECT;
}
//写使能禁止
void Write_DISABLE(void) //
{
// DF_RDY_BUSY; // check if flash is busy
DF_CHIP_SELECT;
_nop_();_nop_();
SendSPIByte(0x04); //写使能禁止
_nop_();
DF_CHIP_NOSELECT;
}
//使能状态寄存器写
void State_Register_WR_EN(void)
{
// DF_RDY_BUSY; // check if flash is busy
DF_CHIP_SELECT;
_nop_();_nop_();
SendSPIByte(0x50); //写使能命令
DF_CHIP_NOSELECT;
}
//写状态寄存器
void State_Register_WR(void)
{
// DF_RDY_BUSY; // check if flash is busy
DF_CHIP_SELECT;
SendSPIByte(0x01); //写使能命令
SendSPIByte(0x00); //State_register的内容
_nop_();
DF_CHIP_NOSELECT;
_nop_(); _nop_();_nop_();_nop_();
}
//写字节到Flash
void FlashWrite_BYTE(unsigned long start_addr, unsigned char date) //向缓冲区1的指定位置(0-263)写入指定字节
{
// char byte;
// DF_RDY_BUSY; // check if flash is busy
//WREN_Check();
Write_EN();
// byte = Read_State_Register();
// putchar(byte);
DF_CHIP_SELECT; // CE
// _nop_();_nop_();
SendSPIByte(FLASH_WRITE_BYTE);
SendSPIByte((unsigned char)(start_addr>>16));
SendSPIByte((unsigned char)(start_addr>>8));
SendSPIByte((unsigned char)start_addr);
SendSPIByte(date);
DF_CHIP_NOSELECT;
//Wait_Busy();
}
//写连续字节
void FlashWrite_Auto_BYTE(unsigned long start_addr, unsigned int len,unsigned char *buffer)
{
unsigned long temp2 = 0;
xdata unsigned int i = 0;
temp2 = start_addr + len;
for(;start_addr < temp2;start_addr ++)
{
FlashWrite_BYTE(start_addr,buffer[i]);
i++;
delay(5000);
}
}
//写连续字节到Flash
void FlashWrite_AutoIncrement_BYTE(unsigned long start_addr, unsigned int len,unsigned char *buffer) //向缓冲区1的指定位置(0-263)写入指定字节
{
char State_Register;
unsigned char i;
Write_EN();
DF_CHIP_SELECT;
_nop_();_nop_();
SendSPIByte(AUTOINCREMENT_BYTE);
SendSPIByte((unsigned char)(start_addr>>16));
SendSPIByte((unsigned char)(start_addr>>8));
SendSPIByte((unsigned char)start_addr);
SendSPIByte(buffer[0]);
DF_CHIP_NOSELECT;
delay(5000);
for (i=1;i<len;i++)
{

DF_CHIP_SELECT;
SendSPIByte(AUTOINCREMENT_BYTE);
SendSPIByte(buffer[i]);
DF_CHIP_NOSELECT;
delay(5000);
}
Write_DISABLE();
State_Register = Read_State_Register();
// putchar(State_Register);
_nop_();
}
//Sector_Erease 4K字节擦除
void Sector_Erease(unsigned long start_addr)
{
// DF_RDY_BUSY; // check if flash is busy
Write_EN();
DF_CHIP_SELECT;
_nop_();_nop_();
SendSPIByte(SECTOR_EREASE); //写使能命令
SendSPIByte((unsigned char)(start_addr>>16));
SendSPIByte((unsigned char)(start_addr>>8));
SendSPIByte((unsigned char)start_addr);
_nop_();
DF_CHIP_NOSELECT;
_nop_();
}
//块擦除 32K字节擦除
void Block_Erease(unsigned long start_addr)
{
// DF_RDY_BUSY; // check if flash is busy
Write_EN();
DF_CHIP_SELECT;
_nop_();_nop_();
SendSPIByte(BLOCK_EREASE); //写使能命令
SendSPIByte((unsigned char)(start_addr>>16));
SendSPIByte((unsigned char)(start_addr>>8));
SendSPIByte((unsigned char)start_addr);
_nop_();
DF_CHIP_NOSELECT;
_nop_(); _nop_();_nop_();_nop_();
}
//芯片擦除
void Chip_Erease(void)
{
// DF_RDY_BUSY; // check if flash is busy
DF_CHIP_SELECT;
// WREN_Check();
Write_EN();
DF_CHIP_SELECT;
_nop_();_nop_();
SendSPIByte(CHIP_EREASE); //写使能命令
_nop_();_nop_();
DF_CHIP_NOSELECT;
// Wait_Busy();
}
//芯片ID读取
unsigned long Flash_Read_ID(void)
{
unsigned long Manufact_ID1 = 0,Product_ID1 = 0,Manufact_ID2 = 0,Product_ID2 = 0;
unsigned long Chip_ID;
// DF_RDY_BUSY; // check if flash is busy
DF_CHIP_SELECT;
_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();
SendSPIByte(READ_ID); //写使能命令
SendSPIByte(0x00);
SendSPIByte(0x00);
SendSPIByte(0x01); //0x00则先得到生厂商ID,0x01则先得到产品ID
Manufact_ID1 = GetSPIByte();
Product_ID1 = GetSPIByte();
Manufact_ID2 = GetSPIByte();
Product_ID2 = GetSPIByte();
DF_CHIP_NOSELECT;
Chip_ID = Manufact_ID1 << 24 | Product_ID1<< 16 | Manufact_ID2 << 8 | Product_ID2;
return(Chip_ID);
}

//系统初始化函数

void SYSCLK_Init (void)
{
hold_1();
wp_1();
WDTCN = 0xde; // disable watchdog timer
WDTCN = 0xad;
OSCXCN = 0x67;
while(OSCXCN & 0x80 ==0);
OSCICN |= 0x08;
}

//端口初始化函数

void PORT_Init (void)
{
XBR0=0x04; //spi and uart enable
XBR1=0x00; //INT0 and INT1 disenable
XBR2=0x46; // 弱上拉要设置 要不然产生不了中断。
// EMI0CN=0x00; //
// EMI0CF=0x1c; //
// EMI0TC=0xff; //
P2MDOUT=0xff;
P1MDOUT=0xfB;
P0MDOUT|=0xff;
// SPIMISO = 1;
P2=0xff;
}

//串口初始化函数

void SerialInit()
{
#ifdef _UART0_
SCON0 = 0x52;
CKCON |= 0x10;
PCON |= 0x80;
#endif
#ifdef _UART1_
SCON1 = 0x52;
// CKCON |= 0x10;
PCON |= 0x10;
#endif
#ifdef _UART_
SCON = 0x52;
PCON |= 0x80;
#endif
TMOD &= 0x0F;
TMOD |= 0x20;
TL1 = TH1 = 0xF3;
TR1 = 1;
}

/*
* putchar (mini version): outputs charcter only
*/

//串口输出字符函数
char putchar (char c) {
#ifdef _UART0_
while (!TI0);
TI0 = 0;
SBUF0 = c;
#endif
#ifdef _UART1_
while ((SCON1&0x02)==0);
SCON1 &= 0xFD;
SBUF1 = c;
#endif
#ifdef _UART_
while (!TI);
TI = 0;
SBUF = c;
#endif
return c;
}

char _getkey () {
char c;

#ifdef _UART0_
while (!RI0);
c = SBUF0;
RI0 = 0;
#endif
#ifdef _UART1_
while ((SCON1&0x01)==0);
c = SBUF1;
SCON1 &= 0xFE;
#endif
#ifdef _UART_
while (!RI);
c = SBUF;
RI = 0;
#endif

return (c);
}

void delay(unsigned long i){while(i--);}



二、头文件model_spi.h,其中定义了一些端口,能静下心来的同志应该能看懂,内容如下:

#ifndef __MODEL_SPI__
#define __MODEL_SPI__
#include <C8051F020.H>
#define uchar unsigned char
#define uint unsigned int
//sbit P37 = P3^7;
#define SYSCLK 11059200
//#define DF_RESET P2 &= ~(0x1); P2 |= 0x1; // P50 DataFlash reset port pin (P20)
//#define DF_RDY_BUSY P1|=0x80;// while(!(P3&0x80)); //P37 DataFlash rea
#define DF_CHIP_SELECT P1 &= 0xf7; // P53 DataFlash chip select port pin (P23) WE引脚为P2^3
#define DF_CHIP_NOSELECT P1 |= 0x08; // P53 DataFlash chip select port pin (P23)
#define FLASH_READ 0x03 // Flash read
#define FLASH_WRITE_BYTE 0x02 // Flash Write
#define AUTOINCREMENT_BYTE 0xAF
#define SECTOR_EREASE 0x20
#define BLOCK_EREASE 0x52
#define CHIP_EREASE 0x60
#define READ_ID 0x90
#define RXBUFSIZE 128

#define _UART1_
//#define _UART0_
//#define _UART_

#define hold_0() //P2&=0xfe //HOLD 为P2^0
#define hold_1() //P2|=0x01
#define wp_0() //P2&=0xFD //WP 为P2^1
#define wp_1() //P2|=0x02
sbit SPICLK = P1^0;
sbit SPIMISO = P1^2; //主入 应置漏极开路
sbit SPIMOSI = P1^1; //主出 应置推挽输出
sbit SPIMSS = P1^3;

extern unsigned char ErrFlag;
extern bit RxFlag,StFlag,TxFlag;
extern unsigned char idata RxBuf[];
extern uchar Manufact_ID,Product_ID;

extern void SerialInit();
extern char putchar (char c);
extern char GetPack(unsigned char buf[],char bufsize);

extern void PORT_Init (void);
extern void SYSCLK_Init (void);
extern void SendSPIByte(unsigned char SPI_byte);
extern uchar GetSPIByte(void);
extern void FlashRead(unsigned long star_addr,unsigned int len, unsigned char *buffer);
extern uchar FlashRead_BYTE(unsigned long star_addr);
extern unsigned char Read_State_Register(void);
extern void Write_EN(void);
extern void Write_DISABLE(void);
extern void State_Register_WR_EN(void);
extern void State_Register_WR(void) ;
extern void FlashWrite_BYTE(unsigned long start_addr, unsigned char date); //向缓冲区1的指定位置(0-263)写入指定字节
extern void FlashWrite_Auto_BYTE(unsigned long start_addr, unsigned int len,unsigned char *buffer);
extern void FlashWrite_AutoIncrement_BYTE(unsigned long start_addr, unsigned int len,unsigned char *buffer); //向缓冲区1的指定位置(0-263)写入指定字节
extern void Sector_Erease(unsigned long start_addr);
extern void Block_Erease(unsigned long start_addr);
extern void Chip_Erease(void);
extern unsigned int Read_ID(void);
extern void SerialInit();
extern char putchar (char);
extern void Init(void);
extern unsigned long Flash_Read_ID(void);
extern unsigned long Test_Read_ID(void);
extern void WREN_Check(void);
extern void delay(unsigned long i);
#endif



三、主函数例子,定义为SPI_WR.c,内容如下:

#include <c8051f020.h> // SFR declarations
#include <stdio.h>
#include<intrins.h>
#include "model_spi.h"
unsigned char MyBuff[16];

void main (void)
{
xdata unsigned int i;
xdata unsigned int j;
char temp1,temp2;
char status;
SYSCLK_Init (); // initialize oscillator
PORT_Init (); // initialize crossbar and GPIO
SerialInit();
Chip_Erease(); //整片擦除
delay(50000);
State_Register_WR_EN(); //状态寄存器改变使能
State_Register_WR(); //状态寄存器改变为可写状态,这两个步骤必备,不然写不进去
delay(3000);
for (j = 0;j < 16;j ++ )
{
MyBuff[j]=j;
FlashWrite_BYTE(j*2,MyBuff[j]);
delay(100);
FlashWrite_BYTE(j*2+1,(MyBuff[j]+1));
delay(100);
}
while(1)
{
status = Read_State_Register();
putchar(status);
for(i = 0;i < 16;i ++)
{
temp1 = FlashRead_BYTE(i*2);
delay(100);
temp2 = FlashRead_BYTE(i*2+1);
delay(100);
putchar(temp1);
putchar(temp2);
}
delay(5000);
}
}

注意:State_Register_WR_EN(); 和State_Register_WR();状态寄存器必须改变为可写状态,这两个步骤必备,不然写不进去

相关文章:
CC2530的FLASH读写程序
CC2530的FLASH读写程序_计算机硬件及网络_IT/计算机_专业资料。#include <ioCC...ID FLASH_SPI_RX(ID[1]); FLASH_SPI_RX(ID[2]); FLASH_SPI_END(); ...
spi_flash (stm32 spi_flash的编程)
(); } //读取 SPI_FLASH 的状态寄存器 //BIT7 6 //SPR 5 4 3 2 1 ...2.我在写程序的时候犯了个很低级的失误,在写乘法时用了 2i 结果一直提示有...
基于C8051F340的Flash读写设计
完成程序设计后经过 调试,实验结果表明该设计能够实现 FLASH读写并通过串口助手成功显示。 关键词:C8051F340;SPI;UART;FLASH Abstract: In the electronic ...
IMPACT SPI FLASH 烧写流程
IMPACT SPI FLASH 烧写流程_计算机硬件及网络_IT/计算机_专业资料。Xilinx SPI FLASH 的烧写方法 1、首先在 ISE 中打开要烧写的工程,然后如图双击打开烧写工具。 ...
spi flash连接原理
spi flash连接原理_信息与通信_工程科技_专业资料。spi flash连接原理今日推荐 90份文档 2014年执业医师资格考试 口腔执业医师实践技能复习资料 中医护理学基础重点 执...
SPI flash OTP 软件保护方法
SPI flash OTP 软件保护方法_IT/计算机_专业资料。SPI flash OTP 软件保护方法...然后解密,把解密获得的ID跟从flash读到的unique ID作比较,如果相同程序继续运行...
SPI接口的模组Flash解决方案
SPI接口的模组Flash解决方案_计算机软件及应用_IT/计算机_专业资料。模组Flash是...212SPI接口flash存储器A... 17页 免费 SPI读写flash程序 5页 2下载券 SPI...
模拟SPI程序
模拟SPI程序_信息与通信_工程科技_专业资料。用stm32的GPIO口模拟SPI时序控制FLASH芯片W25X80读写擦除 写程序: void SPIx_WriteByte(u8 TxData) { u8 j=0; ...
AT45db081的spi读写程序
SendSPIByte(0); for (i=0;i<len;i++) { buffer = GetSPIByte(); // read data from SPI } DF_CHIP_NOSELECT; } //启用缓存 2 读 void Flash...
atlys开发板之SPI FLASH实验
下面我们来编写 SPI FLASH 的测试程序。 我们先来编写hello.flash.c的程序代码。在这个程序里完成对SPI Flash的擦 除,编程和读取验证。如果读取的数据和编程的...
更多相关标签:
spi flash读写 | spi flash读写原理 | spi flash读写速度 | spi flash读写verilog | quad spi读写flash | fpga读写spi flash | 模拟spi读写程序 | spi读写程序 |