OpenEdv-开源电子网

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

SPI实验 WW25QXX_Read 函数疑问

[复制链接]

9

主题

48

帖子

0

精华

初级会员

Rank: 2

积分
169
金钱
169
注册时间
2020-11-24
在线时间
38 小时
发表于 2021-3-7 17:04:40 | 显示全部楼层 |阅读模式
5金钱
你好,请问SPI实验中,为何扇区序号*4096就是24位的地址?具体在附代码中“???”下面那一行。感谢解答。
  1. u8 W25QXX_BUFFER[4096];        // 申请4KB的缓存空间         
  2. void W25QXX_Write(u8* pBuffer,u32 WriteAddr,u16 NumByteToWrite)   
  3. {
  4.         u32 secpos;
  5.         u16 secoff;
  6.         u16 secremain;          
  7.         u16 i;   
  8.         u8 * W25QXX_BUF;        // 所谓u8 *类型,就是存放u8 变量地址的类型  
  9.            W25QXX_BUF=W25QXX_BUFFER; // u8 * 类型指针变量指向该缓存空间的第一个地址              
  10.         secpos=WriteAddr/4096;//扇区地址  
  11.         secoff=WriteAddr%4096;//在扇区内的偏移
  12.         secremain=4096-secoff;//扇区剩余空间大小   
  13.         //printf("ad:%X,nb:%X\r\n",WriteAddr,NumByteToWrite);//测试用
  14.         if(NumByteToWrite<=secremain)secremain=NumByteToWrite;//不大于4096个字节
  15.         while(1)
  16.         {       
  17.                 // ????
  18.                 W25QXX_Read(W25QXX_BUF,secpos*4096,4096);//读出整个扇区的内容
  19.                 for(i=0;i<secremain;i++)//校验数据
  20.                 {
  21.                         if(W25QXX_BUF[secoff+i]!=0XFF)break;//需要擦除            
  22.                 }
  23.                 if(i<secremain)//需要擦除
  24.                 {
  25.                         W25QXX_Erase_Sector(secpos);//擦除这个扇区
  26.                         for(i=0;i<secremain;i++)           //复制
  27.                         {
  28.                                 W25QXX_BUF[i+secoff]=pBuffer[i];          
  29.                         }
  30.                         W25QXX_Write_NoCheck(W25QXX_BUF,secpos*4096,4096);//写入整个扇区  

  31.                 }
  32.                 else
  33.                         W25QXX_Write_NoCheck(pBuffer,WriteAddr,secremain);//写已经擦除了的,直接写入扇区剩余区间.                                   
  34.                 if(NumByteToWrite==secremain)
  35.                         break;//写入结束了
  36.                 else//写入未结束
  37.                 {
  38.                         secpos++;//扇区地址增1
  39.                         secoff=0;//偏移位置为0          

  40.                            pBuffer+=secremain;  //指针偏移
  41.                         WriteAddr+=secremain;//写地址偏移          
  42.                            NumByteToWrite-=secremain;                                //字节数递减
  43.                         if(NumByteToWrite>4096)secremain=4096;        //下一个扇区还是写不完
  44.                         else secremain=NumByteToWrite;                        //下一个扇区可以写完了
  45.                 }         
  46.         }         
  47. }
复制代码


最佳答案

查看完整内容[请看2#楼]

它这个意思不是说secpos*4096代表24位,它的意思是说这个模块可寻地址是24位的,有这么大的空间,您传入的地址要在这个范围,0~2^24-1地址范围内。
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

11

主题

314

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1039
金钱
1039
注册时间
2020-7-21
在线时间
258 小时
发表于 2021-3-7 17:04:41 | 显示全部楼层
shelden 发表于 2021-3-8 11:26
抱歉,打错了。已将问题中“24字节地址”修改 “24位地址”。我是从W25QXX_Read函数的定义,看到参数Read ...

它这个意思不是说secpos*4096代表24位,它的意思是说这个模块可寻地址是24位的,有这么大的空间,您传入的地址要在这个范围,0~2^24-1地址范围内。
回复

使用道具 举报

11

主题

314

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1039
金钱
1039
注册时间
2020-7-21
在线时间
258 小时
发表于 2021-3-8 10:38:15 | 显示全部楼层
16Mb字节,那么就有24位地址才能访问16Mb字节
回复

使用道具 举报

9

主题

48

帖子

0

精华

初级会员

Rank: 2

积分
169
金钱
169
注册时间
2020-11-24
在线时间
38 小时
 楼主| 发表于 2021-3-8 11:12:37 | 显示全部楼层
本帖最后由 shelden 于 2021-3-8 11:23 编辑
DFY 发表于 2021-3-8 10:38
16Mb字节,那么就有24位地址才能访问16Mb字节

你好,我知道16MByte=2^24Byte,所以需要24位来表示地址才能访问16MByte空间。我的疑惑是   扇区序号*4096   为何就是  24位的地址了   ???感谢回复。
回复

使用道具 举报

11

主题

314

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1039
金钱
1039
注册时间
2020-7-21
在线时间
258 小时
发表于 2021-3-8 11:15:18 | 显示全部楼层
扇区序号*4096是  24字节的地址    这个哪里的文档或者注释有提到吗,麻烦截图看下,谢谢
回复

使用道具 举报

9

主题

48

帖子

0

精华

初级会员

Rank: 2

积分
169
金钱
169
注册时间
2020-11-24
在线时间
38 小时
 楼主| 发表于 2021-3-8 11:26:21 | 显示全部楼层
DFY 发表于 2021-3-8 11:15
扇区序号*4096是  24字节的地址    这个哪里的文档或者注释有提到吗,麻烦截图看下,谢谢

抱歉,打错了。已将问题中“24字节地址”修改 “24位地址”。我是从W25QXX_Read函数的定义,看到参数ReadAddr是24位(Bit)的地址,所以有这个疑惑。为何secpos*4096就是24位了?
  1. //读取SPI FLASH  
  2. //在指定地址开始读取指定长度的数据
  3. //pBuffer:数据存储区
  4. //ReadAddr:开始读取的地址(24bit)
  5. //NumByteToRead:要读取的字节数(最大65535)
  6. void W25QXX_Read(u8* pBuffer,u32 ReadAddr,u16 NumByteToRead)   
  7. {
  8.         u16 i;                                                                                       
  9.         W25QXX_CS=0;                            //使能器件   
  10.     SPI1_ReadWriteByte(W25X_ReadData);         //发送读取命令   
  11.     SPI1_ReadWriteByte((u8)((ReadAddr)>>16));  //发送24bit地址   
  12.     SPI1_ReadWriteByte((u8)((ReadAddr)>>8));   
  13.     SPI1_ReadWriteByte((u8)ReadAddr);   
  14.     for(i=0;i<NumByteToRead;i++)
  15.         {
  16.         pBuffer[i]=SPI1_ReadWriteByte(0XFF);   //循环读数  
  17.     }
  18.         W25QXX_CS=1;                                                   
  19. }  
复制代码
感谢您的回复。
回复

使用道具 举报

9

主题

48

帖子

0

精华

初级会员

Rank: 2

积分
169
金钱
169
注册时间
2020-11-24
在线时间
38 小时
 楼主| 发表于 2021-3-9 08:45:33 | 显示全部楼层
DFY 发表于 2021-3-8 15:02
它这个意思不是说secpos*4096代表24位,它的意思是说这个模块可寻地址是24位的,有这么大的空间,您传入 ...

明白了!谢谢您!
回复

使用道具 举报

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

本版积分规则



关闭

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

正点原子公众号

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

GMT+8, 2025-2-28 12:42

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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