使用了MX25L512的SPI接口的Flash

电路连接图:

总的大小512kb,即64kB,sector的大小为256 Bytes,block的大小为4k Bytes

调试时出现的问题:

1、Flash只能读数据,不能写数据

根源在于Flash的软件写保护没有去掉,这样,写、擦除,甚至写状态寄存器都不能执行。

1)Hardware Protection

Hardware Protection Mode(HPM):by using WP# going low to protect the BP0-BP1 bits and SRWD bit from data change

因为WP#是高电平,所以没有硬件保护,再来看软件保护。

2)Software Protection

Software Protection Mode(SPM):by using BP0-BP1 bits to set the part of flash protected from data change

通过下面几幅图可知,在WP#高电平情况下write status register可以改变SRWD、BP0、BP1的值为0,从而去掉软件写保护。

3)代码实现去除保护

//在所有需要修改的操作之前必须去除软件保护BP0,BP1
//FLASH的状态寄存器
//bit7        bit6    bit5    bit4    bit3    bit2    bit1            bit0
//SRWD        0         0          0        BP1        BP0        WEL                WIP
// 1=status write disable                            1=write enable    1=write in process
#define MASK_CLEAR_BPX 0x73    //掩码,设置使能写状态寄存器,清除BP1、BP0
void SPI_WRITE_STATUS()     //主要是清除保护,可以写数据
{
    unsigned ;
    SPI_WRITE_ENABLE();    //设置状态器WEL位为1,在进行写状态寄存器之前必须写使能
    status=SPI_READ_STATUS();

    NSSMD0=;
    SPI0DAT=FLASH_WRITE_STATUS;
    while(!SPIF);
    SPIF=;

    SPI0DAT=status&MASK_CLEAR_BPX;
    while(!SPIF);
    SPIF=;

    NSSMD0=;//cs must go high at the byte boundary,otherwise instruction will be reject and not executed

    do        //query until WIP convert from 1 to 0 when write status register cycle is finished
    {
        status=SPI_READ_STATUS();
        status=status&0x01;
    }while(status);
}

2、sector大小为256 Bytes,但是连续写256 Bytes,只有最后的32 Bytes写进去了

在测试MX25L512的扇区的时候,老是遇到一个问题,写入256个字节,但是读出的是最后32个Bytes,前面的总是0xFF,于是就怀疑是不是扇区

的大小没有datasheet所说的那么大呢?最后测试发现扇区的大小只有32Bytes,如果连续写入的字节数大于32 Bytes,就会把除最后32 Bytes之外

的数据丢弃,只写最后的32 Bytes。仔细翻看datasheet,发现MX25L512MC-12G的扇区为256 Bytes,而MX25L512IE的扇区只有32Bytes原来具体

芯片规格和元件后缀名也有关系。

说明:sector是读写数据的最小单元,block是擦除的最小单元。(有时候sector概念类似于page,要看具体的芯片)

扇区被擦除后内部的数据变为0xFF。

3、SPI接口波形不对

虽然C8051F320已经交叉配置为串口和SPI接口,但是实际情况是还是要在输出的管脚PushPull,

P0MDOUT=0x1D;//0001 1101

否则可能SPI口的OUT输出驱动不了,导致波形都没有。

贴上Flash操作的代码:

#ifndef _SPI_CMD_H_
#define _SPI_CMD_H_

#include"misc.h"
////////////////////////////////////////////////
//////////////////MX25L512的flash说明///////////////////
//page:256byte
//sector:4kbyte
//注意MX25L512MC-12G page为256 bytes
//MX25L512IE.. page为32 bytes
///////////////////////////////////////////////

#define FLASH_READ_ID            0x9F     //读设备ID
#define FLASH_WRITE_ENABLE     0x06    //写使能
#define FLASH_WRITE_DISABLE     0x04    //写禁止
#define FLASH_READ_STATUS         0x05    //读状态寄存器
#define FLASH_WRITE_STATUS    0x01    //写状态寄存器
#define FLASH_READ_DATA        0x03    //读数据
#define FLASH_WRITE_DATA         0x02    //写数据
#define FLASH_SECTOR_ERASE     0x20    //擦除一个扇区

];//缓冲区全局变量,可以保存一个page的256字节
//在头文件中只是申明一下,不能定义,定义变量要在相应的C文件中定义
//以上不然会报错:multiple public definitions

void SPI_READ_ID();
void SPI_WRITE_ENABLE();
void SPI_WRITE_DISABLE();
unsigned char SPI_READ_STATUS();
void SPI_WRITE_STATUS();
void SPI_SECTOR_ERASE(unsigned char sectors);
void SPI_READ_Page(unsigned char sectors,unsigned char pages);
void SPI_WRITE_Page(unsigned char *str,unsigned char sectors,unsigned char pages);
void FillDBR();

#endif
#include"SPI_CMD.h"

//#define SPI0INT(x) {SPI0DAT=x;while(!SPIF);SPIF=0;}
//可以用这个定义来取代以下一大段的代码
//SPI0DAT=FLASH_READ_ID;
//while(!SPIF);               ----->SPI0DAT=FLASH_READ_ID;
//SPIF=0;
void SPI_READ_ID()
{
    NSSMD0=;

    SPI0DAT=FLASH_READ_ID;
    while(!SPIF);
    SPIF=;

    SPI0DAT=;    //dummy write to output serial clock
    while(!SPIF); //wait for value to be read
    SPIF=;
    sendChar(SPI0DAT);

    SPI0DAT=;
    while(!SPIF);
    SPIF=;
    sendChar(SPI0DAT);    

    SPI0DAT=;
    while(!SPIF);
    SPIF=;
    sendChar(SPI0DAT);

    NSSMD0=;
}

void SPI_WRITE_ENABLE()
{
    NSSMD0=;
    SPI0DAT=FLASH_WRITE_ENABLE;
    while(!SPIF);
    SPIF=;
    NSSMD0=;
}

void SPI_WRITE_DISABLE()
{
    NSSMD0=;
    SPI0DAT=FLASH_WRITE_DISABLE;
    while(!SPIF);
    SPIF=;
    NSSMD0=;
}

unsigned char SPI_READ_STATUS()
{
    NSSMD0=;
    SPI0DAT=FLASH_READ_STATUS;//可以将类似的这种形式做成一个宏定义
    while(!SPIF);
    SPIF=;

    SPI0DAT=;
    while(!SPIF);
    SPIF=;
    NSSMD0=;

    return SPI0DAT;
}

//在所有需要修改的操作之前必须去除软件保护BP0,BP1
//FLASH的状态寄存器
//bit7        bit6    bit5    bit4    bit3    bit2    bit1            bit0
//SRWD        0         0          0        BP1        BP0        WEL                WIP
// 1=status write disable                            1=write enable    1=write in process
#define MASK_CLEAR_BPX 0x73    //掩码,设置使能写状态寄存器,清除BP1、BP0
void SPI_WRITE_STATUS()     //主要是清除保护,可以写数据
{
    unsigned ;
    SPI_WRITE_ENABLE();    //设置状态器WEL位为1,在进行写状态寄存器之前必须写使能
    status=SPI_READ_STATUS();

    NSSMD0=;
    SPI0DAT=FLASH_WRITE_STATUS;
    while(!SPIF);
    SPIF=;

    SPI0DAT=status&MASK_CLEAR_BPX;
    while(!SPIF);
    SPIF=;

    NSSMD0=;//cs must go high at the byte boundary,otherwise instruction will be reject and not executed

    do        //query until WIP convert from 1 to 0 when write status register cycle is finished
    {
        status=SPI_READ_STATUS();
        status=status&0x01;
    }while(status);
}

void SPI_SECTOR_ERASE(unsigned char sectors)
{
    unsigned ;
    SPI_WRITE_ENABLE();

    NSSMD0=;

    SPI0DAT=FLASH_SECTOR_ERASE;
    while(!SPIF);
    SPIF=;

    //any address in the sector,but i choose the first address of sector
    SPI0DAT=0x00;            //high address
    while(!SPIF);
    SPIF=;
    SPI0DAT=sectors<<;        //middle address
    while(!SPIF);
    SPIF=;
    SPI0DAT=0x00;            //low address
    while(!SPIF);
    SPIF=;

    NSSMD0=;

    do        //query until WIP convert from 1 to 0 when write status register cycle is finished
    {
        status=SPI_READ_STATUS();
        status=status&0x01;
    }while(status);
}

unsigned ];
//读一页256 bytes
void SPI_READ_Page(unsigned char sectors,unsigned char pages)
{
    unsigned ;
    NSSMD0=;
    SPI0DAT=FLASH_READ_DATA; //command
    while(!SPIF);
    SPIF=;

    SPI0DAT=0x00;             //read address
    while(!SPIF);
    SPIF=;
    SPI0DAT=(sectors<<) + pages;
    while(!SPIF);
    SPIF=;
    SPI0DAT=0x00;
    while(!SPIF);
    SPIF=;

    ;i<;i++)            //read a page 256 bytes
    {                        //实测每页的数据只有32byte,所以一次连续写32byte
        SPI0DAT=;                 //read datas out
        while(!SPIF);
        SPIF=;
        buff[i]=SPI0DAT;
    }
    NSSMD0=;
}

//写一页256 bytes
void SPI_WRITE_Page(unsigned char *str,unsigned char sectors,unsigned char pages)
{
    unsigned ;
    unsigned ;
    SPI_WRITE_ENABLE();      //在改变数据之前都要进行写使能操作
    NSSMD0=;
    SPI0DAT=FLASH_WRITE_DATA; //write command
    while(!SPIF);
    SPIF=;

    SPI0DAT=0x00;             //write address
    while(!SPIF);                //最高地址默认为0x00,所以不用传他的参数
    SPIF=;
    SPI0DAT=(sectors<<) + pages;
    while(!SPIF);
    SPIF=;
    SPI0DAT=0x00;
    while(!SPIF);
    SPIF=;

    ;i<;i++)        //write a page 256 bytes
    {
        SPI0DAT=str[i];    //write data in
        while(!SPIF);
        SPIF=;
    }

    NSSMD0=;

    do        //query until WIP convert from 1 to 0 when write cycle is finished
    {
        status=SPI_READ_STATUS();
        status=status&0x01;
    }while(status);
}

SPI Flash的更多相关文章

  1. Nand Flash,Nor Flash,CFI Flash,SPI Flash 之间的关系

    前言:    在嵌入式开发中,如uboot的移植,kernel的移植都需要对Flash 有基本的了解.下面细说一下标题中的中Flash中的关系 一,Flash的内存存储结构    flash按照内部存 ...

  2. 【iCore、iCore2 双核心板】EPCS 实验(SPI Flash)(基于Verilog语言)

    _____________________________________ 深入交流QQ群: A: 204255896(1000人超级群,可加入) B: 165201798(500人超级群,满员) C ...

  3. nand flash,nor flash,spi flash,片上RAM,片外RAM

    Flash有掉电数据保存的特点,RAM掉电则数据丢失,但是RAM的速度更高,擦写次数理论上没有限制,而Flash则不行. Nand Flash相比其余的几种flash优势在于可擦写次数多,擦写速度快, ...

  4. 27.some company's Spi Flash chip replace altera epcsxxx

    由于altera公司的epcsxxx芯片比较贵,所以一般用其它公司的spi flash芯片代替也可以.据AlteraFAE描述:“EPCS器件也是选用某家公司的SPIFlash,只是中间经过Alter ...

  5. OpenRisc-32-ORPSoC烧写外部spi flash

    引言 经过前面的分析和介绍,我们对ORPSoC的启动过程(http://blog.csdn.net/rill_zhen/article/details/8855743)和 ORpSoC的debug子系 ...

  6. SPI FLASH与NOR FLASH的区别?

    1.SPI Flash (即SPI Nor Flash)是Nor Flash的一种: 2.NOR Flash根据数据传输的位数可以分为并行(Parallel)NOR Flash和串行(SPI)NOR ...

  7. SPI Flash(W25Q16DV) 驱动

    大体上可分为以下几个部分: 1.注册设备驱动 spi_register_driver 2.分配 mtd_info 结构体 3.配置 mtd_info 结构体 4.注册 mtd_info 结构体 构建 ...

  8. SPI Flash(W25Q16DV) 基本操作

    读取厂家\设备 ID 发送 90H 指令,再发送 00h 的地址,然后接收即可. 代码如下: void SPIFlashReadID(int *pMID, int *pDID) { SPIFlash_ ...

  9. Jlink使用技巧之烧写SPI Flash存储芯片

    前言 大多数玩单片机的人都知道Jlink可以烧写Hex文件,作为ARM仿真调试器,但是知道能烧写SPI Flash的人应该不多,本篇文章将介绍如何使用JLink来烧写或者读取SPI Flash存储器, ...

  10. SPI Flash Memory 芯片手册阅读

    SPI Flash Memory 芯片手册阅读 信息来源

随机推荐

  1. 串口调试工具(Python2.7+pyserial+Tkinter)

    需要与串口设备进行通讯,那么一个调试工具是必须的. 根据我自己的需要,写了个简易版本的串口调试工具: 预览图: ====================== 项目结构: COM --SerialHel ...

  2. python提取隐含结构的字符串

    当我用Stanford CoreNLP和A Python wrapper for the Java Stanford Core NLP tools(NLP的python调用工具)进行句法分析时,遇到一 ...

  3. 烧饼(nyoj779)

    描述烧饼有两面,要做好一个兰州烧饼,要两面都弄热.当然,一次只能弄一个的话,效率就太低了.有这么一个大平底锅,一次可以同时放入k个兰州烧饼,一分钟能做好一面.而现在有n个兰州烧饼,至少需要多少分钟才能 ...

  4. SQL Server 与内存相关的术语

    术语 1. virtual address space 虚拟地址空间 它是一个应用程序可以访问的最大地址空间.32位机上是4G(2^32).虚拟地址空间中的数据不一定在物理内存里.可能在缓存文件中. ...

  5. NFC协议学习分享

    很多同学在学习NFC协议的时候,觉得NFC的规范从底层到上层的应有尽有,有点无处下手的感觉.这里就和大家分享下我曾经学习NFC规范的经验.如果有不对的地方,也请各位同学批评指正.NFC Forum中有 ...

  6. javascript链式调用实现方式总结

    方法链一般适合对一个对象进行连续操作(集中在一句代码).一定程度上可以减少代码量,缺点是它占用了函数的返回值. 一.方法体内返回对象实例自身(this) function ClassA(){ this ...

  7. Checkbutton 和 Radiobutton

    The Checkbutton widget is used to display a number of options to a user as toggle buttons. The user ...

  8. 【Leetcode】寻找数串中连续最大整数和且最大长度的子串

    寻找数串中连续最大整数和且最大长度的子串 输入示例: 1000 -100 200 -200 100 -100 10 90 输出结果: 1100 分析: 分治法解决问题非常方便,依然分为三种情况:a[1 ...

  9. SQL SERVER 2005 获取表的所有索引信息以及删除和新建语句

    BEGIN        WITH tx AS        (                SELECT a.object_id                      ,b.name AS s ...

  10. 带有OUTPUT的INSERT,DELETE,UPDATE

    原文地址:http://blog.sina.com.cn/s/blog_71460d950100nld2.html OUTPUT是SQL SERVER2005的新特性.可以从数据修改语句中返回输出.可 ...