STM32F10x_模拟I2C读写EEPROM

发布者:温文儒雅最新更新时间:2017-02-05 来源: eefocus关键字:STM32F10x  模拟I2C  读写EEPROM 手机看文章 扫描二维码
随时随地手机看文章

Ⅰ、写在前面

说到IIC,大家都应该不会陌生,我们初学单片机的时候或多或少都知道或了解过,甚至使用I2C控制过器件。但是,有多少人真正去深入理解,或者深入研究过I2C通信协议呢?

 

1、我们有必要学习I2C通信吗?

I2C作为常见串行通信的其中一种,在嵌入式领域中占有很重要的地位。原因在于我们嵌入式开发的产品中有很多设备都是使用I2C进行通信的。我们开始学习单片机开发的时候最先接触的应该是使用I2C操作EEPROM(如AT24C08)通信,这也是典型的I2C通信例子。其实还有很多常见的I2C通信设备,如温度芯片、触摸芯片、时钟芯片等,当你工作今后或多或少都会遇到I2C通信的设备。所以,如果你有时间的话,请花一定时间去研究学习一下I2C通信协议,当你以后工作中需要用到I2C设备,而你没有了解过,那个时候再去了解,恐怕项目的进度会因此而受到影响。

 

2、常见串行通信有哪些,我们又要了解哪些?

常见的串行通信:USART、I2C、SPI、CAN、USB等;我们需要学习哪些?这个问题笔者的建议都要学(在时间、条允许的 情况下)。想要做嵌入式开发,这些通信方式是我们常见的,因此需要掌握。

由于做技术这一行,要学到东西太多,如果你的时间真的有限,那么简单一点的(USART、I2C、SPI)你必须要弄明白,不然你真的有点“水”。这种简单的通信方式应该在面试中是经常问及的问题,如果你是一位刚毕业的大学生,你最好把这些东西你需要弄明白了才去面试。

 

I2C的读写对时序要求很高,所以,每一个函数都应尽量标准才行,在你自己编写I2C驱动,或借鉴网上的需特别注意(在下面I2C读写函数,我会举例说网上几种常见的不标准的函数)。

本文是使用普通IO软件模拟I2C通信,实现EEPROM(AT24Cxx)串行通信读写数据的文章,将结合I2C通信的时序和软件来讲述这种通信是如何实现的。模拟I2C的好处是移植方便,关于硬件SPI,我计划在下一篇文章讲述(网上说的“ST官网提供的I2C操作EEPROM实例有问题”是事实,有个地方确实存在不足,你知道是哪里吗? 请提前思考一下,下一篇文章揭晓答案)。

 

提供“简洁版”和“综合版”两个版本的源代码工程供大家下载学习,简洁版内容容易理解一点(本文以此版本讲述),“综合版”相对复杂一点,包含的判断信息更多,感兴趣的朋友可以下载源代码测试。

 

 

关于本文的更多详情请往下看。

 

Ⅱ、实例工程下载

笔者针对于初学者提供的例程都是去掉了许多不必要的功能,精简了官方的代码,对初学者一看就明白,以简单明了的工程供大家学习。

笔者提供的实例工程都是在板子上经过多次测试并没有问题才上传至360云盘,欢迎下载测试、参照学习。

 

提供下载的软件工程是基于Keil(MDK-ARM) V5版本、STM32F103ZE芯片,但F1其他型号也适用(适用F1其他型号: 关注微信,回复“修改型号”)。

 

模拟I2C读写EEPROM简洁版(不切换SDA方向、不检测ACK位)实例源代码工程:

http://yunpan.cn/c6WawSRZLjJIa  访问密码

 

模拟I2C读写EEPROM综合版(切换SDA方向、检测ACK位)实例源代码工程:

http://yunpan.cn/c6WacI2eTkikZ  访问密码

 

I2C  EEPROM(AT24xx)资料:

https://yunpan.cn/c667rIDPgvwTf  访问密码 1099

 

STM32F1资料:

https://yunpan.cn/crBUdUGdYKam2  访问密码 ca90

 

Ⅲ、关于I2C协议

I2C协议的描述请网上搜索,下面将结合时序图+源代码程序一起讲解关于I2C协议中重要的几点。

 

1.开始和停止条件

SCL时钟电平为高:

SDA数据线由高 -> 低 为总线开始条件;

SDA数据线由低 -> 高 为总线结束条件;

(注意:开始之后将SCL变为低电平,防止误操作SDA使其通信停止,见源代码)

时序图:

源代码程序:

 

2.数据位传输

SCL时钟电平为低, 可以改换SDA数据线的电平,在SCL上升沿的过程将SDA数据发送出去。

(切记:请先将SCL变为低电平,再改变SDA电平状态。 主要用于I2C读写Byte函数,这两个函数网上很多人写的不规范,引用需注意,在下面我会举例说明)

时序图:

 

发送一位“高”数据流程:

SCL_LOW时钟低 ->  SDA_HIGH数据 ->  SCL_HIGH时钟高

 

 

3.应答位信息

I2C是以字节(8位)的方式进行传输,总线上每传输完1字节之后会有一个应答信号,主器件(主机)需要产生对应的一个额外时钟。

应答位产生及接收:

1.在(主机)写数据的时候是从机应答(给主机),主机检测;

2.在(主机)读数据的时候是主机应答(给从机),从机检测;

(这里可以借助I2C读写函数一起理解)

1.时序图(主机写,从机应答,主机读取应答):

 

2.时序图(主机读,主机产生应答):

 

4.I2C写一字节

这里说的I2C写,是主机往从机接入1Byte的数据;

 

“写”要求按照上面的“数据为传输”来操作:在SCL时钟为低电平时准备好,待SCL为高电平时发送出去。

 

写完一字节(8位)之后,读取从机的应答位:

若为0,表示从机应答,可以继续下一步操作;

若为1,表示从机非应答,不能进行下一步操作。

 

注意:

I2C写一字节不是EEPROM写一字节(需要区分开来)。

“简洁版”没有对应答信号做出检测判断,需要检测应答信号,可参考“综合版”

写一字节时序(前面8位数据 + 最后1为应答):

源代码程序:

 

I2C写数据(网上常见几种不规范写法 - 或许整个I2C驱动能通信成功,但各个函数之间依赖关系很强,不便理解,也不是标准的函数):

1.首先将SCL置高:

void I2C_WriteByte(uint8_t Data)

{

  uint8_t cnt;

  for(cnt=0; cnt<8; cnt++)

  {

    I2C_SCL_HIGH; 

 

    if(Data & 0x80)

      I2C_SDA_HIGH;

    else

      I2C_SDA_LOW;

    Data <<= 1;

 

    I2C_SCL_LOW;

  }

  I2C_GetAck();

}

这种程序的写法有一个致命的地方(有可能停止,或重新开始I2C通信):

首先将SCL置高:

A.若之前SDA是低电平,第一位写入高电平,将停止I2C通信。

B.若之前SDA是高电平,第一位写入低电平,将重新开始I2C通信。

 

2.写完8位数据之后,未将SCL置低(也就是SCL保持高电平状态):

由于写完8位数据之后,将要读取应答信号,也就是要SDA将从输出状态变为输入状态。

这个时候SCL为高,如果SDA最后一位是低且SDA是开漏模式,需要将SDA释放,也就是要将SDA置位高,那么,这个时候就进行了一个停止操作。

 

3.时序混乱:

void I2C_WriteByte(uint8_t Data)

{

  uint8_t cnt;

 

  I2C_SCL_HIGH;

 

  for(cnt=0; cnt<8; cnt++)

  {

    if(Data & 0x80)

      I2C_SDA_HIGH;

    else

      I2C_SDA_LOW;

    Data <<= 1;

 

    I2C_SCL_LOW;

    I2C_SCL_HIGH;

  }

  I2C_GetAck();

}

多种问题的例子,有可能产生以下问题:

A.有可能多写1位数据;

B.有可能停止I2C通信;

C.有可能重新开始I2C通信。

 

5.I2C读一字节

I2C的读一字节函数,其实和“写一字节”类似,只是数据传输方向相反,应答的方向也是相反。

 

读完一字节(8位)之后,由主机产生应答(或非应答)位:

若产生应答,表示可以继续读下一字节操作(从设备地址指向下一字节);

若产生非应答,表示不可以继续读下一字节操作;

 

网上I2C读数据程序和“写数据”类似,存在很多不标准的版本,参考时请注意。

读一字节时序(主机读取前面8位数据 + 主机产生1为非应答<连续读,主机产生应答位>):

读字节源代码程序:

 

Ⅳ、EEPROM读写

EEPROM的种类比较多,大多数都遵循I2C协议通信,我们这里就以典型的AT24Cxx为例来讲述通过I2C通信读写AT24Cxx芯片。

 

EEPROM读(或写)一字节数据需要I2C多次通信过程,下面将讲述几个重要的内容:

 

1.设备(从机、器件)地址

I2C的开始信号之后的第一步就是发送设备物理地址, AT24Cxx的物理地址的格式如上面:

前面四位固定为:1010

第567位对应A2 A1 A0(有些器件未使用)

第8位是读/写位。

一个设备一般是接地,这就是为什么我们看到A0这个宏定义的来由。

 

2.数据地址长度

有些芯片数据地址只有8位(如:AT24C01、AT24C02),那么它只发送一字节地址即可;

有些芯片有16位地址,它需要发送两字节地址(看下面读写函数)。

 

 

3.EEPROM写一字节数据

EEPROM写数据一般包含下面五步骤(见下面源代码)。这里的写数据,相当于手册中是随机写(任意地址,写一字节数据)。

(未检测应答,需要可以看我提供的另一个源代码程序)

 

注意两个地方:1.设备地址更加需要看你看引脚的情况;

2.数据地址长度根据芯片不同而不同。

 

4.EEPROM读一字节数据

EEPROM读数据和写数据相比,要多两个步骤(见下面源代码)。由于要先确定读的地址,所以要先发送地址,使其EEPROM指向对应的地址。(当然,如果当前地址就是需要读取的地址,也可以省略前面发送地址的步骤)。

(在手册中有这么一个步骤“Dummy Write”,有些人把它翻译为“伪操作”,可能很多人不明白它的意思,其实就是确定地址,先要发送地址的意思)

具体请看源代码:(未检测应答,需要可以看我提供的另一个源代码程序)

 

 

    跟多关于EEPROM的操作(如:页写、多字节读写等),相对来说复杂一点,当你理解单字节读写操作之后,再去理解就容易的多了。具体内容可以下载我提供的实例参考学习。

 

Ⅴ、说明

EEPROM的读写操作按照I2C标准协议通信,请参看数据手册,有助于提高对I2C的理解。

以上总结仅供参考,若有不对之处,敬请谅解。


关键字:STM32F10x  模拟I2C  读写EEPROM 引用地址:STM32F10x_模拟I2C读写EEPROM

上一篇:stm32f4 - 时钟树分析配置
下一篇:STM32F10x_硬件I2C读写EEPROM(标准外设库版本)

推荐阅读最新更新时间:2024-03-16 15:32

STM32单片机内部EEPROM读写
STM32L系列单片机内部提供了EEPROM存储区域,但实质上,其FLASH也是EEPROM类型,只不过有一块区域被开放出来专门用作EEPROM操作而已。STM32L的EEPROM使用寿命设计为100000次擦写以上,容量为2K-4K,这对于一般设备的参数存储来说是非常理想的。但从EEPROM使用方式看,其不适用于被反复修改的数据存储使用,一般作为配置参数,其修改次数往往是比较少量的。 STM32L的EEPROM和FLASH是统一编址,操作共用同一个读写电路,所以在EEPROM读写的时候STM32L核对于FLASH的一切访问和操作都将暂停,只有当EEPROM的操作完成后,才继续执行后续代码,在这期间只有EEPROM的读写电路工
[单片机]
STM32F10x Flash 模拟 EEPROM
STM32 F10x芯片本身没有集成EEPROM,替代方案是用片上Flash来模拟EEPROM。Flash与EEPROM的区别主要是:一、EEPROM可以按位擦写,而Flash只能按块(页)擦除;二、Flash的擦除寿命约1 万次,较EEPROM低一个量级。ST网站有个Flash模拟EEPROM的范例: AN2594: EEPROM emulation in STM32F10x microcontrollers (包括源码和文档)。范例在保存修改的数据时,以写入新数据来替代对原数据的修改,并使用两个页面轮流写入,单页写满后进行数据迁移,再一次性擦除旧页面。这个策略可以有效降低Flash擦除次数。   不过,范例代码只能保存固定大
[单片机]
STM32F10x 学习笔记 2 (SysTick 定时器)
SysTick 定时器被集成在NVIC中。因此,只要是Cortex-M3 内核的单片机,就都有它。这个学习笔记就用SysTick 定时器来实现走马灯的功能。 SysTick 定时器非常简答,只有四个寄存器。这四个寄存器的含义在《Cortex-M3权威指南》那本书中讲的非常的清楚,这里不复述了,下面只讲讲在STM32上SysTick有什么特殊之处。按照CMSIS 标准,用C语言访问这四个寄存器时使用的寄存器名称分别如下: SysTick- CTRL SysTick- LOAD SysTick- VAL SysTick- CALIB SysTick- CALIB 的值固定为9000,因此,只有当系统嘀嗒时钟设定为9MHz(H
[单片机]
STM32模拟I2C读取MPU9250数据
利用Stm32的Gpio口模拟I2C读取MPU9250数据 1、每个数据字节在传送时都是高位(MSB)在前; 写通讯过程: 1. 主控在检测到总线空闲的状况下,首先发送一个START信号掌管总线; 2. 发送一个地址字节(包括7位地址码和一位R/W); 3. 当被控器件检测到主控发送的地址与自己的地址相同时发送一个应答信号(ACK); 4. 主控收到ACK后开始发送第一个数据字节; 5. 被控器收到数据字节后发送一个ACK表示继续传送数据,发送NACK表示传送数据结束; 6. 主控发送完全部数据后,发送一个停止位STOP,结束整个通讯并且释放总线; 读通讯过程: 1. 主控在检测到总线空闲的状况下,
[单片机]
STM8L的EEPROM读写原理及例程
STM8L103C6拥有1KB的片上EEPROM,可以用来存储程序需要用到的参数,就不需要额外使用24C02这样的外部存储器了. 同时,和24C02比起来,STM8L的片上EEPROM操作更简单,可以直接对地址进行操作,进行数据读写. 下图是STM8L闪存和EEPROM的地址分配图,可以看到EEPROM的起始地址为0x001000,结束地址为0x0013FF.共1024个地址空间,所以EEPROM的容量为1KB. EEPROM在上电复位后是写保护的,在向其中写入数据时,需要解锁,关闭写保护.解锁流程为: ①第一次向FLASH_DUKR写入密钥0xAE ②第二次向FLASH_DUKR写入密钥0x56 两次都写入正确后,写保护
[单片机]
STM8L的<font color='red'>EEPROM</font><font color='red'>读写</font>原理及例程
stm32 hal 模拟i2c
管脚配置(我是用的是PA9和PA10): //i2c.h #include stm32f0xx_hal.h #define GPIO_PORT_I2C GPIOA // GPIO端口 #define I2C_SCL_PIN SCL_Pin // 连接到SCL时钟线的GPIO #define I2C_SDA_PIN SDA_Pin // 连接到SDA数据线的GPIO /* 定义读写SCL和SDA的宏 */ #define I2C_SCL_1() GPIO_PORT_I2C- BSRR = I2C_SCL_PIN // SCL = 1 #define I2C_SCL_0() GPIO_
[单片机]
stm32 hal <font color='red'>模拟</font><font color='red'>i2c</font>
AVR内部EEPROM读写实验
片内EEPROM读写实险。 1、用内部EEPROM记录CPU启动次数,并在PB口上显示出来。 2、内部1 M晶振,程序采用单任务方式,软件延时。 3、进行此实验请插上JP1的所有8个短路块,JP7(LED_EN)短路块。 4、通过此实验,可以对对内部EEPROM有个初步认识,了解EEPROM函数的操作。 5、可过复位键让系统重启,这样就可以更新显示了。 */ #include "iom16v.h" /*延时函数*/ void delay_ms(unsigned char i) { unsigned char a, b; for (a = 1; a i; a++) { for (b = 1; b; b++
[模拟电子]
AT89C51ED2 的EEPROM 读写操作总结
今天因为要用到ED2的EEPROM,写点东西总结一下,以防日后忘了。 先引用网上有朋友问到的一个问题。 //////// 哪位高手用过AT89C51ED EEPROM 保存数据 下面程序写数据到EEPROM: #define EEPROM_VC_ADD 0X0100 adr = EEPROM_VC_ADD; // ACC = c1; while(EECON & 0x01); EA = 0; ACC = 44; EECON = 0x02; XBYTE = ACC; // *(unsigned char xdata*)adr = ACC; EECON = 0x00; E
[单片机]
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved