OpenEdv-开源电子网

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

W25Q64无法写入

[复制链接]

12

主题

44

帖子

0

精华

初级会员

Rank: 2

积分
102
金钱
102
注册时间
2013-12-22
在线时间
1 小时
发表于 2014-7-21 21:05:42 | 显示全部楼层 |阅读模式
5金钱
我用的是SPI1,和触摸屏共用SPI1,初始化以及Flash部分的代码完全使用的原子哥《原子教你玩STM32(库函数版)》SPI实验的,


TP_DCS是关闭触屏的片选,然后调用读取ID函数返回的ID值不是0xffff就是0,写了数据进去读出的数据也任然全是255
FLASH部分代码
[mw_shl_code=c,true]u8 SPI1_ReadWriteByte(u8 TxData) { u8 retry=0; while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET) //检查指定的SPI标志位设置与否:发送缓存空标志位 { retry++; if(retry>200)return 0; } SPI_I2S_SendData(SPI1, TxData); //通过外设SPIx发送一个数据 retry=0; while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET) //检查指定的SPI标志位设置与否:接受缓存非空标志位 { retry++; if(retry>200)return 0; } return SPI_I2S_ReceiveData(SPI1); //返回通过SPIx最近接收的数据 } u16 SPI_FLASH_TYPE;//默认就是25Q64 //读取SPI_FLASH的状态寄存器 //BIT7 6 5 4 3 2 1 0 //SPR RV TB BP2 BP1 BP0 WEL BUSY //SPR:默认0,状态寄存器保护位,配合WP使用 //TB,BP2,BP1,BP0:FLASH区域写保护设置 //WEL:写使能锁定 //BUSY:忙标记位(1,忙;0,空闲) //默认:0x00 u8 SPI_Flash_ReadSR(void) { u8 byte=0; SPI_FLASH_CS=0; //使能器件 SPI1_ReadWriteByte(W25X_ReadStatusReg); //发送读取状态寄存器命令 byte=SPI1_ReadWriteByte(0Xff); //读取一个字节 SPI_FLASH_CS=1; //取消片选 return byte; } //写SPI_FLASH状态寄存器 //只有SPR,TB,BP2,BP1,BP0(bit 7,5,4,3,2)可以写!!! void SPI_FLASH_Write_SR(u8 sr) { SPI_FLASH_CS=0; //使能器件 SPI1_ReadWriteByte(W25X_WriteStatusReg); //发送写取状态寄存器命令 SPI1_ReadWriteByte(sr); //写入一个字节 SPI_FLASH_CS=1; //取消片选 } //SPI_FLASH写使能 //将WEL置位 void SPI_FLASH_Write_Enable(void) { SPI_FLASH_CS=0; //使能器件 SPI1_ReadWriteByte(W25X_WriteEnable); //发送写使能 SPI_FLASH_CS=1; //取消片选 } //SPI_FLASH写禁止 //将WEL清零 void SPI_FLASH_Write_Disable(void) { SPI_FLASH_CS=0; //使能器件 SPI1_ReadWriteByte(W25X_WriteDisable); //发送写禁止指令 SPI_FLASH_CS=1; //取消片选 } //读取芯片ID W25X16的ID:0XEF14 u16 SPI_Flash_ReadID(void) { u16 Temp = 0; SPI_FLASH_CS=0; SPI1_ReadWriteByte(0x90);//发送读取ID命令 SPI1_ReadWriteByte(0x00); SPI1_ReadWriteByte(0x00); SPI1_ReadWriteByte(0x00); Temp|=SPI1_ReadWriteByte(0xFF)<<8; Temp|=SPI1_ReadWriteByte(0xFF); SPI_FLASH_CS=1; return Temp; } //读取SPI FLASH //在指定地址开始读取指定长度的数据 //pBuffer:数据存储区 //ReadAddr:开始读取的地址(24bit) //NumByteToRead:要读取的字节数(最大65535) void SPI_Flash_Read(u8* pBuffer,u32 ReadAddr,u16 NumByteToRead) { u16 i; SPI_FLASH_CS=0; //使能器件 SPI1_ReadWriteByte(W25X_ReadData); //发送读取命令 SPI1_ReadWriteByte((u8)((ReadAddr)>>16)); //发送24bit地址 SPI1_ReadWriteByte((u8)((ReadAddr)>>8)); SPI1_ReadWriteByte((u8)ReadAddr); for(i=0;i<NumByteToRead;i++) { pBuffer=SPI1_ReadWriteByte(0XFF); //循环读数 // pBuffer=SPI_WriteByte(0XFF); //循环读数 printf( "pBuffer[%d]=",i); printf( "%d",pBuffer); } SPI_FLASH_CS=1; //取消片选 } //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; //使能器件 SPI1_ReadWriteByte(W25X_PageProgram); //发送写页命令 SPI1_ReadWriteByte((u8)((WriteAddr)>>16)); //发送24bit地址 SPI1_ReadWriteByte((u8)((WriteAddr)>>8)); SPI1_ReadWriteByte((u8)WriteAddr); for(i=0;i<NumByteToWrite;i++)SPI1_ReadWriteByte(pBuffer);//循环写数 SPI_FLASH_CS=1; //取消片选 SPI_Flash_Wait_Busy(); //等待写入结束 } //无检验写SPI FLASH //必须确保所写的地址范围内的数据全部为0XFF,否则在非0XFF处写入的数据将失败! //具有自动换页功能 //在指定地址开始写入指定长度的数据,但是要确保地址不越界! //pBuffer:数据存储区 //WriteAddr:开始写入的地址(24bit) //NumByteToWrite:要写入的字节数(最大65535) //CHECK OK void SPI_Flash_Write_NoCheck(u8* pBuffer,u32 WriteAddr,u16 NumByteToWrite) { u16 pageremain; pageremain=256-WriteAddr%256; //单页剩余的字节数 if(NumByteToWrite<=pageremain)pageremain=NumByteToWrite;//不大于256个字节 while(1) { SPI_Flash_Write_Page(pBuffer,WriteAddr,pageremain); if(NumByteToWrite==pageremain)break;//写入结束了 else //NumByteToWrite>pageremain { pBuffer+=pageremain; WriteAddr+=pageremain; NumByteToWrite-=pageremain; //减去已经写入了的字节数 if(NumByteToWrite>256)pageremain=256; //一次可以写入256个字节 else pageremain=NumByteToWrite; //不够256个字节了 } }; } //写SPI FLASH //在指定地址开始写入指定长度的数据 //该函数带擦除操作! //pBuffer:数据存储区 //WriteAddr:开始写入的地址(24bit) //NumByteToWrite:要写入的字节数(最大65535) u8 SPI_FLASH_BUF[4096]; void SPI_Flash_Write(u8* pBuffer,u32 WriteAddr,u16 NumByteToWrite) { u32 secpos; u16 secoff; u16 secremain; u16 i; secpos=WriteAddr/4096;//扇区地址 0~511 for w25x16 secoff=WriteAddr%4096;//在扇区内的偏移 secremain=4096-secoff;//扇区剩余空间大小 if(NumByteToWrite<=secremain)secremain=NumByteToWrite;//不大于4096个字节 while(1) { SPI_Flash_Read(SPI_FLASH_BUF,secpos*4096,4096);//读出整个扇区的内容 for(i=0;i<secremain;i++)//校验数据 { if(SPI_FLASH_BUF[secoff+i]!=0XFF)break;//需要擦除 } if(i<secremain)//需要擦除 { SPI_Flash_Erase_Sector(secpos);//擦除这个扇区 for(i=0;i<secremain;i++) //复制 { SPI_FLASH_BUF[i+secoff]=pBuffer; } SPI_Flash_Write_NoCheck(SPI_FLASH_BUF,secpos*4096,4096);//写入整个扇区 }else SPI_Flash_Write_NoCheck(pBuffer,WriteAddr,secremain);//写已经擦除了的,直接写入扇区剩余区间. if(NumByteToWrite==secremain)break;//写入结束了 else//写入未结束 { secpos++;//扇区地址增1 secoff=0;//偏移位置为0 pBuffer+=secremain; //指针偏移 WriteAddr+=secremain;//写地址偏移 NumByteToWrite-=secremain; //字节数递减 if(NumByteToWrite>4096)secremain=4096; //下一个扇区还是写不完 else secremain=NumByteToWrite; //下一个扇区可以写完了 } }; } //擦除整个芯片 //整片擦除时间: //W25X16:25s //W25X32:40s //W25X64:40s //等待时间超长... void SPI_Flash_Erase_Chip(void) { SPI_FLASH_Write_Enable(); //SET WEL SPI_Flash_Wait_Busy(); SPI_FLASH_CS=0; //使能器件 SPI1_ReadWriteByte(W25X_ChipErase); //发送片擦除命令 SPI_FLASH_CS=1; //取消片选 SPI_Flash_Wait_Busy(); //等待芯片擦除结束 } //擦除一个扇区 //Dst_Addr:扇区地址 0~511 for w25x16 //擦除一个山区的最少时间:150ms void SPI_Flash_Erase_Sector(u32 Dst_Addr) { Dst_Addr*=4096; SPI_FLASH_Write_Enable(); //SET WEL SPI_Flash_Wait_Busy(); SPI_FLASH_CS=0; //使能器件 SPI1_ReadWriteByte(W25X_SectorErase); //发送扇区擦除指令 SPI1_ReadWriteByte((u8)((Dst_Addr)>>16)); //发送24bit地址 SPI1_ReadWriteByte((u8)((Dst_Addr)>>8)); SPI1_ReadWriteByte((u8)Dst_Addr); SPI_FLASH_CS=1; //取消片选 SPI_Flash_Wait_Busy(); //等待擦除完成 } //等待空闲 void SPI_Flash_Wait_Busy(void) { while ((SPI_Flash_ReadSR()&0x01)==0x01); // 等待BUSY位清空 } //进入掉电模式 void SPI_Flash_PowerDown(void) { SPI_FLASH_CS=0; //使能器件 SPI1_ReadWriteByte(W25X_PowerDown); //发送掉电命令 SPI_FLASH_CS=1; //取消片选 delay_us(3); //等待TPD } //唤醒 void SPI_Flash_WAKEUP(void) { SPI_FLASH_CS=0; //使能器件 SPI1_ReadWriteByte(W25X_ReleasePowerDown); // send W25X_PowerDown command 0xAB SPI_FLASH_CS=1; //取消片选 delay_us(3); //等待TRES1 } [/mw_shl_code]

哪管多少辛酸已获胜算!
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

12

主题

44

帖子

0

精华

初级会员

Rank: 2

积分
102
金钱
102
注册时间
2013-12-22
在线时间
1 小时
 楼主| 发表于 2014-7-21 21:35:14 | 显示全部楼层
好奇葩,刚重新下了下代码,运行第一次,读出EFFF的ID,复位一次居然正确了!!!写进去的字符串读出来也没问题,我程序设置成读出后显示然后就While(1);停在那了,所以我按板子的复位键,结果读出的ID又变成了2020!再怎么复位也一直显示2020!但是断电重开,又是运行第一次,读出EFFF的ID,复位一下又正常了,再复位就又变2020了!另外,写入的时候有一个把整个扇区读出来的过程,我就把整个扇区全打印出来,发现有些地方我没写过的地方居然是0,擦除扇区后还是有个别有0的,这是什么情况?
哪管多少辛酸已获胜算!
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2014-7-21 23:39:49 | 显示全部楼层
把你的触摸屏拔了,在测试下。
看看是不是触摸屏干扰了
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复

使用道具 举报

12

主题

44

帖子

0

精华

初级会员

Rank: 2

积分
102
金钱
102
注册时间
2013-12-22
在线时间
1 小时
 楼主| 发表于 2014-7-23 10:43:58 | 显示全部楼层
回复【3楼】正点原子:
---------------------------------
拔了也没用,我怀疑是不是布线的问题,线布得很细,而且是自动布线的,中间走了过孔,会不会是这原因导致的?但是触摸屏的走线还更远,信号线先从单片机到W25Q64引脚然后才到的触摸屏,而触摸屏是正常的,,,无解
哪管多少辛酸已获胜算!
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2014-7-23 23:14:27 | 显示全部楼层
回复【4楼】雪噬剑:
---------------------------------
过孔一般不会有问题.
拔了还不行,那说明不是LCD的影响了.
再检查配置和电路吧.
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复

使用道具 举报

12

主题

44

帖子

0

精华

初级会员

Rank: 2

积分
102
金钱
102
注册时间
2013-12-22
在线时间
1 小时
 楼主| 发表于 2014-7-24 12:45:14 | 显示全部楼层
回复【5楼】正点原子:
---------------------------------
配置就如上面贴的代码所示,电路也直接参考的战舰板的,何况它有时有用,说明应该电路连接是对的啊~
哪管多少辛酸已获胜算!
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2014-7-24 23:38:33 | 显示全部楼层
回复【6楼】雪噬剑:
---------------------------------
检测下走线看看.
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复

使用道具 举报

2

主题

15

帖子

0

精华

初级会员

Rank: 2

积分
73
金钱
73
注册时间
2014-9-17
在线时间
7 小时
发表于 2015-10-24 20:41:34 | 显示全部楼层
回复【7楼】正点原子:
---------------------------------
走线会怎么干扰? 尽管SPI数据线上有些杂波,但是读取是正常的,但在写使能操作中,始终无法另状态位上的WEL置位为1.使用的是标准的SPI,且读出来的两个寄存器的值全为0,也就是说完全没有任何Memory Protection。
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2015-10-25 22:01:38 | 显示全部楼层
回复【8楼】zi_yang:
---------------------------------
这得慢慢查了
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复

使用道具 举报

12

主题

44

帖子

0

精华

初级会员

Rank: 2

积分
102
金钱
102
注册时间
2013-12-22
在线时间
1 小时
 楼主| 发表于 2015-10-26 00:29:45 | 显示全部楼层
这个问题后面搁置了,在后面觉得该换块w25q64的时候把焊盘搞掉了,然后项目脱手了~
哪管多少辛酸已获胜算!
回复

使用道具 举报

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

本版积分规则



关闭

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

正点原子公众号

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

GMT+8, 2025-6-20 02:34

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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