STM32F103驱动M24256 256k存储芯片进行读写
2020-05-28 16:00:47来源:博客园 阅读 ()
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介绍
M24256是ST公司的一款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 |
E2、E1、E0 | Chip Enable | Input |
SDA | Serial Data | I/O |
SCL | Serial Clock | Input |
WC(低电平有效) | Write Control | Input |
VCC | Supply voltage | ?? |
VSS | Ground | ?? |
? ?
通过控制E2、E1、E0的电平关系来修改芯片的地址,也就是说每一个IIC总线上最多可以挂接8个M24256存储芯片。
Write Control引脚用于保护写操作,可以用来保护存储器的整个内容免受意外写操作。将写控制(WC)驱动为高电平时,将禁止对整个存储器阵列进行写操作。 当写控制(WC)被驱动为低电平或悬空时,使能写操作。 将写控制(WC)驱动为高电平时,确认器件选择和地址字节,不确认数据字节。
3 M24256设备地址
? ?
表3-1 芯片地址(设备选择代码)
通过硬件电路定义E2、E1、E0的电平来定义设备的地址,其中最低位为读写标志位,当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???????????? ????????????????CLK频率为200KHz时,查询次数为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个字节读完后,CPU产生NACK信号(驱动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();??/* 中间字节读完后,CPU产生ACK信号(驱动SDA = 0) */ ????????} ????????else ????????{ ????????????IIC_NAck(); /* 最后1个字节读完后,CPU产生NACK信号(驱动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
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有
- WDK驱动调试问题点滴 2020-04-21
- stm32F103片上串口USART1通信实验 2019-09-17
- usb口打印机的指令打印和驱动打印 2019-08-16
- jz_2440_电阻屏触摸驱动 2018-12-04
- C++的特点 2018-11-29
IDC资讯: 主机资讯 注册资讯 托管资讯 vps资讯 网站建设
网站运营: 建站经验 策划盈利 搜索优化 网站推广 免费资源
网络编程: Asp.Net编程 Asp编程 Php编程 Xml编程 Access Mssql Mysql 其它
服务器技术: Web服务器 Ftp服务器 Mail服务器 Dns服务器 安全防护
软件技巧: 其它软件 Word Excel Powerpoint Ghost Vista QQ空间 QQ FlashGet 迅雷
网页制作: FrontPages Dreamweaver Javascript css photoshop fireworks Flash