使用了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. [Linux]Service mysql start出错(mysql: unrecognized service)解决方法

    service mysql start出错,mysql启动不了,解决mysql: unrecognized service错误的方法如下: [hitony ~]# service mysql star ...

  2. windows 数据类型转换为 dotnet 数据类型

    Windows Data Type .NET Data Type BOOL, BOOLEAN Boolean or Int32 BSTR String BYTE Byte CHAR Char DOUB ...

  3. shopnc 发票项目

    ---恢复内容开始--- file_put_contents( 't.txt' , print_r($input_invoice_info ,true) ); 打印 $input_invoice_in ...

  4. python运维开发(十一)----线程、进程、协程

    内容目录: 线程 基本使用 线程锁 自定义线程池 进程 基本使用 进程锁 进程数据共享 进程池 协程 线程 线程使用的两种方式,一种为我们直接调用thread模块上的方法,另一种我们自定义方式 方式一 ...

  5. python操作csv-xls完善后的代码

    #coding:utf-8 #导入相应模块 import csv,xlwt,sys,os,fnmatch,xlrd from xlutils.copy import copy #对xls文件中的绝对值 ...

  6. iOS中判断设备系统版本

    @import url(http://i.cnblogs.com/Load.ashx?type=style&file=SyntaxHighlighter.css);@import url(/c ...

  7. mono 判断系统的网络是否可用

    /**  * 判断系统的网络是否可用  * @return  */        private bool isNetworkConnected()        {            bool ...

  8. SQL Server 查看数据库空间分配情况的 2 种方法

    方法 1. sys.dm_db_file_space_usage. 方法 2. sys.dm_db_session_space_usage. ----------------------------- ...

  9. MEMS加速度计工作原理

    一般加速度计有两块芯片组成,一块是MEMS传感器,另一块是客户化的信号处理芯片. 加速度计也称惯性传感器,因为它的工作原理就是靠MEMS中可移动部分的惯性.由于中间电容板的质量很大,而且它是一种悬臂构 ...

  10. Android的数据存储方式(转)

    数据存储在开发中是使用最频繁的,在这里主要介绍Android平台中实现数据存储的5种方式,分别是: 1 使用SharedPreferences存储数据 2 文件存储数据 3 SQLite数据库存储数据 ...