STC15F2K16S2单片机利用SPI功能与片外Flash读写程序就能读写255字节(第一页)
时间:10-02
整理:3721RD
点击:
大神们,帮忙看看不知道问题出在哪了,就能读写第一页 一共255 字节 当读写第二页时候,发现回来的都是0XFF,第一页数据读写正常
//用SPI查询方式将音频文件通过SPI存入到flash芯片里,写一整页(256bytes)
#include "STC15F2K60S2.h"
typedef bit BOOL;
#define uchar unsigned char
#define uint unsigned int
#define ulong unsigned long
#define FALSE 0
#define TRUE 1
uchar flag=0;
uchar ii=0;
uchar g_Buffer[255]; //Flash读写缓冲区
uchar g_Buffer1[255]; //Flash读写缓冲区
sbit CS=P1^1; //Mx25L片选信号
BOOL g_fFlashOK; //Flash状态
//====================STC15F2K16S2的SPI寄存器====================
#define SPI_S0 0x04
#define SPI_S1 0x08
#define SPIF 0x80 //SPSTAT.7
#define WCOL 0x40 //SPSTAT.6
#define SSIG 0x80 //SPCTL.7
#define SPEN 0x40 //SPCTL.6
#define DORD 0x20 //SPCTL.5
#define MSTR 0x10 //SPCTL.4
#define CPOL 0x08 //SPCTL.3
#define CPHA 0x04 //SPCTL.2
#define SPDHH 0x00 //CPU_CLK/4
#define SPDH 0x01 //CPU_CLK/16
#define SPDL 0x02 //CPU_CLK/64
#define SPDLL 0x03 //CPU_CLK/128
#define ESPI 0x02 //IE2.1
//================Mx25l8005的flash存储器指令码===================
#define SFC_WREN 0x06 //Write Enable
#define SFC_WRDI 0x04 //Write Disable
#define SFC_RDSR 0x05 //Read status register
#define SFC_WRSR 0x01 //Write status register
#define SFC_READ 0x03 //Read data
#define SFC_FASTREAD 0x0b //Fast read data
#define SFC_PAGEPROG 0x02 //Page Program
#define SFC_SECTORER 0x20 //Sector Erase
#define SFC_BLOCKER 0xd8 //Block Erase
#define SFC_CHIPER 0xc7 //Chip Erase
#define SFC_RDID 0x9f //Read idenification
//=================页面地址======================================
#define Mx25L8005_BLOCK0 0x000000
#define Mx25L8005_BLOCK1 0x010000
#define Mx25L8005_BLOCK2 0x020000
#define Mx25L8005_BLOCK3 0x030000
#define Mx25L8005_BLOCK4 0x040000
#define Mx25L8005_BLOCK5 0x050000
#define Mx25L8005_BLOCK6 0x060000
#define Mx25L8005_BLOCK7 0x070000
#define Mx25L8005_BLOCK8 0x080000
#define Mx25L8005_BLOCK9 0x090000
#define Mx25L8005_BLOCKA 0x0a0000
#define Mx25L8005_BLOCKB 0x0b0000
#define Mx25L8005_BLOCKC 0x0c0000
#define Mx25L8005_BLOCKD 0x0d0000
#define Mx25L8005_BLOCKE 0x0e0000
#define Mx25L8005_BLOCKF 0x0f0000
//======================串口初始化===============================
void uart_init()
{
AUXR=0x40; //定时器1速度是传统8051的12倍
TMOD&=0x0f; //设置T1定时器为工作模式0 16位自动装载
TL1=0xe0; //设置波特率为9600
TH1=0xfe;
SM0=0; //设置SCON 串口模式1 8位UART
SM1=1;
TR1=1; //开启T1定时器
REN=1; //允许串行接收
ET1=0; //关闭T1定时器
EA=1; //打开总中断
ES=1; //打开串口中断
}
//======================Spi初始化================================
void InitSpi()
{
ACC = P_SW1; //切换到第一组SPI
ACC &= ~(SPI_S0 | SPI_S1); //SPI_S0=0 SPI_S1=0
P_SW1 = ACC; //(P1.2/SS, P1.3/MOSI, P1.4/MISO, P1.5/SCLK)
SPSTAT = SPIF | WCOL; //清除SPI状态
SPCTL = SSIG | SPEN | MSTR |CPHA |CPOL|SPDHH; //设置SPI为主模式,CPHA=1,CPOL=1,CPU_CLK/4
}
//================写一个字节数据(对单片机操作)===================
void SpiWrite(uchar byte)
{
SPSTAT =SPIF | WCOL; //清除SPI状态
SPDAT=byte; //写一字节数据
while (!(SPSTAT & SPIF )); //等待SPI数据传输完成
}
//================读一个字节数据(对单片机操作)===================
uchar SpiRead()
{
SPSTAT=SPIF | WCOL; //传输初始化
SPDAT=0xff; //随意发送一字节数据
while (!(SPSTAT & SPIF)); //等待SPI数据传输完成
return SPDAT;
}
//================检查Flash是否为忙(等于1即为忙)=================
BOOL IsFlashBusy()
{
uchar dat=0;
CS = 0;
SpiWrite(SFC_RDSR); //发送读取状态命令
dat = SpiRead(); //读取状态
CS = 1;
return (dat & 0x01); //状态值的Bit0即为忙标志
}
//===============检测Flash是否准备就绪(等于1准备就绪)============
BOOL FlashCheckID()
{
uchar dat1, dat2,dat3;
while (IsFlashBusy()); //Flash忙检测
CS = 0;
SpiWrite(SFC_RDID); //发送读取ID命令;
dat1 = SpiRead(); //读取制造商ID
dat2 = SpiRead(); //读取设备ID1
dat3 = SpiRead(); //读取设备ID2
CS = 1;
while (IsFlashBusy()); //Flash忙检测
//检测是否为PM25LVxx系列的Flash
g_fFlashOK = ((dat1 == 0xc2) && (dat2 == 0x20)&& (dat3 == 0x14));
return g_fFlashOK;
}
//======================Flash使能信号============================
void FlashWriteEnable()
{
CS = 0;
SpiWrite(SFC_WREN); //发送写使能命令
CS = 1;
}
//======================擦除整片指令=============================
void FlashErase()
{
if (g_fFlashOK)
{
FlashWriteEnable(); //使能Flash写命令
while (IsFlashBusy()); //Flash忙检测
CS = 0;
SpiWrite(SFC_CHIPER); //发送片擦除命令
CS = 1;
while (IsFlashBusy()); //Flash忙检测
}
}
//===================页面编程指令(0~4095)==========================
void FlashWrite(uint page,uchar *p,uint size)
{
ulong addr;
addr=(((ulong)page)<<8); //取page地址
if (g_fFlashOK)
{
FlashWriteEnable(); //使能Flash写命令
while (IsFlashBusy()); //Flash忙检测
CS=0;
SpiWrite(SFC_PAGEPROG); //发送页编程命令
SpiWrite((uchar)((addr&0x00ff0000)>>16)); //设置起始地址
SpiWrite((uchar)((addr&0x00ff0000)>>8));
SpiWrite((uchar)(addr&0x000000ff));
while(size)
{
SpiWrite(*p);
p++;
size--;
}
CS=1;
}
}
//========================读指令===================================
void FlashRead(uint page,uchar *p,uint size)
{
ulong addr2;
addr2=(((ulong)page)<<8); //取page地址
if (g_fFlashOK)
{
while (IsFlashBusy()); //Flash忙检测
CS=0;
SpiWrite(SFC_FASTREAD); //使用读取命令
SpiWrite((uchar)((addr2&0x00ff0000)>>16)); //设置起始地址
SpiWrite((uchar)((addr2&0x0000ff00)>>8));
SpiWrite((uchar)(addr2&0x000000ff));
SpiWrite(0xff);
while(size)
{
*p=SpiRead();
p++;
size--;
}
CS=1;
while (IsFlashBusy());
}
}
//======================主函数===================================
void main()
{
InitSpi(); //Spi初始化
uart_init(); //串口初始化
//初始化Flash状态
g_fFlashOK = FALSE;
//检测Flash状态
FlashCheckID();
while(1);
}
//=======================串口中断函数============================
void ser() interrupt 4
{
uchar a;
uint jj;
RI=0;
a=SBUF;
if(flag)
{
g_Buffer[ii++]=a; //串口发来的数据写入到Flash缓冲区中
if(ii==255)
{
ii=0;
FlashWrite(0x0000,g_Buffer,255);
FlashRead(0x0000,g_Buffer1,255);
ES=0;
for(jj=0;jj<255;jj++)
{
SBUF=g_Buffer1[jj];
while(!TI);
TI=0;
}
ES=1;
}
}
else
{
if(a==0x88)
{
flag=1;
FlashErase(); //擦除整个芯片数据
}
}
}
//用SPI查询方式将音频文件通过SPI存入到flash芯片里,写一整页(256bytes)
#include "STC15F2K60S2.h"
typedef bit BOOL;
#define uchar unsigned char
#define uint unsigned int
#define ulong unsigned long
#define FALSE 0
#define TRUE 1
uchar flag=0;
uchar ii=0;
uchar g_Buffer[255]; //Flash读写缓冲区
uchar g_Buffer1[255]; //Flash读写缓冲区
sbit CS=P1^1; //Mx25L片选信号
BOOL g_fFlashOK; //Flash状态
//====================STC15F2K16S2的SPI寄存器====================
#define SPI_S0 0x04
#define SPI_S1 0x08
#define SPIF 0x80 //SPSTAT.7
#define WCOL 0x40 //SPSTAT.6
#define SSIG 0x80 //SPCTL.7
#define SPEN 0x40 //SPCTL.6
#define DORD 0x20 //SPCTL.5
#define MSTR 0x10 //SPCTL.4
#define CPOL 0x08 //SPCTL.3
#define CPHA 0x04 //SPCTL.2
#define SPDHH 0x00 //CPU_CLK/4
#define SPDH 0x01 //CPU_CLK/16
#define SPDL 0x02 //CPU_CLK/64
#define SPDLL 0x03 //CPU_CLK/128
#define ESPI 0x02 //IE2.1
//================Mx25l8005的flash存储器指令码===================
#define SFC_WREN 0x06 //Write Enable
#define SFC_WRDI 0x04 //Write Disable
#define SFC_RDSR 0x05 //Read status register
#define SFC_WRSR 0x01 //Write status register
#define SFC_READ 0x03 //Read data
#define SFC_FASTREAD 0x0b //Fast read data
#define SFC_PAGEPROG 0x02 //Page Program
#define SFC_SECTORER 0x20 //Sector Erase
#define SFC_BLOCKER 0xd8 //Block Erase
#define SFC_CHIPER 0xc7 //Chip Erase
#define SFC_RDID 0x9f //Read idenification
//=================页面地址======================================
#define Mx25L8005_BLOCK0 0x000000
#define Mx25L8005_BLOCK1 0x010000
#define Mx25L8005_BLOCK2 0x020000
#define Mx25L8005_BLOCK3 0x030000
#define Mx25L8005_BLOCK4 0x040000
#define Mx25L8005_BLOCK5 0x050000
#define Mx25L8005_BLOCK6 0x060000
#define Mx25L8005_BLOCK7 0x070000
#define Mx25L8005_BLOCK8 0x080000
#define Mx25L8005_BLOCK9 0x090000
#define Mx25L8005_BLOCKA 0x0a0000
#define Mx25L8005_BLOCKB 0x0b0000
#define Mx25L8005_BLOCKC 0x0c0000
#define Mx25L8005_BLOCKD 0x0d0000
#define Mx25L8005_BLOCKE 0x0e0000
#define Mx25L8005_BLOCKF 0x0f0000
//======================串口初始化===============================
void uart_init()
{
AUXR=0x40; //定时器1速度是传统8051的12倍
TMOD&=0x0f; //设置T1定时器为工作模式0 16位自动装载
TL1=0xe0; //设置波特率为9600
TH1=0xfe;
SM0=0; //设置SCON 串口模式1 8位UART
SM1=1;
TR1=1; //开启T1定时器
REN=1; //允许串行接收
ET1=0; //关闭T1定时器
EA=1; //打开总中断
ES=1; //打开串口中断
}
//======================Spi初始化================================
void InitSpi()
{
ACC = P_SW1; //切换到第一组SPI
ACC &= ~(SPI_S0 | SPI_S1); //SPI_S0=0 SPI_S1=0
P_SW1 = ACC; //(P1.2/SS, P1.3/MOSI, P1.4/MISO, P1.5/SCLK)
SPSTAT = SPIF | WCOL; //清除SPI状态
SPCTL = SSIG | SPEN | MSTR |CPHA |CPOL|SPDHH; //设置SPI为主模式,CPHA=1,CPOL=1,CPU_CLK/4
}
//================写一个字节数据(对单片机操作)===================
void SpiWrite(uchar byte)
{
SPSTAT =SPIF | WCOL; //清除SPI状态
SPDAT=byte; //写一字节数据
while (!(SPSTAT & SPIF )); //等待SPI数据传输完成
}
//================读一个字节数据(对单片机操作)===================
uchar SpiRead()
{
SPSTAT=SPIF | WCOL; //传输初始化
SPDAT=0xff; //随意发送一字节数据
while (!(SPSTAT & SPIF)); //等待SPI数据传输完成
return SPDAT;
}
//================检查Flash是否为忙(等于1即为忙)=================
BOOL IsFlashBusy()
{
uchar dat=0;
CS = 0;
SpiWrite(SFC_RDSR); //发送读取状态命令
dat = SpiRead(); //读取状态
CS = 1;
return (dat & 0x01); //状态值的Bit0即为忙标志
}
//===============检测Flash是否准备就绪(等于1准备就绪)============
BOOL FlashCheckID()
{
uchar dat1, dat2,dat3;
while (IsFlashBusy()); //Flash忙检测
CS = 0;
SpiWrite(SFC_RDID); //发送读取ID命令;
dat1 = SpiRead(); //读取制造商ID
dat2 = SpiRead(); //读取设备ID1
dat3 = SpiRead(); //读取设备ID2
CS = 1;
while (IsFlashBusy()); //Flash忙检测
//检测是否为PM25LVxx系列的Flash
g_fFlashOK = ((dat1 == 0xc2) && (dat2 == 0x20)&& (dat3 == 0x14));
return g_fFlashOK;
}
//======================Flash使能信号============================
void FlashWriteEnable()
{
CS = 0;
SpiWrite(SFC_WREN); //发送写使能命令
CS = 1;
}
//======================擦除整片指令=============================
void FlashErase()
{
if (g_fFlashOK)
{
FlashWriteEnable(); //使能Flash写命令
while (IsFlashBusy()); //Flash忙检测
CS = 0;
SpiWrite(SFC_CHIPER); //发送片擦除命令
CS = 1;
while (IsFlashBusy()); //Flash忙检测
}
}
//===================页面编程指令(0~4095)==========================
void FlashWrite(uint page,uchar *p,uint size)
{
ulong addr;
addr=(((ulong)page)<<8); //取page地址
if (g_fFlashOK)
{
FlashWriteEnable(); //使能Flash写命令
while (IsFlashBusy()); //Flash忙检测
CS=0;
SpiWrite(SFC_PAGEPROG); //发送页编程命令
SpiWrite((uchar)((addr&0x00ff0000)>>16)); //设置起始地址
SpiWrite((uchar)((addr&0x00ff0000)>>8));
SpiWrite((uchar)(addr&0x000000ff));
while(size)
{
SpiWrite(*p);
p++;
size--;
}
CS=1;
}
}
//========================读指令===================================
void FlashRead(uint page,uchar *p,uint size)
{
ulong addr2;
addr2=(((ulong)page)<<8); //取page地址
if (g_fFlashOK)
{
while (IsFlashBusy()); //Flash忙检测
CS=0;
SpiWrite(SFC_FASTREAD); //使用读取命令
SpiWrite((uchar)((addr2&0x00ff0000)>>16)); //设置起始地址
SpiWrite((uchar)((addr2&0x0000ff00)>>8));
SpiWrite((uchar)(addr2&0x000000ff));
SpiWrite(0xff);
while(size)
{
*p=SpiRead();
p++;
size--;
}
CS=1;
while (IsFlashBusy());
}
}
//======================主函数===================================
void main()
{
InitSpi(); //Spi初始化
uart_init(); //串口初始化
//初始化Flash状态
g_fFlashOK = FALSE;
//检测Flash状态
FlashCheckID();
while(1);
}
//=======================串口中断函数============================
void ser() interrupt 4
{
uchar a;
uint jj;
RI=0;
a=SBUF;
if(flag)
{
g_Buffer[ii++]=a; //串口发来的数据写入到Flash缓冲区中
if(ii==255)
{
ii=0;
FlashWrite(0x0000,g_Buffer,255);
FlashRead(0x0000,g_Buffer1,255);
ES=0;
for(jj=0;jj<255;jj++)
{
SBUF=g_Buffer1[jj];
while(!TI);
TI=0;
}
ES=1;
}
}
else
{
if(a==0x88)
{
flag=1;
FlashErase(); //擦除整个芯片数据
}
}
}
小编,你的问题解决了吗,我也出现这种问题,帮忙顶上去。
没有,前段时间我把程序改了,数据写进去了。今天一试又不好使了,还是0x00
我的可以了,我的应该是写入数据出现了问题
能贴出来看下吗
顶起来,,,,,,,,,,
小编有这个芯片的资料吗?麻烦发下给我!谢谢811043655@qq.com
小编,解决了吗?我现在也在做这个,求指导一下!
很实用的,谢谢分享
请问小编这个程序有没有出现数据丢包的现象?