我正在使用PIC16F1789和MPU-9250。我的I2C阅读功能中的代码如下所示:

unsigned char i2cSensor_Read(unsigned char regAddr){
unsigned char val;
// Start
i2cWait();
SEN = 1;

// Address + Write Bit
i2cWait();
SSP1BUF = ((slvAdd<<1) | (0b0<<0)); // address slave + write (0)
i2cWait();

//Register address
SSP1BUF = regAddr; // address register
i2cWait();

//Start
RSEN = 1;
i2cWait();

// Address + Read Bit
SSP1BUF = ((slvAdd<<1) | (0b1<<0)); //Address + read (1)
i2cWait();

// Read data
RCEN = 1;
i2cWait();
val = SSP1BUF;

ACKDT = 1; // set acknowlege Bit (1 = Not Acknowlege, 0 = Acknowlege)
ACKEN = 1; // send acknowlege Bit

// Stop
i2cWait();
PEN = 1;
return val;


}

调用最后一个i2cWait()时,程序挂起。
等待函数如下所示:

void i2cWait(){
while((SSP1STAT & 0x04) || (SSP1CON2 & 0x1F));
}


我已经使用了9250数据表第35页上的“单字节读取序列”:https://cdn.sparkfun.com/assets/learn_tutorials/5/5/0/MPU9250REV1.0.pdf

和PIC数据表:http://ww1.microchip.com/downloads/en/DeviceDoc/40001675C.pdf

调试时,在我发送NACK位后,程序卡在了i2cWait()中。之所以卡住是因为SSPCON2寄存器(PIC数据表的第341页)的ACKEN位(第4位)没有被清除,因此程序被卡在while()中。

为什么会这样呢?从站是否必须清除该位?从设备是否损坏?

最佳答案

我认为问题实际上是BF标志仍然设置并且不允许ack移出。一旦设置了RCEN,便会清除BF标志,因此对wait的调用不会执行任何操作,并且val可能包含旧数据,而不是新数据。 8个时钟后,BF标志被置1,SSP1BUF具有新数据。同样,问题在于设置了BF是因为您在接收数据后没有读取数据缓冲区,因此波特率发生器(时钟源)被挂起:


  “将SSPSR的内容加载到SSPBUF中,BF标志位
  位置1时,将SSP1IF标志位置1并将波特率发生器设置为1。
  暂停计数,将SCL保持在低电平。 MSSP现在处于空闲状态
  状态等待下一个命令。当CPU读取缓冲区时,
  BF标志位自动清零。然后,用户可以发送
  通过设置确认在接收结束时确认位
  SSPCON2寄存器的ACKEN位序列使能。”


要解决此问题,您应该在编写RCEN之后轮询BF标志以查找真值。

还有其他问题,例如写入SEN之后的等待可能也不起作用,因为仅写入SEN的SSP1IF位(SSP1IF在启动完成时由硬件置位)。

关于c - I2C ACK位不会被硬件清除,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/59480164/

10-12 14:49
查看更多