OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 7136|回复: 7

SPI外部Flash-----实在没办法再问一个

[复制链接]

96

主题

247

帖子

1

精华

高级会员

Rank: 4

积分
801
金钱
801
注册时间
2012-6-29
在线时间
0 小时
发表于 2012-12-11 01:17:10 | 显示全部楼层 |阅读模式
SPI 外部Flash,支持连续写两页吗?
怎么我在连续的地址上,分段(跨页)写了两次数据,却只能读出前一段的数据?问一下为什么?
 
http://blog.tianya.cn/blogger/blog_main.asp?BlogID=4666068
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2012-12-11 10:48:00 | 显示全部楼层
直接用我的代码就可以了。
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

96

主题

247

帖子

1

精华

高级会员

Rank: 4

积分
801
金钱
801
注册时间
2012-6-29
在线时间
0 小时
 楼主| 发表于 2012-12-11 11:15:21 | 显示全部楼层
我写一个代码,用于擦除任意起始地址的诺干字节空间:
//可以擦除任意位置Byte空间。
void SPI_ExFlash_Erase_Bytes(u32 EraseAddr, u8 ByteNum)
{
int i=0,j=0,k=0;
int FirstSectorAddr_Num = EraseAddr>>12;//4096
int SecondSectorAddr_Num = FirstSectorAddr_Num+1;

u32 FirstSectorAddr_Start = FirstSectorAddr_Num<<12;
u32 FirstSectorAddr_End = FirstSectorAddr_Start+4095;

u32 SecondSectorAddr_Start = FirstSectorAddr_End+1; 

int Length_SectorStarAddrtToEraseAddr = EraseAddr - FirstSectorAddr_Start;//EraseAddr - (SectorAddr_Start-1) + 1
//如果EraseAddr = 4090;则SectorAddr_End = 4095;那么第一Sector有6个字节:4095-4090+1=5+1;
int BytesInFirstSector = FirstSectorAddr_End-EraseAddr+1;
//如果ByteNum = 23;则 EraseAddr+ByteNum= 4090 + 23 = 4113;减去SSectorAddr_End(=4095),则前三个参数结果=18;
//而第一Sector共有6个字节,那么第二个Sector共有17个字节。所以,前面三个参数要再减去1;
int BytesInSecondSector = EraseAddr+ByteNum-FirstSectorAddr_End-1;
//【备注】BytesInFirstSector+BytesInSecondSector刚好=ByteNum。
u32 EraseAddr_End = EraseAddr+ByteNum-1;//如果EA=4090,ByteNum=6,而EA_E刚好是4095。EA+ByteNum=4096。故要减1;

if(EraseAddr_End<=FirstSectorAddr_End)
{
SPI_ExFlash_Read(SPI_ExFlash_BufSector_1, FirstSectorAddr_Start, W25X_WholeSectorLength);
for(i=0;i<ByteNum;i++)
{
SPI_ExFlash_BufSector_1[Length_SectorStarAddrtToEraseAddr+i]= (u8)0xFF;//擦除后,写入0xFF 是Dummy Write.
}
SPI_ExFlash_Erase_Sector(FirstSectorAddr_Num);//需要150ms
SPI_ExFlash_Write_BlockMax_EraseFirst_Not(SPI_ExFlash_BufSector_1, FirstSectorAddr_Start, W25X_WholeSectorLength);
}else
{
SPI_ExFlash_Read(SPI_ExFlash_BufSector_1, FirstSectorAddr_Start, W25X_WholeSectorLength);
SPI_ExFlash_Read(SPI_ExFlash_BufSector_2, SecondSectorAddr_Start, W25X_WholeSectorLength);
for(j=0;j<BytesInFirstSector;j++)
{
SPI_ExFlash_BufSector_1[Length_SectorStarAddrtToEraseAddr+j]= (u8)0xFF;//擦除后,写入0xFF 是Dummy Write.
}
for(k=0;k<BytesInSecondSector;k++)
{
SPI_ExFlash_BufSector_2[k]= (u8)0xFF;//擦除后,写入0xFF 是Dummy Write.
}
SPI_ExFlash_Erase_Sector(FirstSectorAddr_Num);//需要150ms
SPI_ExFlash_Erase_Sector(SecondSectorAddr_Num);//需要150ms
SPI_ExFlash_Write_BlockMax_EraseFirst_Not(SPI_ExFlash_BufSector_1, FirstSectorAddr_Start, W25X_WholeSectorLength);
SPI_ExFlash_Write_BlockMax_EraseFirst_Not(SPI_ExFlash_BufSector_2, SecondSectorAddr_Start, W25X_WholeSectorLength);
}
}

这个代码测试OK。
现在要写一个在任意起始地址上写入若干字节的数据。发现数据只能写前一个page,后面一个page写不进去。
所以来问一下,是否可以连续调用你提供的page写入函数。
我调用的结果是,写入第二个page的时候,出问题了,写不进去。
>
http://blog.tianya.cn/blogger/blog_main.asp?BlogID=4666068
回复 支持 反对

使用道具 举报

96

主题

247

帖子

1

精华

高级会员

Rank: 4

积分
801
金钱
801
注册时间
2012-6-29
在线时间
0 小时
 楼主| 发表于 2012-12-11 11:18:01 | 显示全部楼层
void SPI_ExFlash_Write_Bytes(u8* pBuffer,u32 WriteAddr_Start)
{
u32 Size = sizeof(pBuffer);
u8 DataBuffer[256];

int i=0;//,j=0,k=0,m=0;
int FirstSectorAddr_Num = WriteAddr_Start>>8;//256
u32 FirstSectorAddr_End = (FirstSectorAddr_Num<<8)+255;
u32 SecondSectorAddr_Start = FirstSectorAddr_End+1;  


int BytesInFirstSector = FirstSectorAddr_End-WriteAddr_Start+1; 
int BytesInSecondSector = WriteAddr_Start+Size-FirstSectorAddr_End-1; 
u32 WriteAddr_End = WriteAddr_Start+Size-1;  

for(i=0;i<BytesInSecondSector;i++)
{
DataBuffer=pBuffer[BytesInFirstSector+i];
}
if(WriteAddr_End<=FirstSectorAddr_End)
{
SPI_ExFlash_Write_Page(pBuffer,WriteAddr_Start,Size);
}
else
{
SPI_ExFlash_Write_Page(pBuffer,WriteAddr_Start,BytesInFirstSector);
SPI_ExFlash_Write_Page(DataBuffer,SecondSectorAddr_Start,BytesInSecondSector);
}
}
这个代码,如果起始地址采用250,沿用你的TEXT,那么就要跨page写入,我调用两次page写入函数,发现错了。
说明一下,如果地址改为0,那么if那个可以实现。起始地址为250,else第二个page写入函数没功能。
http://blog.tianya.cn/blogger/blog_main.asp?BlogID=4666068
回复 支持 反对

使用道具 举报

96

主题

247

帖子

1

精华

高级会员

Rank: 4

积分
801
金钱
801
注册时间
2012-6-29
在线时间
0 小时
 楼主| 发表于 2012-12-11 11:47:42 | 显示全部楼层
不好意思,我错了,Size的定义错了,pBuffer是指针,用sizeof提取字节数是错的。如果在函数增加一个ByteNum控制参数,那样这个函数就对了。实在抱歉,让浪费大家眼力了。
http://blog.tianya.cn/blogger/blog_main.asp?BlogID=4666068
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2012-12-11 12:08:54 | 显示全部楼层
回复【3楼】moline:
---------------------------------
我的页写函数如下:
//SPI在一页(0~65535)内写入少于256个字节的数据
//在指定地址开始写入最大256字节的数据
//pBuffer:数据存储区
//WriteAddr:开始写入的地址(24bit)
//NumByteToWrite:要写入的字节数(最大256),该数不应该超过该页的剩余字节数!!!  
void SPI_Flash_Write_Page(u8* pBuffer,u32 WriteAddr,u16 NumByteToWrite)
{
  u16 i;  
    SPI_FLASH_Write_Enable();                  //SET WEL 
SPI_FLASH_CS=0;                            //使能器件   
    SPI2_ReadWriteByte(W25X_PageProgram);      //发送写页命令   
    SPI2_ReadWriteByte((u8)((WriteAddr)>>16)); //发送24bit地址    
    SPI2_ReadWriteByte((u8)((WriteAddr)>>8));   
    SPI2_ReadWriteByte((u8)WriteAddr);   
    for(i=0;i<NumByteToWrite;i++)SPI2_ReadWriteByte(pBuffer);//循环写数  
SPI_FLASH_CS=1;                            //取消片选 
SPI_Flash_Wait_Busy();    //等待写入结束

该函数不能超过1页的内容,你看看我的SPI_Flash_Write_NoCheck,是如何调用页写的。
SPI_Flash_Write_NoCheck,这个函数也有详细说明,看说明就知道怎么用。
>
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

96

主题

247

帖子

1

精华

高级会员

Rank: 4

积分
801
金钱
801
注册时间
2012-6-29
在线时间
0 小时
 楼主| 发表于 2012-12-11 12:41:16 | 显示全部楼层
原子哥:
第一页:0-255,第二页256-511.
调用page写入函数,起始地址250,数据长度23.就要跨页了。
我用调用两次页写函数,第二个页写函数写不了数据。
我不是说你的代码有问题,而是我想用简单的方法写入数据。
结果发现,跨页写入,第二个页写函数写不进去,我实验过了。而且实验了很多天。
http://blog.tianya.cn/blogger/blog_main.asp?BlogID=4666068
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2012-12-11 13:27:15 | 显示全部楼层
写之前要确保页被可写。
也就是先擦除,其他没什么注意的了。
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-7-19 08:16

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表