调试I2C的时候发现主机发送完一个数据后从机ACK仍拉低,导致主机重新开始发送地址

在调试I2C的过程中,我只发送了一个数据,将SCL和SDA波形勾出来看,发现数据格式为:开始—从机地址(8bit,含写位)—ACK(0)—从机内存地址(8bit)—ACK(0)—数据(8bit)——ACK(0)(我认为这个地方从机应该回复1才对)—开始—从机地址(8bit,含写位)—ACK(0)—STop

img


求解是主机软件问题还是从机的问题,具体问题点又是什么?

①0-ACK 1-NACK
②主机发完数据后,如果从机需要继续接收数据则从机回ACK,如果不需要则回NACK。所以你这里回ACK也是没有时序问题的。
③“主机发送完一个数据后从机ACK仍拉低,导致主机重新开始发送地址” : 主机要不要重新发送地址,是主机的代码逻辑决定的。需要继续发数据的话,可以不重新发送地址,也可以重新发送地址

该回答通过自己思路及引用到GPTᴼᴾᴱᴺᴬᴵ搜索,得到内容具体如下:

根据你提供的信息,可以初步判断这个问题是从机的问题。

从机在收到主机发送的数据后,应该将ACK拉低进行确认,然后主机再继续发送下一个数据。但是根据你提供的数据格式,从机在收到数据后,无论是地址还是数据,都没有将ACK拉高进行确认,导致主机认为从机没有正常接收数据,重新开始发送地址,从而导致通信失败。

因此,你需要检查从机的硬件或软件实现是否正确。具体问题点可能包括:

1. 从机的I2C接口是否正常工作,例如SDA和SCL是否连接正确,电平是否稳定;
2. 从机的I2C从设备地址是否正确配置;
3. 从机的I2C从设备是否正确响应主机的读写请求,例如在收到主机传输的地址和数据后,是否正确地将ACK拉高进行确认。

针对以上问题,你可以进行以下尝试:

1. 确认从机的I2C接口是否正常工作,可以使用示波器或逻辑分析仪检查SDA和SCL的波形是否正确;
2. 检查从机的I2C从设备地址是否正确配置,可以通过读取从机的数据手册或代码进行确认;
3. 在从机的代码中,检查I2C从设备是否正确响应主机的读写请求,例如在收到主机传输的地址和数据后,是否正确地将ACK拉高进行确认。

最后需要注意的是,I2C通信是一种同步通信方式,主机和从机之间的通信必须遵循一定的协议,否则就会出现通信失败的情况。因此,在进行I2C通信时,需要仔细检查硬件和软件实现,确保符合I2C协议规范。

如果以上回答对您有所帮助,点击一下采纳该答案~谢谢

以下答案由GPT-3.5大模型与博主波罗歌共同编写:
根据您所描述的情况,从机的 ACK 拉低可能是由于以下原因:

  1. 从机实际上没有收到主机发送的数据。

  2. 从机没有能够正确处理接收到的数据,导致不能正确回复 ACK 信号。

  3. 主机和从机之间的数据传输速率过快,从而导致从机没有足够的时间来处理数据并回复 ACK。

为了解决这个问题,我们应该逐步进行排查并确定其确切原因。具体操作步骤如下:

  1. 确认从机地址是否正确。首先,需要检查主机发送的从机地址是否正确,如果从机地址不正确,从机将无法正确接收数据并回复 ACK。确保使用正确的从机地址是解决这个问题的第一步。

  2. 确认从机的硬件连接是否正确。如果从机的电路连接不正确,从机可能无法正确接收数据,并回复 ACK。可以检查从机的电源、SDA 和 SCL 线路是否正确连接,以及从机是否正确初始化。

  3. 确认主机和从机之间的电气参数是否正确。如果主机和从机之间的电气参数设置不正确,例如,总线电容过高、拉电阻过小等,可能导致通信错误。在硬件上检查主机和从机的电气参数设置是否正确。

  4. 确认通信速率是否正确。确保主机和从机使用相同的通信速率,并确保通信速率不会过快,以致于从机无法处理每个字节并回复 ACK。

  5. 调试主机和从机代码。在确定以上问题都没有问题之后,需要检查主机和从机的代码逐一排查可能存在的逻辑问题。在这个具体问题点中,从机的 ACK 没有正确回复,这可能是从机没有将数据正确写入存储器中或者没有能够正确处理接收到的数据,导致在回复 ACK 时出现错误。

以下是基于 Python 的示例代码,可以用来检查从机是否能够正确回复 ACK。

主机代码(master.py):

import smbus
import time

# Define I2C bus
BUS_ID = 1
i2c = smbus.SMBus(BUS_ID)

# Define slave device address
SLAVE_ADDR = 0x50

# Define memory address to read/write
MEM_ADDR = 0x01

# Write data to slave device
def write_data(data):
    i2c.write_byte_data(SLAVE_ADDR, MEM_ADDR, data)

# Read data from slave device
def read_data():
    return i2c.read_byte_data(SLAVE_ADDR, MEM_ADDR)

# Send start condition
i2c.write_quick(SLAVE_ADDR)

# Write data to slave device
write_data(0xFF)

# Read data from slave device
val = read_data()
print("Data read from slave: ", val)

# Send stop condition
i2c.write_quick(SLAVE_ADDR)

从机代码(slave.py):

import smbus
import time

# Define I2C bus
BUS_ID = 1
i2c = smbus.SMBus(BUS_ID)

# Define slave device address
SLAVE_ADDR = 0x50

# Define memory address to read/write
MEM_ADDR = 0x01

# Set up memory
memory = [0x00]*256
memory[MEM_ADDR] = 0xAA

# Handle I2C request
def handle_request():
    # Read control byte
    ctrl_byte = i2c.read_byte(SLAVE_ADDR)
    
    # Check that control byte is valid
    if ctrl_byte != MEM_ADDR:
        return
    
    # Read/write data
    rw_bit = (ctrl_byte >> 7) & 0x01
    if rw_bit == 0:
        # Write data
        data = i2c.read_byte(SLAVE_ADDR)
        memory[MEM_ADDR] = data
    else:
        # Read data
        i2c.write_byte(SLAVE_ADDR, memory[MEM_ADDR])

while True:
    try:
        # Handle I2C request
        handle_request()
        
        # ACK
        i2c.write_byte(SLAVE_ADDR, 0x00)
    except KeyboardInterrupt:
        # Clean up on exit
        i2c.close()
        break

这是一个简单的示例,用于检查从机是否能够正确回复 ACK。在这个示例中,主机发送一个数据给从机,并读取从机回复的数据。在从机中,我们使用了一个简单的缓存来处理数据,并回复 ACK。如果从机的代码存在逻辑错误,例如没有能够正确回复 ACK,那么可以通过在从机代码中添加打印语句和调试信息,来帮助我们找到并解决问题。

希望这些信息能够帮助您解决问题。
如果我的回答解决了您的问题,请采纳!

不知道你这个问题是否已经解决, 如果还没有解决的话:

如果你已经解决了该问题, 非常希望你能够分享一下解决方案, 写成博客, 将相关链接放在评论区, 以帮助更多的人 ^-^