使用了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 NOR Flash的更多相关文章

  1. 电子工程师名片——FAT16文件系统(转)

    源:电子工程师名片——FAT16文件系统 从8月8号开始,连续一个月利用每天下班时间和周末的时间终于初步完成了一个电子工程师的电路板名片,就像U盘一样,不过这个FLASH只有64KB的大小,用的单片机 ...

  2. 电子工程师名片——FAT16文件系统

    从8月8号开始,连续一个月利用每天下班时间和周末的时间终于初步完成了一个电子工程师的电路板名片,就像U盘一样,不过这个FLASH只有64KB的大小,用的单片机是C8051F320,是一个USB型的单片 ...

  3. 电子工程师名片——UFI Command,USB盘符的显示

    USB Mass Storage类规范概述        USB Mass storage Device协议即海量存储设备协议适用于硬盘,U盘等大容量存储设备.协议使用的接口端点有BulkIn.Bul ...

  4. 快速开发MQTT(一)电子工程师眼中的MQTT

    转载:https://zhuanlan.zhihu.com/p/54669124 DigCore 主页http://www.digcore.cn 文章首发于同名微信公众号:DigCore 欢迎关注同名 ...

  5. STM32F10X SPI操作flash MX25L64读写数据(转)

    源:STM32F10X SPI操作flash MX25L64读写数据 前一段时间在弄SPI,之前没接触过嵌入式外围应用,就是单片机也只接触过串口通信,且也是在学校的时候了.从离开手机硬件测试岗位后,自 ...

  6. spi nor flash使用汇总

    Overview SPI flash, 分为spi flash, DUAL spi flash, QUAD spi flash, 3-wire spi, 4-wire spi, 6-wire spi. ...

  7. SPI操作flash MX25L64读写数据

    STM32F10X SPI操作flash MX25L64读写数据 简单的一种应用,ARM芯片作为master,flash为slaver,实现单对单通信.ARM主控芯片STM32F103,flash芯片 ...

  8. 【DSP开发】TMS320C66x DSP SPI Nor Flash的程序烧写

    经过一段时间的研究终于把TMS320C6657单核和双核的SPI Nor Flash的程序烧写调通了.工具都是前辈的工作,有需要的可以留下邮箱,我有空可以发. 原理参考钱丰的<TI c66x 系 ...

  9. STM32—SPI读写FLASH

    目录 FLASH简介 W25Q64 W25Q64简介 FLASH控制指令 FLASH内部存储结构 代码讲解 读取芯片ID 发送写使能信号 等待FLASH不忙 擦除扇区 写入数据 读取数据 注 FLAS ...

随机推荐

  1. Effective Java提升Code Coverage代码涵盖率 - 就是爱Java

    虽然我们已经有了测试程序,但是如何得知是否已完整测试了主程序?,透过Code Coverage代码涵盖率,我们可以快速地得知,目前系统中,有多少程序中被测试过,不考虑成本跟投资效益比,涵盖率越高,代表 ...

  2. iPhone 和Android应用,特殊的链接:打电话,短信,email;

    http://ice-k.iteye.com/blog/1426526 下面的这篇文章主要是说,网页中的链接如何写,可以激活电话的功能. 例如,页面中展示的是一个电话号码,当用户在手机浏览器里面点击这 ...

  3. LeetCode_Rotate Image

    You are given an n x n 2D matrix representing an image. Rotate the image by 90 degrees (clockwise). ...

  4. Qt修改文件内容

    在用Qt进行嵌入式开发的时候,有时需要通过界面永久的改变ip地址等网卡信息.此时只能修改系统中包含网卡信息的文件,下图红框中所示就是文件中的网卡信息. 那么如何修改这四行呢,我的做法是先打开该文本文件 ...

  5. ImageMaigck不支持中文路径的问题

    不知道咋回事. 回顾下: char* pTest1 = "测试.txt"; wchar_t* pTest2 = L"测试.txt"; 以上是pTest1指向的内 ...

  6. SATA1.0,2.0,3.0区别

    外观没区别,接口都一样,线也一样,就是传输速率不一样,控制芯片不一样SATA1.0理论传输速度为1.5Gbit/s SATA2.0理论传输速度为3Gbit/sSATA2.0理论传输速度为6Gbit/s ...

  7. linux下awk命令详解

    简介 awk是一个强大的文本分析工具,相对于grep的查找,sed的编辑,awk在其对数据分析并生成报告时,显得尤为强大.简单来说awk就是把文件逐行的读入,以空格为默认分隔符将每行切片,切开的部分再 ...

  8. JSP SMARTUPLOAD组件:上传文件时同时获取表单参数

    原因很简单: 注意更改from 属性啊!否则为null! 因为你用jspsmartuploadsmart时post请求 的格式是multipart/form-data,即enctype="m ...

  9. 《Algorithms 4th Edition》读书笔记——2.4 优先队列(priority queue)-Ⅰ

    许多应用程序都需要处理有序的元素,但不一定要求他们全部有序,或者是不一定要以此就将他们排序.很多情况下我们会手机一些元素,处理当前键值最大的元素,然后再收集更多的元素,再处理当前键值最大的元素.如此这 ...

  10. QT 4.7支持中文(QT4.7)(中文)(makeqpf)

    QT 4.7支持中文(QT4.7)(中文)(makeqpf) 摘要: QT4.7.0在移植到开发板上的时候,中文支持是必不可少的,如何让QT支持中文,如何制作QT支持的字体文件,如何使QT UI编辑器 ...