现在串行SPI接口的FLASH,许多厂商都在生产,一般用于扩展储存程序,读写的速度一般可达30多M,快的有50多M。本例讲一个使用Mega8的IO口模拟SPI读写Spansion生产的串行FLASH芯片(s25fl004a),大小为4Mbit,即是512K字节。想要PDFDATASHEET的朋友可以去21IC下。
程序如下:
/***************************************************
flash.h
***************************************************/
#ifndef _flash_
#define _flassh_
#define SI 4
#define SO 3
#define SCLK 5
#define CS 2
#define WP 1
#define PORT1 PORTB
#define PIN1 PINB
#define DDR1 DDRB
#define SO_0 PORT1&=~(1<#define SO_1 PORT1|=(1<#define SCLK_0 PORT1&=~(1<#define SCLK_1 PORT1|=(1<#define CS_0 PORT1&=~(1<#define CS_1 PORT1|=(1<#define WP_0 PORT1&=~(1<#define WP_1 PORT1|=(1<#define in_SI ((1<
uint8 Read_abyte(uint32 address);
void Write_adata(uint32 address,uint8 write_data);
void WriteEN(void);
uint8 Read_RDSR(void);
void WriteDisable(void);
void Sector_Erase(uint32 address);
void Write_string(uint8 *string,uint32 address,uint8 n);
void Bulk_Erase(void);
void DelayX100ms(uint32 x);
#endif
/*********************************************
flash.c
***********************************************/
#include
#include "mytype.h"
#include "flash.h"
/***************************************************************************************
读取一个字节
*****************************************************************************************/
uint8 Read_abyte(uint32 address)
{
uint8 i;
uint8 read_data;
uint8 command;
command=0x03;//读取数据命令。
while((Read_RDSR())&0x01);//等待空闲。
CS_1;
SCLK_1;
CS_0;
SCLK_0;
for(i=0;i<8;i++)//写入命令。
{
SCLK_0;
if(0x80&command)//高位优先。
SO_1;
else
SO_0;
SCLK_1;
command<<=1;
}
for(i=0;i<24;i++)//写入24位读取地址值。
{
SCLK_0;
if(0x00800000&address)
SO_1;
else
SO_0;
SCLK_1;
address<<=1;
}
SO_0;
for(i=0;i<8;i++)//读取数据值。
{
SCLK_0;
;;
SCLK_1;
read_data<<=1;
if(in_SI)
read_data++;
}
SCLK_0;
CS_1;
return(read_data);
}
/***************************************************************************************
写入一个字节
*****************************************************************************************/
void Write_adata(uint32 address,uint8 write_data)
{
uint8 i;
uint8 command;
while((Read_RDSR())&0x01);
WriteEN();
command=0x02;
CS_1;
SCLK_1;
CS_0;
SCLK_0;
for(i=0;i<8;i++)
{
SCLK_0;
if(0x80&command)
SO_1;
else
SO_0;
SCLK_1;
command<<=1;
}
for(i=0;i<24;i++)
{
SCLK_0;
if(0x00800000&address)
SO_1;
else
SO_0;
SCLK_1;
address<<=1;
}
for(i=0;i<8;i++)
{
SCLK_0;
if(0x80&write_data)
SO_1;
else
SO_0;
SCLK_1;
write_data<<=1;
}
SCLK_0;
CS_1;
}
/***************************************************************************************
写入写使能命令
*****************************************************************************************/
void WriteEN(void)
{
uint8 i;
uint8 command;
command=0x06;//使能命令。
CS_1;
SCLK_1;
CS_0;
for(i=0;i<8;i++)//写入命令。
{
SCLK_0;
if(0x80&command)
SO_1;
else
SO_0;
SCLK_1;
command<<=1;
}
SCLK_0;
CS_1;
}
/***************************************************************************************
写入写禁止命令
*****************************************************************************************/
void WriteDisable(void)
{
uint8 i;
uint8 command;
command=0x04;//写入禁止命令。
CS_1;
SCLK_1;
CS_0;
SCLK_0;
for(i=0;i<8;i++)//写入命令。
{
SCLK_0;
if(0x80&command)
SO_1;
else
SO_0;
SCLK_1;
command<<=1;
}
SCLK_0;
CS_1;
}
/***************************************************************************************
写入段擦除使能命令
*****************************************************************************************/
void Sector_Erase(uint32 address)
{
uint8 i;
uint8 command;
WriteEN();
while((Read_RDSR())&0x01);
command=0xd8;//段擦除命令。
CS_1;
SCLK_1;
CS_0;
SCLK_0;
for(i=0;i<8;i++)
{
SCLK_0;
if(0x80&command)
SO_1;
else
SO_0;
SCLK_1;
command<<=1;
}
for(i=0;i<24;i++)
{
SCLK_0;
if(0x00800000&address)
SO_1;
else
SO_0;
SCLK_1;
address<<=1;
}
SCLK_0;
CS_1;
}
/***************************************************************************************
写入片擦除使能命令
*****************************************************************************************/
void Bulk_Erase(void)
{
uint8 i;
uint8 command;
command=0xc7;//片擦除命令。
while((Read_RDSR())&0x01);
WriteEN();
CS_1;
SCLK_1;
CS_0;
for(i=0;i<8;i++)
{
SCLK_0;
if(0x80&command)
SO_1;
else
SO_0;
SCLK_1;
command<<=1;
}
SO_0;
SCLK_0;
CS_1;
}
/***************************************************************************************
延时X/100ms
*****************************************************************************************/
void DelayX100ms(uint32 x)
{
uint32 i;
while(x--)
{
i="1275";
while(i--);
}
}
/***************************************************************************************
读取状态寄存器。
*****************************************************************************************/
uint8 Read_RDSR(void)
{
uint8 i,j;
uint8 read_data;
uint8 command;
command=0x05;
j=3;
CS_1;
SCLK_1;
CS_0;
SCLK_0;
for(i=0;i<8;i++)
{
SCLK_0;
if(0x80&command)
SO_1;
else
SO_0;
SCLK_1;
command<<=1;
}
SO_0;
for(i=0;i<8;i++)
{
SCLK_0;
j=0;
SCLK_1;
read_data<<=1;
if(in_SI)
read_data++;
}
SCLK_0;
CS_1;
return(read_data);
}
/**************************************************************
写入一串字节,芯片最多支持写入256个字节。
****************************************************************/
void Write_string(uint8 *string,uint32 address,uint8 n)
{
uint8 i;
uint8 command;
while((Read_RDSR())&0x01);
WriteEN();
command=0x02;
CS_1;
SCLK_1;
CS_0;
SCLK_0;
for(i=0;i<8;i++)
{
SCLK_0;
if(0x80&command)
SO_1;
else
SO_0;
SCLK_1;
command<<=1;
}
for(i=0;i<24;i++)
{
SCLK_0;
if(0x00800000&address)
SO_1;
else
SO_0;
SCLK_1;
address<<=1;
}
while(n--)
{
for(i=0;i<8;i++)
{
SCLK_0;
if(0x80&(*string))
SO_1;
else
SO_0;
SCLK_1;
(*string)<<=1;
}
string++;
}
SCLK_0;
CS_1;
}
/**************************************************************
写保护
****************************************************************/
void Write_Protect()
{
uint8 i;
uint8 command;
uint8 write_data;
while((Read_RDSR())&0x01);
WriteEN();
command=0x01;
write_data=0x9c;
CS_1;
SCLK_1;
CS_0;
SCLK_0;
for(i=0;i<8;i++)
{
SCLK_0;
if(0x80&command)
SO_1;
else
SO_0;
SCLK_1;
command<<=1;
}
for(i=0;i<8;i++)
{
SCLK_0;
if(0x80&write_data)
SO_1;
else
SO_0;
SCLK_1;
write_data<<=1;
}
SCLK_0;
CS_1;
}
/****************************************************
main.c
********************************************************/
#include
#include "mytype.h"
#include "uart.h"
#include "flash.h"
uint8 table[16]={"0123456789abcdef"};
void DelayXms(unsigned int x)//延迟xms
{
unsigned int m;
while(x--)
{
m="1275";
while(m--);
}
}
void main(void)
{
uint8 i;
uint8 j;
uint8 string[25]={0};
DDR1=((1<Uart_init();//串口初始化。
WP_1;//屏蔽写保护。
Sector_Erase(0x00000005);//擦除第一段。
Write_adata(0x00000000,0xaa);//向地址0x000000写入0xaa
Write_adata(0x0000000f,0xbb);//向地址0x00000f写入0xaa
for(i=0;i<16;i++)//读取地址0x000000~0x00000f上的值,并发到串口。
{
j=Read_abyte(i);
Send_abyte(table[j/16]);
Send_abyte(table[j%16]);
Send_abyte(' ');
}
}
由于没有带硬件回家,无法给出调试图片,有了再发。
用户1116930 2009-10-28 13:12