找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 230|回复: 3
收起左侧

w25q64数据读取全是ff,应该是没写入不进去,单片机程序在下面各位看下

[复制链接]
ID:1104542 发表于 2024-4-10 00:22 | 显示全部楼层 |阅读模式
大佬们来看一下,
单片机源程序如下:
#include "w25q128.h"


/************************************************************************/
void SPI_init(void)
{
    SPI_CE_High();
    CLK_FLASH = 0;    // set clock to low initial state
    DI_FLASH = 1;
}


/************************************************************************/
void SPI_WriteByte(u8 out)
{
    u8 i;
    i = 8;
    do{
        out <<= 1;
        DI_FLASH  = CY;
        CLK_FLASH = 1;
        CLK_FLASH = 0;
    }while(--i);
    DI_FLASH = 1;
}

/************************************************************************/
u8 SPI_ReadByte(void)
{
    u8 i, in;
    i = 8;
    do{
        in <<= 1;
        if (DO_FLASH) in++;
        CLK_FLASH = 1;
        CLK_FLASH = 0;
    }while(--i);
    return in;
}


/************************************************
检测Flash是否准备就绪
入口参数: 无
出口参数:
    0 : 没有检测到正确的Flash
    1 : Flash准备就绪
************************************************/
void FlashCheckID(void)
{
        u16 ID,ID1,ID2;
    SPI_CE_Low();
    SPI_WriteByte(SFC_RDID);        //发送读取ID命令
    SPI_WriteByte(0x00);            //空读3个字节
    SPI_WriteByte(0x00);
    SPI_WriteByte(0x00);
    ID = SPI_ReadByte();         //读取制造商ID1
    ID1  = SPI_ReadByte();         //读取设备ID
    ID2 = SPI_ReadByte();         //读取制造商ID2
    SPI_CE_High();
        printf("ID:%x,ID1:%x,ID2:%x\r\n",ID,ID1,ID2);
}


/************************************************
检测Flash的忙状态
入口参数: 无
出口参数:
    0 : Flash处于空闲状态
    1 : Flash处于忙状态
************************************************/
u8  CheckFlashBusy(void)
{
    u8  dat;

    SPI_CE_Low();
    SPI_WriteByte(SFC_RDSR);        //发送读取状态命令
    dat = SPI_ReadByte();           //读取状态
    SPI_CE_High();

    return (dat);                   //状态值的Bit0即为忙标志
}

/************************************************
使能Flash写命令
入口参数: 无
出口参数: 无
************************************************/
void FlashWriteEnable(void)
{
    while(CheckFlashBusy() > 0);    //Flash忙检测
    SPI_CE_Low();
    SPI_WriteByte(SFC_WREN);        //发送写使能命令
    SPI_CE_High();
}

/************************************************
禁止Flash写使能命令
入口参数: 无
出口参数: 无
************************************************/

void FlashWriteDisable(void)
{
    while(CheckFlashBusy() > 0);    //Flash忙检测
    SPI_CE_Low();
    SPI_WriteByte(SFC_WRDI);        //发送写使能命令
    SPI_CE_High();
}


/************************************************
擦除扇区, 一个扇区4KB
入口参数: 无
出口参数: 无
************************************************/
void FlashSectorErase(u32 addr)
{
        FlashWriteEnable();             //使能Flash写命令
        SPI_CE_Low();
        SPI_WriteByte(SFC_SECTORER2);    //发送扇区擦除命令
        SPI_WriteByte(((u8 *)&addr)[1]);           //设置起始地址
        SPI_WriteByte(((u8 *)&addr)[2]);
        SPI_WriteByte(((u8 *)&addr)[3]);
        SPI_CE_High();
                while(CheckFlashBusy() > 0);
                FlashWriteDisable();
}

/************************************************
从Flash中读取数据
入口参数:
    addr   : 地址参数
    buffer : 缓冲从Flash中读取的数据
    len   : 数据块大小
出口参数:
    无
************************************************/
void SPI_Read_Nbytes(u32 addr, u8 *buffer, u16 len)
{
        u16 i;
    while(CheckFlashBusy() > 0);        //Flash忙检测
    SPI_CE_Low();                       //enable device
    SPI_WriteByte(SFC_READ);            //read command

        SPI_WriteByte((addr & 0xFF0000) >> 16);
    SPI_WriteByte((addr & 0xFF00) >> 8);
    SPI_WriteByte(addr & 0xFF);
        for (i = 0; i < len; i++)
        {
                buffer[ i]= SPI_ReadByte();
        }
    SPI_CE_High();                      //disable device
}

/************************************************************************
读出n个字节,跟指定的数据进行比较, 错误返回1,正确返回0
************************************************************************/
u8  SPI_Read_Compare(u32 addr, u8 *buffer, u16 len)
{
    u8  j;
    if(len == 0)   return 2;
    while(CheckFlashBusy() > 0);            //Flash忙检测

    j = 0;
    SPI_CE_Low();                           //enable device
    SPI_WriteByte(SFC_READ);                //read command
    SPI_WriteByte(((u8 *)&addr)[1]);        //设置起始地址
    SPI_WriteByte(((u8 *)&addr)[2]);
    SPI_WriteByte(((u8 *)&addr)[3]);
    do
    {
        if(*buffer != SPI_ReadByte())       //receive byte and store at buffer
        {
            j = 1;
            break;
        }
        buffer++;
    }while(--len);         //read until no_bytes is reached
    SPI_CE_High();          //disable device
    return j;
}


/************************************************
写数据到Flash中
入口参数:
    addr   : 地址参数
    buffer : 缓冲需要写入Flash的数据
    len   : 数据块大小
出口参数: 无
************************************************/
void SPI_Write_Nbytes(u32 addr, u8 *buffer, u8 len)
{
        u16 i;
    while(CheckFlashBusy() > 0);        //Flash忙检测
    FlashWriteEnable();                 //使能Flash写命令
    SPI_CE_Low();                       // enable device
    SPI_WriteByte(SFC_PAGEPROG);        // 发送页编程命令
        SPI_WriteByte((addr & 0xFF0000) >> 16);
    SPI_WriteByte((addr & 0xFF00) >> 8);
    SPI_WriteByte(addr & 0xFF);
        for (i = 0; i < len; i++)
        {
                SPI_WriteByte(buffer[ i]);
        }        
    SPI_CE_High();                      // disable device
        while(CheckFlashBusy() > 0);
        FlashWriteDisable();
}

//////////////////////////////////主函数//////////////


code const unsigned char arr[200] = {
        0X00,        0X00,        0X00,        0X00,        0X00,        0X00,        0X00,        0X00,        0X00,        0X00,
        0X00,        0X04,        0X00,        0X00,        0X00,        0X04,        0X00,        0X70,        0X00,        0X40,
        0X04,        0X00,        0X04,        0X00,        0X04,        0X00,        0X07,        0X00,        0X00,        0X00,
        0X00,        0X04,        0X00,        0X00,        0X70,        0X00,        0X07,        0X00,        0X00,        0X00,
        0X00,        0X00,        0X00,        0X07,        0X70,        0X00,        0X77,        0X00,        0X00,        0X00,
        0X00,        0X00,        0X70,        0X07,        0X77,        0X77,        0X77,        0X77,        0X00,        0X00,
        0X00,        0X00,        0X07,        0X77,        0X77,        0X77,        0X77,        0X70,        0X70,        0X00,
        0X00,        0X77,        0X77,        0X00,        0X00,        0X77,        0X77,        0X00,        0X00,        0X00,
        0X00,        0X00,        0X70,        0X70,        0X00,        0X77,        0X77,        0X00,        0X00,        0X00,
        0X00,        0X07,        0X70,        0X70,        0X00,        0X07,        0X77,        0X00,        0X07,        0X00,
        0X07,        0X77,        0X00,        0X00,        0X00,        0X07,        0X77,        0X70,        0X70,        0X00,
        0X00,        0X70,        0X00,        0X40,        0X00,        0X07,        0X77,        0X77,        0X00,        0X00,
        0X00,        0X00,        0X00,        0X00,        0X40,        0X07,        0X77,        0X77,        0X00,        0X00,
        0X00,        0X40,        0X00,        0X00,        0X00,        0X07,        0X77,        0X77,        0X00,        0X00,
        0X00,        0X00,        0X00,        0X00,        0X00,        0X07,        0X70,        0X77,        0X70,        0X00,
        0X00,        0X00,        0X00,        0X40,        0X00,        0X07,        0X00,        0X00,        0X07,        0X00,
        0X00,        0X00,        0X00,        0X00,        0X00,        0X00,        0X00,        0X00,        0X00,        0X00,
        0X00,        0X00,        0X40,        0X00,        0X40,        0X00,        0X00,        0X00,        0X00,        0X00,
        0X00,        0X00,        0X00,        0X00,        0X00,        0X00,        0X00,        0X40,        0X00,        0X00,
        0X00,        0X00,        0X00,        0X00,        0X00,        0X00,        0X00,        0X00,        0X00,        0X00,

};

void main(void)
{
        xdata unsigned char read_dat[256];
//        EA = 1;
        UartInit();
        io_init();
    SPI_init();
    FlashCheckID();
        FlashSectorErase(0x011000); //每次可以擦除一个扇区。4KB
        delay_ms(500);
        SPI_Write_Nbytes(0x011000,arr,200);
        delay_ms(100);
        SPI_Read_Nbytes(0x011000, read_dat,200);  
        delay_ms(100);
        UartSend(read_dat,200);
        
        P03=0;
        while(1);
}

回复

使用道具 举报

ID:226055 发表于 2024-4-10 09:26 | 显示全部楼层
    1、不知你的硬件连接是怎样的,一定注意假如使用的是外部FLASH模块,然后与单片机之间连接尽可能不要使用杜邦线。个人有测试过,杜邦线会导致读取数据失败。、
    2、排除硬件问题,还要考虑操作问题,那就是在写数据之前一定要先擦除(即将存储区域数据置为1),因为FLASH的特点是可将存储数据1变为0,但没办法实现从0变为1。
    3、要考虑软件设计的问题,下面给出的是艾克姆W25Q128的程序(兼容W25Q64)供参考,PDF文档写得非常好,附件和程序一起供参考。
程序截图1.jpg 程序截图2.jpg

spi_w25q128_sw.rar

26.13 KB, 下载次数: 2

实验2-13:SPI总线的应用.pdf

2.56 MB, 下载次数: 2

回复

使用道具 举报

ID:1104542 发表于 2024-4-10 13:50 | 显示全部楼层
cocolala 发表于 2024-4-10 09:26
1、不知你的硬件连接是怎样的,一定注意假如使用的是外部FLASH模块,然后与单片机之间连接尽可能不要使 ...

谢谢大佬,我来根据你发的测试下
回复

使用道具 举报

ID:1104542 发表于 2024-4-10 21:37 | 显示全部楼层
cocolala 发表于 2024-4-10 09:26
1、不知你的硬件连接是怎样的,一定注意假如使用的是外部FLASH模块,然后与单片机之间连接尽可能不要使 ...

按这个例程是w25q64刚写入可以读取,其他地址多写几次之后,开始的就读不出来了显示的FF,换了一个也一样,但最后一次写入的可以读出来
回复

使用道具 举报

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

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

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