【问题标题】:PIC16F1459 I2C Master Ack Issue with 24LC32PIC16F1459 24LC32 的 I2C 主机确认问题
【发布时间】:2014-08-18 21:57:18
【问题描述】:

我遇到了一个奇怪的问题。我一直在我的 PIC16F1459 上使用 bit bangin I2C 功能,但现在我想使用 MSSP(SPI,I2C 主从外设)。所以我开始根据数据表编写函数,开始、停止等。我遇到的问题是我的 PIC 不会确认我发送到 I2C EEPROM 的数据。数据表中明确指出,可以在 SSPCON2.ACKSTAT 中找到 ACK 状态。所以我的猜测是轮询这个位,直到从机响应我的数据,但程序挂在 while 循环中。

 void vReadACK (void)
  {
   while (SSPCON2.ACKSTAT != 0);
  }

这是我的写函数,我的 I2CCheck 函数和 I2C 主初始化函数

void vI2CEcrireOctet (UC ucData, UC ucRW)
 {
   vI2CCheck();
   switch (ucRW)
    {
      case READ:
        SSPBUF = ucData + 1;
      break;
      case WRITE:
        SSPBUF = ucData + 0;
      break;
    }
   vReadACK();
 }

void vI2CCheck (void)
 {
   while (SSPCON2.ACKEN);     //ACKEN not cleared, wait
   while (SSPCON2.RCEN);      //RCEN not cleared, wait
   while (SSPCON2.PEN);       //STOP not cleared, wait
   while (SSPCON2.SEN);       //Start not cleared, wait
   while (SSPCON2.RSEN);      //Rep start not cleared, wait
   while (SSP1STAT.R_NOT_W);  //TX not done wait
 }

void vInitI2CMaster (void)
 {
   TRISB4_bit = 1;        //SDA IN
   TRISB6_bit = 1;        //SCL IN
   SSP1STAT.SMP = 1;      //No slew rate
   SSP1STAT.CKE = 0;      //Disable SMBus inputs
   SSPADD = 0x27;         //100 KHz
   SSPCON1 = 0b00101000;  //I2C Master mode
   SSPCON3 = 0b00000000;  //Rien de slave
 }

您知道,24LC32A WriteProtect 连接到 VSS,A2-A1-A0 连接到 GND,所以地址为 0xA0。 4k7 上拉在 I2C 线上。 PIC16F1459 在 16MHz INTOSC。

我完全被困住了。我浏览了 MSSP 数据表 5 到 6 次,没有发现任何问题。你们能帮忙吗?

这是我的逻辑分析仪预览(删除了 vReadAck() 中的 while)

【问题讨论】:

  • 您的问题表明您认为主设备应该确认它发送给从设备的每个字节。事实上,它是字节的接收者,在这种情况下是从机,他确认每个数据包。从您的逻辑分析仪屏幕截图看来,您的从设备是 NAK
  • 我完全知道,确认主设备发送给它的数据的是药膏。问题是主机必须将其引脚更改为输入状态才能实际“读取”从机发送的 ACK。这就是我轮询 SSPCON2.ACKSTAT 的原因,但图片似乎永远不会收到 ACK。它应该可以工作,地址是正确的,0xA0。

标签: c pic i2c microchip mikroc


【解决方案1】:

看来我已经找到了问题的答案。我正在做的是这样做的确切方式。问题似乎是从站响应所需的总线空闲时间延迟。在 16Mhz 时,我的 I2C 可能对于 EEPROM 存储器来说太快了。所以我在停止操作之后添加了一个小的延迟函数,所以写入序列被延迟并且 BAM 工作。

巴士空闲时间:定时巴士 在一个新的之前必须是免费的 可以开始传输了。

【讨论】:

    【解决方案2】:

    尽管您“完全知道”知道“PIC 不会确认我发送到 I2C EEPROM 的数据”,因为这是不应该的,但您似乎仍然误解了 I2C 确认应该如何工作。它们被称为确认,因为它们可以被肯定(ACK)和否定(NAK)确认。如果您查看您发布的分析器屏幕截图,您会发现它非常清楚地将每个发送的字节标记为已被发送器 NAK'ed。

    要正确检查 I2C ACK,您应该轮询 ACKTIM 位的后沿,然后检查 ACKSTAT 位以查明从机是否发送了 ACK 或 NAK 位。像这样的:

    int
    vReadACK() {
        while(!SSPCON3.ACKTIM);
        while(SSPCON3.ACKTIM);
        return SSPCON2.ACKSTAT;
    }
    

    至于为什么您的从属设备显然对每个字节都进行了 NAK,从您发布的代码中并不清楚,但您的代码中有几个明显的遗漏。您需要生成开始和停止条件,但您没有显示执行此操作的代码。

    【讨论】:

    • 我没有发布此代码,因为这些部分确实有效。我认为这只是关于我写问题的方式。是的,图片是主机,但它是从机(在我的情况下是 24LC32A)正在发送 ACK(如果地址/数据时序匹配)或 NACK(如果地址和|数据不匹配)。如前所述,我一直使用我编写的 bit banging I2C 函数,所以我知道 ACK 和 NACK 问题。再次查看我的问题,我认为它拼写错误。
    猜你喜欢
    • 1970-01-01
    • 2010-10-30
    • 1970-01-01
    • 1970-01-01
    • 2018-06-01
    • 1970-01-01
    • 1970-01-01
    • 2015-09-29
    • 1970-01-01
    相关资源
    最近更新 更多