楼主: azhiking

[已解决] 有关I2C读取数据的疑问(已解决)

[复制链接]

该用户从未签到

1

主题

29

帖子

0

中级会员

Rank: 3Rank: 3

积分
217
最后登录
1970-1-1
发表于 2013-12-7 23:52:31 | 显示全部楼层

RE:有关I2C读取数据的疑问

我的理解是硬件是通过用户的读操作来触发I2C控制器向SCL上拍时钟来读取数据的,所以在读操作前就应该先把读这次数据后要发动ACK或者NACK配好,然后dummy read相当于是告诉硬件来发起读操作,同时将ACK/NACK发出,然后你再读数据寄存器才是你真正想要读到的数据;同时,如果你配置的是ACK,那么I2C控制器会再一次触发读操作,你下一次读数据寄存器时就可以读到数据了,如此循环往复。所以我觉得如果连续读,只需要第一次dummy read,比如你要读n个数据,读的流程就是:
配置ACK -> dummy read -> 连续读n-2个数据 -> 配置NACK -> 读第n-1个数据 -> 读第n个数据
回复 支持 反对

使用道具 举报

该用户从未签到

1

主题

65

帖子

0

中级会员

Rank: 3Rank: 3

积分
233
最后登录
1970-1-1
发表于 2013-12-8 21:29:27 | 显示全部楼层

回复:有关I2C读取数据的疑问

回复第 4 楼 于2013-12-03 20:57:37发表:
必须空读,因为只有空读才能把把ACK或者NACK的信号发送到SDA总线上,在手册中尽管有描述,但是描述不是很明确,主要是下面两点:
1.FACK 选择是否快速ACK,默认为0 An ACK or NACK is sent on the following receiving data byte
2.TXAK  An acknowledge signal is sent to the bus on the following receiving byte (if FACK is cleared) or the
current receiving byte (if FACK is set).发送一个ACK信号需要在下一个接收数据,这也就解释了为什么需要空读。
 
看手册I2C章节 最后面 的流程图。 里面写了整个工作流程。看完那个会有更好的理解
 
回复 支持 反对

使用道具 举报

该用户从未签到

1

主题

65

帖子

0

中级会员

Rank: 3Rank: 3

积分
233
最后登录
1970-1-1
发表于 2013-12-8 21:42:27 | 显示全部楼层

回复:有关I2C读取数据的疑问

回复第 9 楼 于2013-12-05 11:00:21发表:
回复第 8 楼 于2013-12-05 09:59:21发表:
程序中写读取的寄存器地址好多次,应该只需要一次就可以了,它连续的读写是靠ACK或者NACK信号控制的,不是把每一个要读取的地址都写一遍,另外,//MKL_I2C_GetAck(i2cn);这一句应该是保留的,MKL_I2C_Delay();似乎可以去掉,因为在MKL_I2C_Wait(i2cn);后就保证了DATA被放在总线上了。
写读取的寄存器地址只有一次,因为传进来的寄存器地址的BYTE类型的,有可能寄存器地址超过一个字节,所以通过一个while语句把寄存器地址一次发出来。
另外我发现,最后一次从寄存器中读取I2C数据的时候,必须MKL_I2C_Stop(i2cn);之后读取,否则就会出现上面截图上最后面那段波形——没有数据(数据总线拉高),出现9个时钟脉冲。
 
 
i2c作为 master 然后 转为receive模式。 这时 CLK 还是master发出来的。
dummy read(读数据寄存器) 可以简单理解为 “触发开始下一次传输”, 所以在polling模式下,第一次是转变为receive 模式,然后dummy read, 之后 第二到N-1次,都是正常的 receive = read_DataRegister (读数据的同时,也触发了下一字节), 最后一个字节 必须要先发stop。(这个时候数据已经在 DataRegister 里了),如果先 读,再发完stop 就会 “触发”一个新的byte的CLK (这个byte的CLK 是master发出来的,然后第N个字节 master回了NAK ,slave就知道是结束传输,不会发数据。所以这时第N+1个byte 只有9个CLK然后数据都是1.)。所以要先发stop,再然后读还存在DataRegister的值。
 
整个流程datasheet写的很清楚,没注意看而已。 最后几节中的 那个硕大的流程图。(虽然画得很丑)

 
回复 支持 反对

使用道具 举报

该用户从未签到

12

主题

103

帖子

0

新手上路

Rank: 1

积分
173
最后登录
1970-1-1
 楼主| 发表于 2013-12-9 13:28:51 | 显示全部楼层

回复:有关I2C读取数据的疑问

回复第 11 楼 于2013-12-07 23:52:31发表:
我的理解是硬件是通过用户的读操作来触发I2C控制器向SCL上拍时钟来读取数据的,所以在读操作前就应该先把读这次数据后要发动ACK或者NACK配好,然后dummy read相当于是告诉硬件来发起读操作,同时将ACK/NACK发出,然后你再读数据寄存器才是你真正想要读到的数据;同时,如果你配置的是ACK,那么I2C控制器会再一次触发读操作,你下一次读数据寄存器时就可以读到数据了,如此循环往复。所以我觉得如果连续读,只需要第一次dummy read,比如你要读n个数据,读的流程就是:
配置ACK -> dummy read -> 连续读n-2个数据 -> 配置NACK -> 读第n-1个数据 -> 读第n个数据
 
谢谢你,我上周已经调通了,实际上用的读的流程和你描述的差不多。
 
回复 支持 反对

使用道具 举报

该用户从未签到

12

主题

103

帖子

0

新手上路

Rank: 1

积分
173
最后登录
1970-1-1
 楼主| 发表于 2013-12-9 13:30:05 | 显示全部楼层

回复:有关I2C读取数据的疑问

回复第 13 楼 于2013-12-08 21:42:27发表:
回复第 9 楼 于2013-12-05 11:00:21发表:
回复第 8 楼 于2013-12-05 09:59:21发表:
程序中写读取的寄存器地址好多次,应该只需要一次就可以了,它连续的读写是靠ACK或者NACK信号控制的,不是把每一个要读取的地址都写一遍,另外,//MKL_I2C_GetAck(i2cn);这一句应该是保留的,MKL_I2C_Delay();似乎可以去掉,因为在MKL_I2C_Wait(i2cn);后就保证了DATA被放在总线上了。
写读取的寄存器地址只有一次,因为传进来的寄存器地址的BYTE类型的,有可能寄存器地址超过一个字节,所以通过一个while语句把寄存器地址一次发出来。
另外我发现,最后一次从寄存器中读取I2C数据的时候,必须MKL_I2C_Stop(i2cn);之后读取,否则就会出现上面截图上最后面那段波形——没有数据(数据总线拉高),出现9个时钟脉冲。
 
 
i2c作为 master 然后 转为receive模式。 这时 CLK 还是master发出来的。
dummy read(读数据寄存器) 可以简单理解为 “触发开始下一次传输”, 所以在polling模式下,第一次是转变为receive 模式,然后dummy read, 之后 第二到N-1次,都是正常的 receive = read_DataRegister (读数据的同时,也触发了下一字节), 最后一个字节 必须要先发stop。(这个时候数据已经在 DataRegister 里了),如果先 读,再发完stop 就会 “触发”一个新的byte的CLK (这个byte的CLK 是master发出来的,然后第N个字节 master回了NAK ,slave就知道是结束传输,不会发数据。所以这时第N+1个byte 只有9个CLK然后数据都是1.)。所以要先发stop,再然后读还存在DataRegister的值。
 
整个流程datasheet写的很清楚,没注意看而已。 最后几节中的 那个硕大的流程图。(虽然画得很丑)

 谢谢你!!!Kinetis的datasheet组织的确实让人看起来不方便。

 
回复 支持 反对

使用道具 举报

该用户从未签到

0

主题

4

帖子

0

新手上路

Rank: 1

积分
2
最后登录
1970-1-1
发表于 2014-5-30 21:42:42 | 显示全部楼层

回复:有关I2C读取数据的疑问(已解决)

楼主能发个例程看看嘛?或者发些相关资料
回复 支持 反对

使用道具 举报

该用户从未签到

145

主题

4926

帖子

0

金牌会员

Rank: 6Rank: 6

积分
9267
最后登录
1970-1-1
发表于 2014-6-3 12:55:39 | 显示全部楼层

回复:有关I2C读取数据的疑问(已解决)

回复第 16 楼 于2014-05-30 21:42:42发表:
楼主能发个例程看看嘛?或者发些相关资料 

你是想要I2C的代码吗?
在我们的论坛就有哦:https://www.nxpic.org.cn/bbs/article_1280_554911.html
回复 支持 反对

使用道具 举报

该用户从未签到

0

主题

4

帖子

0

新手上路

Rank: 1

积分
2
最后登录
1970-1-1
发表于 2014-6-30 15:29:49 | 显示全部楼层

回复:有关I2C读取数据的疑问(已解决)

回复第 17 楼 于2014-06-03 12:55:39发表:
回复第 16 楼 于2014-05-30 21:42:42发表:
楼主能发个例程看看嘛?或者发些相关资料 

你是想要I2C的代码吗?
在我们的论坛就有哦:https://www.nxpic.org.cn/bbs/article_1280_554911.html
 
我想要连续读取i2c内的信息的代码?用来读取HMC5883和MS5611的
 
回复 支持 反对

使用道具 举报

该用户从未签到

4

主题

27

帖子

0

注册会员

Rank: 2

积分
124
最后登录
2015-9-14
发表于 2014-11-24 11:10:49 | 显示全部楼层
程序死在 i2c_wait()里是怎么回事呢?看代码,这里是等待中断    while(( I2C_S_REG(I2CN[i2cn]) & I2C_S_IICIF_MASK)==0) ;         I2C_S_REG(I2CN[i2cn]) |= I2C_S_IICIF_MASK;但初始化程序并没有开中断啊。哪位在侠解释下,谢谢
回复 支持 反对

使用道具 举报

该用户从未签到

4

主题

27

帖子

0

注册会员

Rank: 2

积分
124
最后登录
2015-9-14
发表于 2014-11-24 11:20:06 | 显示全部楼层
另一个问题,i2c_start()同i2c_repeatstart()有什么区别,i2c_start可以代替i2c_repeatstart吗?
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 注册/登录

本版积分规则

关闭

站长推荐上一条 /3 下一条

Archiver|手机版|小黑屋|恩智浦技术社区

GMT+8, 2025-7-29 04:54 , Processed in 0.097448 second(s), 29 queries , MemCache On.

Powered by Discuz! X3.4

Copyright © 2001-2024, Tencent Cloud.

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