OpenEdv-开源电子网

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

求助。W25X40芯片的读写问题

[复制链接]

29

主题

70

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
354
金钱
354
注册时间
2013-12-17
在线时间
80 小时
发表于 2016-8-10 16:59:55 | 显示全部楼层 |阅读模式
10金钱

//模拟SPI写操作
void SPI_WriteByte(uchar TxData)
{
        unsigned char i;
          for(i=0;i<8;i++)
    {
      if(TxData&0x80)
      {
              SW25X_DO();
      }
      else
      {
              CW25X_DO();
      }
      CW25X_CLK();
      SW25X_CLK();
      TxData<<=1;
    }
}
//模拟SPI读操作
uchar SPI_ReadByte(void)
{
       
        unsigned char i,temp_data = 0;
        unsigned long tmp;
          for(i=0;i<8;i++)
    {
      SW25X_CLK();
      CW25X_CLK();
      temp_data<<=1;
      tmp = IOPIN1;
      tmp &= W25X_DI;
      if(tmp)
        temp_data=temp_data|0x01;
    }
          return temp_data;
}

//读器件ID        W25X40 = 0xEF12
uint W25X40_ReadID(void)
{
        uint ID = 0;
        CW25X_CS();                                                                //使能器件

        SPI_WriteByte(W25X_ManufactDeviceID);        //《设备ID》指令
        SPI_WriteByte(0x00);
        SPI_WriteByte(0x00);
        SPI_WriteByte(0x00);

        ID |= SPI_ReadByte()<<8;                                //读取ID
        ID |= SPI_ReadByte();
        SW25X_CS();                                                                //失能器件
        return ID;
}
       
//写页程序
void W25X40_WritePage(uchar * pBuffer, uint WriteAddr, uint nByte)
{
        W25X40_WRITE_ENABLE();                                                //写使能

        CW25X_CS();                                                                        //使能器件
        SPI_WriteByte(W25X_PageProgram);                        //《页编程》指令
        SPI_WriteByte((uchar)((WriteAddr)>>16));        //发送24bit地址
        SPI_WriteByte((uchar)((WriteAddr)>>8));
        SPI_WriteByte((uchar)WriteAddr);

        while (nByte--)
        {
                SPI_WriteByte(*pBuffer);
                pBuffer++;
        }

        SW25X_CS();
        W25X40_WaitForNoBusy();                                                //等待空闲(等待写入结束)
}

void W25X40_WriteSR(uchar SR)
{
        W25X40_WRITE_ENABLE();                                        //写使能
        SPI_WriteByte(W25X_WriteStatusReg);                //《写状态寄存器》指令
        SPI_WriteByte(SR);                                                //写入一个字节
        SW25X_CS();                                                                //失能器件
}

uchar W25X40_ReadSR(void)
{
        uchar data_tmp;
        CW25X_CS();                                                                //使能器件
        SPI_WriteByte(W25X_ReadStatusReg);                //《读状态寄存器》指令
        data_tmp = SPI_ReadByte();                                //读取一个字节
        SW25X_CS();                                                                //失能器件
        return data_tmp;
}

void W25X40_EraseSector(uint SectorAddr)
{
        SectorAddr *= 4096;                                                //扇区首地址
        W25X40_WRITE_ENABLE();                                        //写使能
        W25X40_WaitForNoBusy();
        CW25X_CS();                                                                //使能器件
        SPI_WriteByte(W25X_SectorErase);                                //《擦除扇区》指令
        SPI_WriteByte((uchar)((SectorAddr)>>16));                //擦除地址
        SPI_WriteByte((uchar)((SectorAddr)>>8));
        SPI_WriteByte((uchar)SectorAddr);
        SW25X_CS();

        W25X40_WaitForNoBusy();                                                        //等待擦除完成
}

void W25X40_ReadOneByte(uchar *pBuffer, uint ReadAddr, uint nByte)
{
        uint i;                                                                                       
        CW25X_CS();
    SPI_WriteByte(W25X_ReadData);                                //《读数据》指令
        SPI_WriteByte((uchar)((ReadAddr)>>16));                //发送24bit地址
        SPI_WriteByte((uchar)((ReadAddr)>>8));
        SPI_WriteByte((uchar)ReadAddr);
    for(i=0;i<nByte;i++)
        {
                pBuffer[i] = SPI_ReadByte();                        //读取出的数据存进缓存区
    }
        SW25X_CS();
}

//测试读写子程序
void main(void)
{
        while(1)
        {
                if(W25X40_ReadID() == 0xEF12)                //确认ID
            {
                    W25X40_ReadOneByte(W25X40_read_buf,0,10);                        //每次先读取参数
                    for(i=0;i<10;i++)                                //判断是否有数据
                    {
                            if(W25X40_read_buf[i] != 0xff) break;
                    }
                    if(i<10)                //若有数据在里面,则写入0123456789
                    {
                            W25X40_EraseSector(0);                //擦除扇区
                            W25X40_ReadOneByte(W25X40_read_buf,0,10);
                            copymovedata(telphone_book_buf,"0123456789",10);        //写入存储器,将0123456789复制到telphone_book_buf缓存
                            W25X40_WritePage(telphone_book_buf,0,10);                        //写操作
                            copymovedata(telphone_book_buf,"1111111111",10);        //修改缓存区
                    }
                    else                        //若里面无数据,则写入9876543210
                    {
                            copymovedata(telphone_book_buf,"9876543210",10);        //写入存储器,将9876543210复制到telphone_book_buf缓存
                            W25X40_WritePage(telphone_book_buf,0,10);                        //写操作
                            copymovedata(telphone_book_buf,"0000000000",10);        //修改缓存区
                    }
                }
        }
}

模拟SPI口进行读写,
问题是这样的,上电读取芯片ID,确认是W25X40的ID,进行读取操作,第一次上电的时候读出来都是0xff,确认是空,所以进行写操作,将9876543210写进存储芯片,再读一次,确认已经写进。然后断电重新进行读操作,发现读出的数据还是0xff,然后再将9876543210写进存储芯片,不断电再读一次,发现读出的值是对的“9876543210”。
每闪重新上电,取出的值都是0xff!!是数据根本没有写进去吗?写子程序不对?读取芯片ID都是对的呀。。



正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165524
金钱
165524
注册时间
2010-12-1
在线时间
2116 小时
发表于 2016-8-10 16:59:56 | 显示全部楼层
回复

使用道具 举报

29

主题

70

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
354
金钱
354
注册时间
2013-12-17
在线时间
80 小时
 楼主| 发表于 2016-8-11 09:53:46 | 显示全部楼层
void W25X40_ReadOneByte(uchar *pBuffer, uint ReadAddr, uint nByte)
{
        uint i;                                                                                       
        CW25X_CS();
    SPI_WriteByte(W25X_ReadData);                                //《读数据》指令
        SPI_WriteByte((uchar)((ReadAddr)>>16));                //发送24bit地址
        SPI_WriteByte((uchar)((ReadAddr)>>8));
        SPI_WriteByte((uchar)ReadAddr);
    for(i=0;i<nByte;i++)
        {
                pBuffer[i] = SPI_ReadByte();                        //读取出的数据存进缓存区
    }
        SW25X_CS();
}

读操作就用这个函数可以吗?应该没有其他需要设置的寄存器了吧
回复

使用道具 举报

29

主题

70

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
354
金钱
354
注册时间
2013-12-17
在线时间
80 小时
 楼主| 发表于 2016-8-12 08:17:25 | 显示全部楼层

谢谢原子大大帮顶。问题找出来了。
板子是用Ulink2仿真的,在仿真的时候点KEIL的复位键。貌似系统还会跑一段代码,而这段代码整好有个擦除扇区的操作,虽然每次复位都会把之前写的数据擦除。至于为什么会按复位键后还会执行代码,这个不清楚,求牛人解释。。
回复

使用道具 举报

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

本版积分规则



关闭

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

正点原子公众号

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

GMT+8, 2025-6-7 22:35

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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