STM32F103驱动M24256 256k存储芯片进行读写

2020-05-28 16:00:47来源:博客园 阅读 ()

新老客户大回馈,云服务器低至5折

STM32F103驱动M24256 256k存储芯片进行读写

0 摘要

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

1 所使用的软件

  • Proteus 8.9 SP2

    链接:https://pan.baidu.com/s/1Mnc5M0A5rOIQ2xrPT96ugw

    提取码:dfct

  • Keil5

    链接:https://pan.baidu.com/s/1Aavx3TkvBSLrLxlFOZ7xPw

    提取码:uagc

  • STM32CubeMX

    https://www.st.com/en/development-tools/stm32cubemx.html

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 读写测试


原文链接:https://www.cnblogs.com/Mr-Wangblogs/p/12978868.html
如有疑问请与原作者联系

标签:

版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有

上一篇:复习C++语法--string与string_view

下一篇:C++ 名称空间嵌套