zoukankan      html  css  js  c++  java
  • STM32F103驱动M24256 256k存储芯片进行读写

    0 摘要

    M24256 是一个256k的存储芯片,本文将主要讲解如何采用模拟IIC实现对M24256的读写驱动操作。并且使用Proteus进行仿真验证。处理器采用STM32F103,使用STM32CubeMX和Keil5进行联合开发。

    1 所使用的软件

    2 M24256介绍

    M24256ST公司的一款256k EEPROM存储芯片,其具有以下特点。

    • M24256具有256kbit EEPROM内容,每页可写入的内容为64bytes(Page Size = 64 bytes)
    • Single supply voltage and high speed
    • Write:
      • – Byte Write within 5 ms
      • – Page Write within 5 ms
    • Random and sequential Read modes
    • Write protect of the whole memory array 所有内存整列均可以进行写保护
    • Enhanced ESD/Latch-Up protection
    • More than 4 million Write cycles
    • More than 200-years data retention

         

    M24256引脚接口如表2-1所示:

    表2-1 芯片引脚定义

    Signal name

    Function

    Direction

    E2E1E0

    Chip Enable

    Input

    SDA

    Serial Data

    I/O

    SCL

    Serial Clock

    Input

    WC(低电平有效)

    Write Control

    Input

    VCC

    Supply voltage

      

    VSS

    Ground

      

       

    通过控制E2E1E0的电平关系来修改芯片的地址,也就是说每一个IIC总线上最多可以挂接8个M24256存储芯片。

    Write Control引脚用于保护写操作,可以用来保护存储器的整个内容免受意外写操作。将写控制(WC)驱动为高电平时,将禁止对整个存储器阵列进行写操作。 当写控制(WC)被驱动为低电平或悬空时,使能写操作。 将写控制(WC)驱动为高电平时,确认器件选择和地址字节,不确认数据字节。

    3 M24256设备地址

       

    表3-1 芯片地址(设备选择代码)

    通过硬件电路定义E2E1E0的电平来定义设备的地址,其中最低位为读写标志位,当bit0=1时处于Read模式,反之处于Write模式。而高八位为固定地址,通常使用的是Memory array情况,所以高八位为A

    如果在设备选择代码上发生匹配,则相应的设备会在第9位时间内给出串行数据(SDA)的确认。 如果设备与设备选择代码不匹配,则会从总线上取消选择自身,并进入待机模式。

       

    4 M24256写操作

    当芯片处于非写保护状态,即WC为0时对应的时序图如图4-1所示。

    表4-1 M24256写时序(WC为低电平)

    由图可以看出,M24256支持两种形式的写操作,分别是按字节写入和按页写入。接下来将针对其时序图逐一进行分析。

    4.1 Byte Write Mode

    按字节写入的时序图如图4-2所示。

    图4-2 Byte Write Mode 时序图

    由图可知,该模式下,设备仅向指定地址中写入一个字节的数据。其包含的时序过程如下:

    Start

    发送设备地址

    1010 E2E1E0 0

    ACK

    待写入的设备地址高8位

    Byte addr

    ACK

    待写入的设备地址低8位

    Byte addr

    ACK

    待写入的八位数据

    Data in

    ACK

    Stop

    对应的写入代码如下:

    uint8_t W24256_Byte_Write(uint8_t WriteData,uint16_t address)

    {

        uint16_t usAddr;

        usAddr = address;  

        /* 第1步:I2C总线启动 */

        IIC_Start();

        /* 第2步:起控制字,高7bit是地址,bit0是读写控制位,0表示1表示 */

        IIC_Send_Byte(EEPROM_DEV_ADDR | I2C_WR);    /* 此指令 */

        /*第3步:等待ACK信*/

        if (IIC_Wait_Ack() != 0)

        {

            goto cmd_fail;  /* EEPROM器件无 */

        }

        /* 第4步:送字地址,送地址直接高八位*/

        IIC_Send_Byte((uint8_t)(usAddr>> 8));

        /*第5步:等待ACK信*/

        if (IIC_Wait_Ack() != 0)

        {

            goto cmd_fail;  /* EEPROM器件无 */

        }

        /* 第6步:送字地址,送地址直接低八位*/

        IIC_Send_Byte((uint8_t)(usAddr&0x00ff));

        /*第7步:等待ACK信*/

        if (IIC_Wait_Ack() != 0)

        {

            goto cmd_fail;  /* EEPROM器件无 */

        }

        /* 第8步: */

        IIC_Send_Byte(WriteData);

        /*第7步:等待ACK信*/

        if (IIC_Wait_Ack() != 0)

        {

            goto cmd_fail;  /* EEPROM器件无 */

        }

        IIC_Stop();

        return 1;

    cmd_fail: /* 命令行失后,切记发送停止信,避免影I2C总线上其他设备 */

        /* I2C总线停止信 */

        IIC_Stop();

        return 0;

    }

    4.2 Page Write Mode

    按页写入的时序图如图4-3所示。

    图4-3 Page Write Mode

    由图可知,该模式下,设备可以向指定页中写入指定字节的数据,可写入的字节数小于等于64byte。其包含的时序过程如下:

    Start

    发送设备地址

    1010 E2E1E0 0

    ACK

    待写入的设备地址高8位

    Byte addr

    ACK

    待写入的设备地址低8位

    Byte addr

    ACK

    待写入的八位数据

    Data in

    如果继续写入,则ACK

    停止写入,则NACK

    STOP

    对应的按页写入代码如下:

    uint8_t W24256_Page_Write(uint8_t *WriteBuf, uint16_t Page, uint16_t Size)

    {

        uint16_t i,m;

        uint16_t usAddr;

          

        /*

         * 串行EEPROM不像操作可以连续读多字,每次操作只能在同一page。

         * 24xx02,page size = 8

         * 简单理方法:按字节写操作模式,没写1,都送地址

         * 了提高连续写的效率: 本函采用page wirte操作。

         */

       

        usAddr = Page * 0x0040;

        for (i = 0; i < Size; i++)

        {

            /* 当发送第1或是面首地址,需要重新启动和地址 */

            if ((i == 0) || (usAddr & (EEPROM_PAGE_SIZE - 1)) == 0)

            {

    //          /* 第0步:停止信启动内操作 */

    //          IIC_Stop();

                  

                /* 通过检查器件答的方式,判断内操作是否完成, 一般小于 10ms            

                    CLK200KHz查询数为30次左右

                */

                for (m = 0; m < 1000; m++)

                {              

                    /* 第1步:I2C总线启动 */

                    IIC_Start();

                      

                    /* 第2步:起控制字,高7bit是地址,bit0是读写控制位,0表示1表示 */

                    IIC_Send_Byte(EEPROM_DEV_ADDR | I2C_WR);    /* 此指令 */

                      

                    /* 第3步:送一个时钟,判器件是否正确应 */

                    if (IIC_Wait_Ack() == 0)

                    {

                        break;

                    }

                }

                if (m  == 1000)

                {

                    goto cmd_fail;  /* EEPROM器件 */

                }

              

                /* 第4步:送字地址,送地址直接高八位*/

                IIC_Send_Byte((uint8_t)(usAddr>> 8));

                /*第五步:等待ACK信*/

                if (IIC_Wait_Ack() != 0)

                {

                    goto cmd_fail;  /* EEPROM器件无 */

                }

                /* 第6步:送字地址,送地址直接低八位*/

                IIC_Send_Byte((uint8_t)(usAddr&0x00ff));

                /* 第5步:等待ACK */

                if (IIC_Wait_Ack() != 0)

                {

                    goto cmd_fail;  /* EEPROM器件无 */

                }

            }

          

            /* 第6步: */

            IIC_Send_Byte(WriteBuf[i]);

          

            /* 第7步:ACK */

            if (IIC_Wait_Ack() != 0)

            {

                goto cmd_fail;  /* EEPROM器件无 */

            }

       

            usAddr++;   /* 地址增1 */      

        }

          

        /* 命令行成功,I2C总线停止信 */

        IIC_Stop();

        return 1;

       

    cmd_fail: /* 命令行失后,切记发送停止信,避免影I2C总线上其他设备 */

        /* I2C总线停止信 */

        IIC_Stop();

        return 0;

    }

    注:M24256有256kbit空间,每一页的大小Page Size =64,所以计算可得页的取值范围为:256*1024/8/64 = 512 页。

    5 M24256读操作

    WC引脚的电平状态对读操作无效,所以其对应的时序图入图5-1所示。

    图5-1 Read mode sequences

    由图5-1可知,M24256共有三种模式的读操作,包括随机地址读取(Random Address Read)、当前地址(Current Address Read)、顺序读取(Sequential Read)

    下面主要针对随机地址读取和顺序读取两种模式进行分析。其余分析类似。

    5.1 Random Address Read

    图5-2 Random Address Read 时序图

    由图可知,该模式下,仅从设备的指定地址中读取一个字节的数据。其包括的时序如下:

    Start

    设备地址和控制字

    1010 E2E1E0 0

    ACK

    待写入的设备地址高8位

    Byte addr

    ACK

    待写入的设备地址低8位

    Byte addr

    ACK

    Start

    重启IIC总线

    设备地址和控制字

    1010 E2E1E0 1

    ACK

    读出的数据

    Data out

    NACK

    Stop

    对应的代码如下:

    uint8_t W24256_Byte_Read( uint16_t Address)

    {

        uint16_t uAddress;

        uint8_t ReadData;

        uAddress = Address;

        /* 第1步:I2C总线启动 */

        IIC_Start();    

        

        /* 第2步:起控制字,高7bit是地址,bit0是读写控制位,0表示1表示 */

        IIC_Send_Byte(EEPROM_DEV_ADDR | I2C_WR);    /* 此指令 */  

        

        /* 第3步:等待ACK */

        if (IIC_Wait_Ack() != 0)

        {

            IIC_Stop(); /* EEPROM器件无 */

        }

        

        /* 第4步:送字地址高8位 */

        IIC_Send_Byte((uint8_t)(uAddress>>8));  

        

        /* 第5步:等待ACK */

        if (IIC_Wait_Ack() != 0)

        {

            IIC_Stop(); /* EEPROM器件无 */

        }  

        /* 第6步:送字地址低八位 */

        IIC_Send_Byte((uint8_t)uAddress&0xff);  

        

        /* 第7步:等待ACK */

        if (IIC_Wait_Ack() != 0)

        {

            IIC_Stop(); /* EEPROM器件无 */

        }

        /* 第8步:重新启动I2C总线。前面的代的目的向EEPROM送地址,下面 */

        IIC_Start();    

        

        /* 第9步:起控制字,高7bit是地址,bit0是读写控制位,0表示1表示 */

        IIC_Send_Byte(EEPROM_DEV_ADDR | I2C_RD);    /* 此指令 */

          

        /* 第10步:ACK */

        if (IIC_Wait_Ack() != 0)

        {

            IIC_Stop(); /* EEPROM器件无 */

        }  

          

       

        /* 第11步:保存*/

        ReadData = IIC_Read_Byte(); /* 1 */

        /*第12步:NACK命令*/    

        IIC_NAck(); /* 最后1节读完后,CPUNACK信(驱动SDA = 1) */

       

        /*第13步:I2C总线停止信 */

        IIC_Stop();

        return ReadData;    /* 行成功 */

    }

    5.2 Sequention Random Read

    图5-3 Sequention Random Read 时序图

    由图可知,该模式下,可以向指定地址中读取指定数目的数据。其包括的时序如下:

    Start

    设备地址和控制字

    1010 E2E1E0 0

    ACK

    待写入的设备地址高8位

    Byte addr

    ACK

    待写入的设备地址低8位

    Byte addr

    ACK

    Start

    重启IIC总线

    设备地址和控制字

    1010 E2E1E0 1

    ACK

    读出的数据

    Data out

    如果到达要读取数据个数,发送NACK,反之发送ACK

    Stop

    其对应的代码如下:

    /**

      * 函功能: 串行EEPROM指定地址处开取若干

      * 参数: ReadBuf : 存放到的据的缓冲区

      *           Address : 起始地址  

      *           Size : 度,

      * 返 回 :  0 表示失1表示成功

      *     明:无

      */

    uint8_t W24256_Page_Read(uint8_t *ReadBuf, uint16_t Page, uint16_t Size)

    {

        uint16_t i;

        uint16_t uAddress;

        /* 采用串行EEPROM随即读取指令序列,连续读取若干字 */

        uAddress = Page * 0x0040;

        /* 第1步:I2C总线启动 */

        IIC_Start();    

        

        /* 第2步:起控制字,高7bit是地址,bit0是读写控制位,0表示1表示 */

        IIC_Send_Byte(EEPROM_DEV_ADDR_Page | I2C_WR);   /* 此指令 */  

        

        /* 第3步:等待ACK */

        if (IIC_Wait_Ack() != 0)

        {

            goto cmd_fail;  /* EEPROM器件无 */

        }

        

        /* 第4步:送字地址高8位 */

        IIC_Send_Byte((uint8_t)(uAddress>>8));  

        

        /* 第5步:等待ACK */

        if (IIC_Wait_Ack() != 0)

        {

            goto cmd_fail;  /* EEPROM器件无 */

        }  

        /* 第6步:送字地址低八位 */

        IIC_Send_Byte((uint8_t)uAddress&0xff);  

        

        /* 第7步:等待ACK */

        if (IIC_Wait_Ack() != 0)

        {

            goto cmd_fail;  /* EEPROM器件无 */

        }

        /* 第8步:重新启动I2C总线。前面的代的目的向EEPROM送地址,下面 */

        IIC_Start();    

        

        /* 第7步:起控制字,高7bit是地址,bit0是读写控制位,0表示1表示 */

        IIC_Send_Byte(EEPROM_DEV_ADDR_Page | I2C_RD);   /* 此指令 */

          

        /* 第8步:ACK */

        if (IIC_Wait_Ack() != 0)

        {

            goto cmd_fail;  /* EEPROM器件无 */

        }  

          

        /* 第9步:循环读 */

        for (i = 0; i < Size; i++)

        {

            ReadBuf[i] = IIC_Read_Byte();   /* 1 */

              

            /* 每1后,需要Ack, 最后一不需要Ack,Nack */

            if (i != Size - 1)

            {

                IIC_Ack();  /* 中节读完后,CPUACK信(驱动SDA = 0) */

            }

            else

            {

                IIC_NAck(); /* 最后1节读完后,CPUNACK信(驱动SDA = 1) */

            }

        }

        /* I2C总线停止信 */

        IIC_Stop();

        return 1;   /* 行成功 */

       

    cmd_fail: /* 命令行失后,切记发送停止信,避免影I2C总线上其他设备 */

        /* I2C总线停止信 */

        IIC_Stop();

        return 0;

    }

       

    6 M24256读写测试

    使用Proteus 和Stm32CubeMX keil 联合开发,对M24256的读写测试进行仿真分析。

    图6-1 仿真搭建

    6.1 按字节读写测试结果

    代码如下

    W24256_Byte_Write(0x01,0x0000);

    HAL_Delay(100);

    W24256_Byte_Read(0x0000);

    HAL_Delay(500);

    图6-2 仿真结果

    第一行

    S

    A0

    A

    00

    A

    00

    A

    01

    A

    P

    向1101 000x设备的0x0000地址写入0x01数据

       

    第二行

    S

    A0

    A

    00

    A

    00

    A

    Sr

    A1

    A

    01

    N

    P

    从1101 000x设备的0x0000地址读出数据,读出的数据为0x01

       

    6.2 按页读写测试结果

    uint8_t Data[3]={0x01,0x05,0xff};

    uint8_t DataRead[3]={0x00,0x00,0x00};

    W24256_Page_Write(Data,10,3);

    HAL_Delay(100);

    W24256_Page_Read(DataRead,10,3);

    HAL_Delay(500);

    图6-3 仿真结果

    第一行

    S

    A0

    A

    02

    A

    80

    A

    01

    A

    05

    A

    FF

    A

    P

    向1101 000x设备的第10页(0X0280)写入0x01、0X05、0XFF三个字节数据

       

    第二行

    S

    A0

    A

    02

    A

    80

    A

    Sr

    A1

    A

    01

    A

    05

    A

    FF

    N

    P

    从1101 000x 设备的第10页(0x0280)读取3个字节数据,读出的数据为 0x01、0x05、0xff

       

    6.3 按字节读写多个字节测试

        uint8_t Data[3]={0x01,0x05,0xff};

        uint8_t DataRead[3]={0x00,0x00,0x00};

        W24256_Write(0x0000,Data,3);

        HAL_Delay(100);

        W24256_Read(0x0000,DataRead,3);

        HAL_Delay(500);

       

    图6-4 仿真结果

    第一行

    S

    A0

    A

    00

    A

    00

    A

    01

    A

    P

    向1010 000x设备的0x0000地址写入0x01数据

    第二行

    S

    A0

    A

    00

    A

    01

    A

    05

    A

    P

    向1010 000x设备的0x0001地址写入0x05数据

    第三行

    S

    A0

    A

    00

    A

    02

    A

    FF

    A

    P

    向1010 000x设备的0x0002地址写入0xFF数据

       

    第四行

    S

    A0

    A

    00

    A

    00

    A

    Sr

    A1

    A

    01

    N

    P

    从1010 000x设备的0x0000地址读取数据,结果为0x01

    第五行

    S

    A0

    A

    00

    A

    01

    A

    Sr

    A1

    A

    05

    N

    P

    从1010 000x设备的0x0001地址读取数据,结果为0x05

    第六行

    S

    A0

    A

    00

    A

    02

    A

    Sr

    A1

    A

    FF

    N

    P

    从1010 000x设备的0x0002地址读取数据,结果为0xFF

     

     

    制作不易,如有错误或者不好理解的地方请留言

    如果需要仿真源文件,请联系EMAIL:whl1457139188@163.com

    并添加QQ:975107705

    请注明M24256 读写测试

  • 相关阅读:
    hdu 4114 Disney's FastPass 状压dp
    lightoj 1381
    bzoj 2428: [HAOI2006]均分数据 随机化
    bzoj 3969: [WF2013]Low Power 二分
    套题:wf2013 (1/8)
    hdu 4119 Isabella's Message 模拟题
    hdu 4118 Holiday's Accommodation 树形dp
    UESTC 2015dp专题 N 导弹拦截 dp
    UESTC 2015dp专题 j 男神的约会 bfs
    UESTC 2015dp专题 H 邱老师选妹子 数位dp
  • 原文地址:https://www.cnblogs.com/Mr-Wangblogs/p/12978868.html
Copyright © 2011-2022 走看看