AVR(Mega8)的 IO口模拟SPI,读写FLASH

来源:互联网 发布:气力输送计算软件 编辑:程序博客网 时间:2024/05/16 12:08
 现在串行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<<SO)
#define SO_1 PORT1|=(1<<SO)
#define SCLK_0 PORT1&=~(1<<SCLK)
#define SCLK_1 PORT1|=(1<<SCLK)
#define CS_0 PORT1&=~(1<<CS)
#define CS_1 PORT1|=(1<<CS)
#define WP_0 PORT1&=~(1<<WP)
#define WP_1 PORT1|=(1<<WP)
#define in_SI ((1<<SI)&PIN1)< p>

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<<SO)|(1<<SCLK)|(1<<CS)|(1<<WP));
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(' ');
}
}

源程序下载地址:http://download.csdn.net/detail/dearwind153/4196953

原创粉丝点击