https://static.assets-stash.eet-china.com/album/old-resources/2009/7/29/7fa23c9f-aada-4a2d-be9f-2ea9cbb55951.rar at25f4096驱动程序。通过proteus7.4仿真,可以学习spi接口的时序驱动及程序编写。我用的是avr的芯片,用io口模拟spi的时序。
///////////////////////////////////////////////////////////////////////////////////////
unsigned char SPI_HostReadByte(void) //下降沿
{
uchar i,RecData = 0;
for(i=0;i<8;i++)
{
RecData <<= 1;
if(PINB&0X08)RecData += 1;
SCK_high;
SCK_low;
}
return (RecData);
}
///////////////////////////////////////////////////////////////////////////////////////
void SPI_HostWriteByte(unsigned char wByte) //上升沿
{
unsigned char i;
for(i = 0; i < 8; i++)
{
if((wByte << i) & 0x80)
{
MOSI_high;
}
else
{
MOSI_low;
}
SCK_high;
SCK_low;
}
}
///////////////////////////////////////////////////////////////////////////////////////
在proteus7.4仿真如下:
以下是针对at25f4096的驱动程序:
#include "includes.h"
#define CS PB0
#define SCK PB1
#define MOSI PB2
#define MISO PB3
#define SCK_high PORTB|=BIT(SCK); DDRB|=BIT(SCK);
#define SCK_low PORTB&=~BIT(SCK); DDRB|=BIT(SCK);
#define MOSI_high PORTB|=BIT(MOSI);
#define MOSI_low PORTB&=~BIT(MOSI);
#define MISO_high PORTB|=BIT(MISO);
#define MISO_low PORTB&=~BIT(MISO);
#define CS_high PORTB|=BIT(CS);
#define CS_low PORTB&=~BIT(CS);
/* Instruction Codes */
#define WREN 0x06
#define WRDI 0x04
#define RDSR 0x05
#define WRSR 0x01
#define READ 0x03
#define PROGRAM 0x02
#define SECTOR_ERASE 0x52
#define CHIP_ERASE 0x62
#define RDID 0x15
unsigned char buffer[256];
/******************************************************************************
//void SPI_Init(void)
******************************************************************************/
void SPI_Init(void)
{
DDRB|=0X07;
DDRB&=0XF7;
CS_high;
SCK_low;
MOSI_low;
MISO_high;
}
/******************************************************************************
//unsigned char SPI_HostReadByte(void)
******************************************************************************/
unsigned char SPI_HostReadByte(void) //下降沿
{
/*
uchar i,RecData = 0;
for(i=0;i<8;i++)
{
SCK_low;
SCK_low;
RecData <<= 1;
if(PINB&0X08)RecData += 1;
SCK_high;
SCK_high;
}
return (RecData);
*/
uchar i,RecData = 0;
for(i=0;i<8;i++)
{
RecData <<= 1;
if(PINB&0X08)RecData += 1;
SCK_high;
SCK_high;
SCK_low;
SCK_low;
}
return (RecData);
}
/******************************************************************************
//void SPI_HostWriteByte(unsigned char wByte)
******************************************************************************/
void SPI_HostWriteByte(unsigned char wByte) //上升沿
{
/* unsigned char i;
for(i = 0; i < 8; i++)
{
SCK_low;
SCK_low;
if((wByte << i) & 0x80)
{
MOSI_high;
}
else
{
MOSI_low;
}
SCK_high;
SCK_high;
}
*/
unsigned char i;
for(i = 0; i < 8; i++)
{
if((wByte << i) & 0x80)
{
MOSI_high;
}
else
{
MOSI_low;
}
SCK_high;
SCK_high;
SCK_low;
SCK_low;
}
}
//=====================================================================================//
//unsigned char read_status_register(void)
//=====================================================================================//
unsigned char read_status_register(void)
{
unsigned char status;
CS_low;
SPI_HostWriteByte(RDSR);
status = SPI_HostReadByte();
CS_high;
return status;
}
//=====================================================================================//
//void SPI_WREN()
//写命令使能(很重要,如果忘记写,读状态一直是忙)
//=====================================================================================//
void SPI_WREN()
{
while((read_status_register()&0x01)==1);//读取状态寄存器,判断是否为忙
CS_low;
SPI_HostWriteByte(WREN);
CS_high;
}
//=====================================================================================//
//unsigned int get_mem_id()
//正常时 i="0x1f"; j="0x64";否则程序出错
//=====================================================================================//
unsigned int get_mem_id()
{
unsigned int i,j;
while((read_status_register()&0x01)==1);//读取状态寄存器,判断是否为忙
CS_low; /* Enable AT25F512 Chip Select (L) */
SPI_HostWriteByte(RDID); /* transmit the SECTOR_ERASE op_code */
i="SPI"_HostReadByte(); /* receive the manufacturing code */
j= SPI_HostReadByte(); /* receive the ID code */
CS_high; /* Disable AT25F512A Chip Select (H) */
return i+j<<8;
}
//=====================================================================================//
// void write_status_register(unsigned char status_register)
// Description: Write Status Register (WRSR)
//=====================================================================================//
void write_status_register(unsigned char status_register)
{
while((read_status_register()&0x01)==1); //读取状态寄存器最高位,判断是否为忙
SPI_WREN(); //you must write
while((read_status_register()&0x01)==1); //读取状态寄存器最高位,判断是否为忙
CS_low;
SPI_HostWriteByte(WRSR); /* transmit the WRSR op_code */
SPI_HostWriteByte(status_register); // /* transmit the status register value */
CS_high;
}
//=====================================================================================//
//void program_at25f4096(uint32 address_write_to_4096, uchar *point_to_databuffer, int num_of_data_writeto4096)
//=====================================================================================//
void program_at25f4096(uint32 address_write_to_4096, uchar *point_to_databuffer, int num_of_data_writeto4096)
{
uchar *pdata_to_be_write = point_to_databuffer;
unsigned int i = 0;
char data_buffer[3];//last_address_of_4096赋值给data_buffer 高位在前
data_buffer[0] = (uint8)(address_write_to_4096>>16);
data_buffer[1] = (uint8)(address_write_to_4096>>8);
data_buffer[2] = (uint8)address_write_to_4096;
while((read_status_register()&0x01)==1); //读取状态寄存器,判断是否为忙
SPI_WREN();
while((read_status_register()&0x01)==1); //读取状态寄存器,判断是否为忙
CS_low;
SPI_HostWriteByte(PROGRAM);
SPI_HostWriteByte(data_buffer[0]);
SPI_HostWriteByte(data_buffer[1]);
SPI_HostWriteByte(data_buffer[2]);
for(i=0;i<num_of_data_writeto4096;i++)
{
SPI_HostWriteByte(pdata_to_be_write);
}
CS_high;
}
//=====================================================================================//
//unsigned char read_from_at25f4096(uint32 address_read_from_at25f4096, uint8 *point_to_databuffer, int num_of_data_readfrom4096)
//=====================================================================================//
void read_from_at25f4096(uint32 address_read_from_at25f4096, uint8 *point_to_databuffer, int num_of_data_readfrom4096)
{
int i;
uint8 *pdata_get_from_4096 = point_to_databuffer;
char data_buffer[3];//要读的储存器的首地址赋给data_buffer 高位在前
data_buffer[0] = (uint8)(address_read_from_at25f4096>>16);
data_buffer[1] = (uint8)(address_read_from_at25f4096>>8);
data_buffer[2] = (uint8)address_read_from_at25f4096;
while((read_status_register()&0x01)==1);
SPI_WREN();
while((read_status_register()&0x01)==1);
CS_low;
{
SPI_HostWriteByte(READ);
SPI_HostWriteByte(data_buffer[0]);
SPI_HostWriteByte(data_buffer[1]);
SPI_HostWriteByte(data_buffer[2]);
for(i=0;i<num_of_data_readfrom4096;i++)
{
pdata_get_from_4096= SPI_HostReadByte();
}
}
CS_high;
}
//=====================================================================================//
//void chip_erase(void)
//=====================================================================================//
void chip_erase(void)
{
while((read_status_register()&0x01)==1);
SPI_WREN();
while((read_status_register()&0x01)==1);
CS_low;
SPI_HostWriteByte(CHIP_ERASE); /* transmit the WRSR op_code */
CS_high;
}
//========================================================================================
//void sector_erase(uint32 address)
//address 为要察的sector里面的任何一个字节的地址
//========================================================================================
void sector_erase(uint32 address)//address 为要察的sector里面的任何一个字节的地址
{
uint8 transfer_buffer[4];
uint32 address_of_erase = address;
while((read_status_register()&0x01)==1);//读取状态寄存器,判断是否为忙
SPI_WREN();
while((read_status_register()&0x01)==1);//读取状态寄存器,判断是否为忙
transfer_buffer[2] = (uint8)address_of_erase;
transfer_buffer[1] = (uint8)(address_of_erase>>8);
transfer_buffer[0] = (uint8)(address_of_erase>>16);
CS_low;
{
SPI_HostWriteByte(CHIP_ERASE);
SPI_HostWriteByte(transfer_buffer[0]);
SPI_HostWriteByte(transfer_buffer[1]);
SPI_HostWriteByte(transfer_buffer[2]);
}
CS_high;
}
//========================================================================================
// level area array addesses locked out
//
// 0 8 NONE
// 1 7 070000-07FFFF
// 2 6 060000-07FFFF
// 3 4 040000-07FFFF
// 4 0 000000-07FFFF
// 参考芯片pdf第八页 Table4
//========================================================================================
void set_write_protected_area(unsigned char area)//Set Write Protected Area
{
while((read_status_register()&0x01)==1);//读取状态寄存器,判断是否为忙
switch(area)
{
case 8:
write_status_register(0b00000010);//全部保护
break;
case 7:
write_status_register(0b00000110);//保护000000-06FFFF地址上数据
break;
case 6:
write_status_register(0b00001010);//保护000000-05FFFF地址上数据
break;
case 4:
write_status_register(0b00001110);//保护000000-03FFFF地址上数据
break;
case 0:
write_status_register(0b00010010);//不保护地址上数据
break;
default :
write_status_register(0b00000010);//全部保护
break;
}
}
//========================================================================================
//void demo()
//测试函数
//========================================================================================
void demo()//读写测试
{
uint ii;
long count="0";
for(ii=0;ii<256;ii++)
buffer[ii]=ii;
SPI_Init();
sector_erase(0); //擦除sector 0
chip_erase(); //整个芯片擦除
set_write_protected_area(0);//Set Write Protected Area
get_mem_id();
// for(count=0;count<1;count++)//写芯片
for(count=0;count<(256*8);count++)//写芯片
{
long addr;
addr="256"*count;
program_at25f4096(addr,buffer,256);
}
set_write_protected_area(8);//Set Write Protected Area
// for(count=0;count<1;count++)//写芯片
for(count=0;count<(256*8);count++)//写芯片
{
for(ii=0;ii<256;ii++)
buffer[ii]=ii;
read_from_at25f4096(256*count,buffer,256);
}
while(1);
}
//========================================================================================
//========================================================================================
void main()
{
demo();
}
用户377235 2014-12-25 11:06
谢谢楼主
用户1592348 2011-4-14 21:39
用户1586933 2011-4-9 17:55