OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 4297|回复: 14

搬运一点关于模拟IIC协议的知识

[复制链接]

23

主题

323

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1010
金钱
1010
注册时间
2016-11-8
在线时间
233 小时
发表于 2017-1-13 14:23:05 | 显示全部楼层 |阅读模式
本帖最后由 南有乔木 于 2017-3-13 16:09 编辑

此贴非原创,我在微信看到的,感觉比较好,就搬运过来了。在这里,感谢原作者的慷慨分享。

I2C总线的详解与应用例程Ⅰ、写在前面
说到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通信,实现EEPROMAT24Cxx)串行通信读写数据的文章,将结合I2C通信的时序和软件来讲述这种通信是如何实现的。模拟I2C的好处是移植方便,关于硬件SPI,我计划在下一篇文章讲述(网上说的“ST官网提供的I2C操作EEPROM实例有问题”是事实,有个地方确实存在不足,你知道是哪里吗?请提前思考一下,下一篇文章揭晓答案)。 提供“简洁版”和“综合版”两个版本的源代码工程供大家下载学习,简洁版内容容易理解一点(本文以此版本讲述),“综合版”相对复杂一点,包含的判断信息更多,感兴趣的朋友可以下载源代码测试。

Ⅱ、实例工程下载笔者针对于初学者提供的例程都是去掉了许多不必要的功能,精简了官方的代码,对初学者一看就明白,以简单明了的工程供大家学习。笔者提供的实例工程都是在板子上经过多次测试并没有问题才上传至360云盘,欢迎下载测试、参照学习。 提供下载的软件工程是基于Keil(MDK-ARM) V5版本、STM32F103ZE芯片,但F1其他型号也适用(适用F1其他型号: 关注微信,回复“修改型号”)。


原作者 EMbeddDeveloper

详细代码和时序图请下载PDF文件



I2C总线.pdf

561.77 KB, 下载次数: 201

亦余心之所善,
虽九死其犹未悔。
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

23

主题

323

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1010
金钱
1010
注册时间
2016-11-8
在线时间
233 小时
 楼主| 发表于 2017-1-13 14:24:06 | 显示全部楼层
本帖最后由 南有乔木 于 2017-3-13 16:20 编辑

Ⅲ、关于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的理解。

以上总结仅供参考,若有不对之处,敬请谅解。
亦余心之所善,
虽九死其犹未悔。
回复 支持 反对

使用道具 举报

23

主题

323

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1010
金钱
1010
注册时间
2016-11-8
在线时间
233 小时
 楼主| 发表于 2017-1-13 14:25:34 | 显示全部楼层
我懒得编辑了,把PDF版传上去了。。大家自己下载看吧。。

原子视频讲的太少了,看起来很费劲,这个讲的很详细。

I2C总线.pdf

561.77 KB, 下载次数: 261

亦余心之所善,
虽九死其犹未悔。
回复 支持 反对

使用道具 举报

23

主题

323

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1010
金钱
1010
注册时间
2016-11-8
在线时间
233 小时
 楼主| 发表于 2017-1-13 14:29:21 | 显示全部楼层
上面文字部分图片没复制上,若要详细查看,请下载PDF。
亦余心之所善,
虽九死其犹未悔。
回复 支持 反对

使用道具 举报

11

主题

94

帖子

0

精华

初级会员

Rank: 2

积分
188
金钱
188
注册时间
2016-12-12
在线时间
55 小时
发表于 2017-1-13 14:31:21 | 显示全部楼层
这个需要支持一下。
回复 支持 反对

使用道具 举报

15

主题

866

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
7560
金钱
7560
注册时间
2016-11-30
在线时间
643 小时
发表于 2017-1-13 14:43:19 | 显示全部楼层
支持一下!
回复 支持 反对

使用道具 举报

23

主题

323

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1010
金钱
1010
注册时间
2016-11-8
在线时间
233 小时
 楼主| 发表于 2017-1-13 14:48:49 | 显示全部楼层
不死鸟 发表于 2017-1-13 14:31
这个需要支持一下。

:  大自然的搬运工
亦余心之所善,
虽九死其犹未悔。
回复 支持 反对

使用道具 举报

1

主题

24

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
415
金钱
415
注册时间
2015-1-16
在线时间
82 小时
发表于 2017-2-24 20:37:00 | 显示全部楼层
顶,这位热心的朋友
回复 支持 反对

使用道具 举报

1

主题

59

帖子

0

精华

高级会员

Rank: 4

积分
870
金钱
870
注册时间
2016-11-13
在线时间
68 小时
发表于 2017-3-10 22:50:20 | 显示全部楼层

支持一下!正在做这个
回复 支持 反对

使用道具 举报

5

主题

90

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
282
金钱
282
注册时间
2016-8-5
在线时间
158 小时
发表于 2017-3-10 23:08:30 | 显示全部楼层
看了那么多,应该就是,每操作完一位都要释放总线,时序就不会乱了
回复 支持 反对

使用道具 举报

23

主题

323

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1010
金钱
1010
注册时间
2016-11-8
在线时间
233 小时
 楼主| 发表于 2017-3-11 08:21:03 | 显示全部楼层
他说他不在 发表于 2017-3-10 23:08
看了那么多,应该就是,每操作完一位都要释放总线,时序就不会乱了

你总结的有道理,我觉得最难的还是应答信号
亦余心之所善,
虽九死其犹未悔。
回复 支持 反对

使用道具 举报

5

主题

90

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
282
金钱
282
注册时间
2016-8-5
在线时间
158 小时
发表于 2017-3-11 16:27:27 | 显示全部楼层
南有乔木 发表于 2017-3-11 08:21
你总结的有道理,我觉得最难的还是应答信号

对着时序图写,不就OK吗?
回复 支持 反对

使用道具 举报

23

主题

323

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1010
金钱
1010
注册时间
2016-11-8
在线时间
233 小时
 楼主| 发表于 2017-3-13 08:28:22 | 显示全部楼层
他说他不在 发表于 2017-3-11 16:27
对着时序图写,不就OK吗?

能写出来就是对的额
亦余心之所善,
虽九死其犹未悔。
回复 支持 反对

使用道具 举报

8

主题

145

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
462
金钱
462
注册时间
2016-12-14
在线时间
75 小时
发表于 2017-3-13 08:55:50 | 显示全部楼层
顶一下。。。。。
书山有路勤为径,学海无涯苦作舟!
回复 支持 反对

使用道具 举报

1

主题

5

帖子

0

精华

初级会员

Rank: 2

积分
108
金钱
108
注册时间
2016-9-12
在线时间
27 小时
发表于 2017-3-13 13:35:43 | 显示全部楼层
好像很牛逼的样子。。
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-6-14 02:32

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表