查看: 25799|回复: 21

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

[复制链接]

该用户从未签到

12

主题

103

帖子

0

新手上路

Rank: 1

积分
173
最后登录
1970-1-1
发表于 2013-12-3 16:46:21 | 显示全部楼层 |阅读模式
看了野火的I2C例程, 其中读取数据有“空读”的语句,我发现如果不dummy read,读取到的数据是不正确的的。
必须要dummy read一次才行。手册上没有看到关于此的描述。
u8 I2C_ReadAddr(I2Cn i2cn, u8 SlaveID, u8 Addr)
{
    u8 result;
    /* Send Slave Address */
    I2C_StartTransmission (i2cn, SlaveID, MWSR);
    i2c_Wait(i2cn);
    /* Write Register Address */
    i2c_write_byte(i2cn, Addr);
    i2c_Wait(i2cn);
    /* Do a repeated start */
    i2c_RepeatedStart(i2cn);
    /* Send Slave Address */

    i2c_write_byte(i2cn, ( SlaveID
我知道答案 目前已有21人回答
回复

使用道具 举报

该用户从未签到

12

主题

103

帖子

0

新手上路

Rank: 1

积分
173
最后登录
1970-1-1
 楼主| 发表于 2013-12-3 16:46:57 | 显示全部楼层

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

我使用的是Kinetis MKL46的MCU,谢谢!
回复 支持 反对

使用道具 举报

该用户从未签到

12

主题

103

帖子

0

新手上路

Rank: 1

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

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

另外能不能提供一个多字节收发的I2C例程啊?谢谢啦
回复 支持 反对

使用道具 举报

该用户从未签到

10

主题

459

帖子

0

中级会员

Rank: 3Rank: 3

积分
303
最后登录
2024-10-24
发表于 2013-12-3 20:57:37 | 显示全部楼层

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

必须空读,因为只有空读才能把把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信号需要在下一个接收数据,这也就解释了为什么需要空读。
回复 支持 反对

使用道具 举报

该用户从未签到

12

主题

103

帖子

0

新手上路

Rank: 1

积分
173
最后登录
1970-1-1
 楼主| 发表于 2013-12-4 09:17:41 | 显示全部楼层

回复:有关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连续收发多字节的例程?不是那种把单字节收发循环以下的那种
 
回复 支持 反对

使用道具 举报

该用户从未签到

10

主题

459

帖子

0

中级会员

Rank: 3Rank: 3

积分
303
最后登录
2024-10-24
发表于 2013-12-4 10:07:48 | 显示全部楼层

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

回复第 5 楼 于2013-12-04 09:17:41发表:
回复第 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连续收发多字节的例程?不是那种把单字节收发循环以下的那种
 
连续多字节读取是需要Master给ACK信号的,所以就需要在每个ACK信号时dummy read。你可以理解成发送ACK或者NACK信号的触发,下面是一个多直接读取的时序示意图,从图上看来除了最后一个字节外,你可以使用循环读取就OK了。哈哈,这样讲够通俗易懂吧!
Capture.PNG

 
回复 支持 反对

使用道具 举报

该用户从未签到

12

主题

103

帖子

0

新手上路

Rank: 1

积分
173
最后登录
1970-1-1
 楼主| 发表于 2013-12-4 16:47:34 | 显示全部楼层

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

 我的多字节读取总是有问题,代码如下,帮我看看怎么回事吧?
I2Cn: I2C号,0 = I2C0,1= I2C1,
ucDevAddr: 器件地址
ucRegAddr:器件寄存器地址
ucRegAddrLen:寄存器地址长度
ulDataLen:需要读取的数据长度
*pucBuf:指向存放读取数据缓冲的指针
ULONG MKL_I2C_ReceiveData(I2Cn i2cn, UBYTE ucDevAddr, ULONG ulRegAddr, 
                                    UBYTE ucRegAddrLen,ULONG ulDataLen, UBYTE *pucBuf)
{
    UBYTE *pucRegAddrBuf = (UBYTE *)&ulRegAddr;
    UBYTE ucTemp = ucRegAddrLen;
    /* 如果读取数据时,设备地址和寄存器地址分开,则先发送设备地址 */
    if(0 != ucTemp)
    {
        /* send start signal */
        MKL_I2C_Start(i2cn);
        /* send ID with W bit */

        MKL_I2C_WriteByte(i2cn,((ucDevAddr
tek00000.JPG
回复 支持 反对

使用道具 举报

该用户从未签到

10

主题

459

帖子

0

中级会员

Rank: 3Rank: 3

积分
303
最后登录
2024-10-24
发表于 2013-12-5 09:59:21 | 显示全部楼层

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

程序中写读取的寄存器地址好多次,应该只需要一次就可以了,它连续的读写是靠ACK或者NACK信号控制的,不是把每一个要读取的地址都写一遍,另外,//MKL_I2C_GetAck(i2cn);这一句应该是保留的,MKL_I2C_Delay();似乎可以去掉,因为在MKL_I2C_Wait(i2cn);后就保证了DATA被放在总线上了。
回复 支持 反对

使用道具 举报

该用户从未签到

12

主题

103

帖子

0

新手上路

Rank: 1

积分
173
最后登录
1970-1-1
 楼主| 发表于 2013-12-5 11:00:21 | 显示全部楼层

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

回复第 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个时钟脉冲。
 
回复 支持 反对

使用道具 举报

该用户从未签到

12

主题

103

帖子

0

新手上路

Rank: 1

积分
173
最后登录
1970-1-1
 楼主| 发表于 2013-12-5 16:36:48 | 显示全部楼层

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

能不能提供一个历程呢?I2C多字节读写的历程,谢谢!
回复 支持 反对

使用道具 举报

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

本版积分规则

关闭

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

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

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

Powered by Discuz! X3.4

Copyright © 2001-2024, Tencent Cloud.

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