原创 AVR(Mega8)的study:9、IO口模拟SPI,读写FLASH

2010-2-26 13:13 1782 5 5 分类: MCU/ 嵌入式

       现在串行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(' ');
}
}


由于没有带硬件回家,无法给出调试图片,有了再发。


程序包:点击下载

PARTNER CONTENT

文章评论0条评论)

登录后参与讨论
我要评论
0
5
关闭 站长推荐上一条 /4 下一条