📄 spi_flash_driver.c
字号:
/*==================================================================
// 文件名: SPI_Flash_Driver.c
// 作 者: 三生石
// 日 期: 2008/06/05
// 描 述: SPI串口Flash烧写读取操作程序集
//
// 参 考: 1.flash型号;AT45DB041B
2.晶振:11.0592MHZ
3.指令周期:≈1us
4.SPI MODE:0; 在此模式下:SCK=0为空闲;时钟上升沿读取,下降沿写
5.除中间函数,完整功能函数出口处SCK都为低
// 版 本:
// 2008/06/05 First version
=====================================================================*/
#include <reg52.h>
#include <intrins.h>
typedef unsigned char uchar;
typedef unsigned int uint;
/*=======接口配置文件=====*/
sbit _CS = P1^2; //Chip select pin
sbit SCK = P2^5; //Serial Data Clock (SCK)
sbit SI = P2^6; //Serial Data Input (SI)
sbit SO = P2^7; //Serial Data Output
/*=======命令宏===================*/
#define R_PAGE 0xD2 //按指定页读取 spi mode 0
#define R_BUSY 0xD7 //读状态命令
#define W_BUF1 0X84 //写BUF1
#define W_BUF2 0x87 //写BUF2
#define W_BUF1_MEM 0x83 //Buffer to Main Memory page program with built-in Erase
#define W_BUF2_MEM 0x86
uchar xdata Buffer[32]={/*-- 文字: 徐 --*/
/*-- 宋体12; 此字体下对应的点阵为:宽x高=16x16 --*/
0x10,0x88,0xC4,0x73,0x22,0x20,0x10,0x28,0x24,0xE3,0x24,0x28,0x18,0x30,0x10,0x00,
0x01,0x00,0xFF,0x00,0x20,0x11,0x0D,0x49,0x81,0x7F,0x01,0x05,0x09,0x39,0x10,0x00};
/*========================================================================
// 函数: void SendByte(uchar cmd)
// 描述: 发送1字节8位的命令,或者地址
// 参数: 要发送的字节数据
// 返回: 无
// 备注:
// 版本:
// 2008/06/05 First version
2008/06/10 Ver1.1 使用掩码来得到数据从高位到低位的bit值,
使程序清晰简洁,提高了可读性和运行效率
//======================================================================*/
void SendByte(uchar Data)
{
uchar i;
uchar mask = 0x80; /*判断Data某位为1或0的掩码*/
for(i=8;i>0;i--)
{
SI = (bit)(Data&mask); /*在时钟上升沿到来前将数据发出*/
SCK = 0;
SCK = 1;
mask>>= 1;
}
}
/*========================================================================
// 函数: void ReceiveByte(uint *SaveAdd)
// 描述: 接收1字节8位的数据
// 参数: 要发送的字节数据
// 返回: 无
// 备注:
// 版本:
// 2008/06/05 First version
//======================================================================*/
/*========================================================================
// 函数: void SendPageAdd(uint PageAdd)
// 描述: 发送11位的目标页地址
// 参数: PageAdd:目标页地址
// 返回: 无
// 备注:
// 版本:
// 2008/06/05 First version
//======================================================================*/
void SendPageAdd(uint PageAdd)
{
uchar i;
uint mask = 0x0400; /*判断PageAdd某位为1或0的掩码*/
for(i=11;i>0;i--)
{
SI = (bit)(PageAdd&mask); /*在时钟上升沿到来前将数据发出*/
SCK=0;
SCK=1;
mask>>= 1;
}
}
/*========================================================================
// 函数: void SendBFAdd(uchar PageAdd)
// 描述: 发送9位目标buffer或页中起始字节地址
// 参数: PageAdd:目标地址
// 返回: 无
// 备注: 因为buffer和页中只用到前面256字节,所以地址最高位都为:0
// 版本:
// 2008/06/05 First version
//======================================================================*/
void SendBFAdd(uchar BFAdd)
{
uchar i;
uchar mask = 0x80; /*判断Data某位为1或0的掩码*/
SI = 0;
SCK = 0;
SCK = 1;
for(i=8;i>0;i--)
{
SI = (bit)(BFAdd&mask); /*在时钟上升沿到来前将数据发出*/
SCK = 0;
SCK = 1;
mask>>= 1;
}
}
/*========================================================================
// 函数: void PageRead(uint PageAdd,uchar BA)
// 描述: 读取指定页中指定起始字节的数据指令
// 参数: PageAdd:要读目标页地址;BA:目标页中要读的字节地址;
// 返回: 无
// 备注: 1.PageAdd为10位;BA这里被设置为8位(只用到前面256字节);
2.在SPI Mode 0下的读;
// 版本:
// 2008/06/05 First version
//======================================================================*/
void PageRead(uint PageAdd,uchar BA)
{
uchar i,j;
uchar RecData=0;
SCK = 0; //模式0下,在片选信号有效前,时钟应为低
_CS = 0;
/*发送页读命令*/
SendByte(R_PAGE);
/*发送4位保留位*/
for(i=0;i<4;i++)
{
SCK = 0;_nop_();
SI = 0;//应该可以去掉,时序满足要求,数据无关!资料上说推荐写0;
SCK = 1;_nop_();
}
/*发送10位页地址*/
SendPageAdd(PageAdd);
/*发送9位字节地址*/
SCK = 0;
_nop_();
SI = 0;//BA最高位为0;
SCK = 1;//准备好数据后,上升沿跳变,使flash可以接收
_nop_();
SendByte(BA);
/*发送32位无关位*/
for(i=0;i<32;i++)
{
SCK = 0;
_nop_();
SI = 0;
SCK = 1;
_nop_();
}
/*=============指令发送完毕,开始接受数据============*/
SO = 1;//初始化接收端口
for(i=0;i<32;i++)
{
for(j=0;j<8;j++)
{
SCK = 0;//数据在SCK从1到0跳变后已经准备好了,下面开始接收
_nop_();
RecData=(RecData<<1)|SO;//把SO上的数据位移位到接受数据的相应位;
SCK = 1;//拉高,等待下次跳变
_nop_();
}
Buffer[i]=RecData;//接收到的数据放到缓冲区
RecData = 0;
}
/*读写操作结束*/
SCK = 0;
_CS = 1;
}
/*========================================================================
// 函数: void WaitFlashReady(void)
// 描述: 等待存储器就绪状态
// 参数: 无
// 返回: 无
// 备注: The user can continuously poll bit 7 of the status register
by stopping SCK at a low level once bit 7 has been output.
The status of bit 7 will continue to be output on the SO pin,
and once the device is no longer busy, the state of SO will
change from 0 to 1.
// 版本:
// 2008/06/05 First version
//======================================================================*/
void WaitFlashReady(void)
{
SCK = 0;
_CS = 0;
SendByte(R_BUSY);
SCK = 0; //把时钟信号线拉低,然后一直查询D7位
while(SO!=1); //直到bit 7变为ready,否则一直等待
_CS = 1;
}
/*========================================================================
// 函数: void BufferWrite(uchar cmd,uchar BuffAdd,uchar* DataAdd)
// 描述: 写buffer
// 参数: cmd:对那个buffer写,BuffAdd:flash缓冲开始地址,DataAdd:传输数据的起始地址// 返回: 无
// 备注:
// 版本:
// 2008/06/06 First version
//======================================================================*/
void BufferWrite(uchar cmd,uchar BuffAdd,uchar* DataAdd)
{
uchar i;
SCK = 0;
_CS = 0;
SendByte(cmd);
for(i=0;i<15;i++)
{
SCK = 0;
_nop_();
SI = 0;
SCK = 1;
_nop_();
}
SendBFAdd(BuffAdd);
/*开始发送数据*/
for(i=0;i<32;i++) //i不能为255,溢出后判断无效
{
SendByte(*DataAdd++);
}
/*SendByte(*DataAdd); //最后一字节单独发送 */
SCK = 0;
_CS = 1;
}
/*========================================================================
// 函数: void Buffer_To_Mem(uchar cmd,uint PageAdd)
// 描述: 写buffer
// 参数: cmd:从哪个buffer写,PageAdd:目标页地址
// 返回: 无
// 备注:
// 版本:
// 2008/06/06 First version
//======================================================================*/
void Buffer_To_Mem(uchar cmd,uint PageAdd)
{
uchar i;
SCK = 0;
_CS = 0;
/*发送命令*/
SendByte(cmd);
/*4个保留位*/
for(i=0;i<4;i++)
{
SCK = 0;_nop_();
SI = 0;
SCK = 1;_nop_();
}
/*发送目标页地址*/
SendPageAdd(PageAdd);
/*9个无关位*/
for(i=0;i<9;i++)
{
SCK = 0;_nop_();
SI = 0;
SCK = 1;_nop_();
}
/*启动写命令*/
SCK = 0;
_CS = 1;
}
/*========================================================================
// 函数: void ProgramFlash(uint PageNum)
// 描述: 烧字库
// 参数: PageNum:需要编程的页数
// 返回: 无
// 备注:
// 版本:
// 2008/06/06 First version
//======================================================================*/
extern DelayMs(uchar n);
extern uchar code Buffer2[32];
void TestFlash(void)
{
uchar i;
uchar* p;
p = Buffer;
BufferWrite(W_BUF1,0,Buffer2);
Buffer_To_Mem(W_BUF1_MEM,0);
for(i=0;i<32;i++)
{
*p=0x00;
p++;
}
/*WaitFlashReady();*/
DelayMs(22);
PageRead(0,0);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -