This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[参考译文] MSP430F5510:当在 I2C 操作期间发生复位时 I2C 挂起

Guru**** 2387830 points
请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/1492758/msp430f5510-i2c-hangup-when-reset-is-happened-during-i2c-operation

器件型号:MSP430F5510

工具与软件:

我已根据 I2C 示例源代码实现了 I2C 主器件。 它可以正常工作、但有一件事除外:当我在 I2C 操作期间通过调试器进行复位(例如、在中断处理内的断点时)时、SDA 保持低电平状态、只有下电上电才能帮助恢复运行

下面是我的代码:

void init_i2c() {
  UCB1CTL1 |= UCSWRST;                      // Enable SW reset
  UCB1CTL0 = UCMST + UCMODE_3 + UCSYNC;     // I2C Master, synchronous mode
  UCB1CTL1 = UCSSEL_2 + UCSWRST;            // Use SMCLK, keep SW reset
  UCB1BR0 = 12;                             // fSCL = SMCLK/12 = ~100kHz
  UCB1BR1 = 0;
  UCB1I2CSA = RTC_ADDR >> 1;                // Set slave address
  UCB1IE |= UCNACKIE;                       // allow NACK interrupt
  UCB1CTL1 &= ~UCSWRST;                     // Clear SW reset, resume operation
}


void i2c_write(uint8_t offset, const uint8_t *data, uint8_t size) {
  i2cbuf = (volatile uint8_t*) data;
  i2clength = size;
  i2coffset = offset;

  UCB1IFG &= ~UCRXIFG;                    // Clear USCI_B1 TX int flag
  UCB1IE |= UCTXIE;                       // Enable TX interrupt
  UCB1CTL1 |= UCTR + UCTXSTT;             // I2C TX, start condition
  __bis_SR_register(LPM0_bits + GIE);     // Enter LPM0, enable interrupts
  __no_operation();                       // Remain in LPM0 until all data
                                          // is TX'd
  while (UCB1CTL1 & UCTXSTP);             // Ensure stop condition got sent
  UCB1IE &= ~UCTXIE;                      // Disable TX interrupt
}

// USCI B1 interrupt service routine
#pragma vector = USCI_B1_VECTOR
__interrupt void USCI_B1_ISR(void)
{
  switch(__even_in_range(UCB1IV,12))
  {
  case  0: break;                           // Vector  0: No interrupts
  case  2: break;                           // Vector  2: ALIFG
  case  4:
    UCB1IFG &= ~UCNACKIFG;                  // Clear USCI_B1 NACK int flag
    __bic_SR_register_on_exit(LPM0_bits);
    break;                                  // Vector  4: NACKIFG
  case  6: break;                           // Vector  6: STTIFG
  case  8: break;                           // Vector  8: STPIFG
  case 10: break;                           // Vector 10: RXIFG
  case 12:                                  // Vector 12: TXIFG  
    if (i2clength)                          // Check TX byte counter
    {
      UCB1TXBUF = *i2cbuf++;                // Load TX buffer
      i2clength--;                          // Decrement TX byte counter
    }
    else
    {
      UCB1CTL1 |= UCTXSTP;                  // I2C stop condition if this is NOT intermediate byte and this is NOT read op
      UCB1IFG &= ~UCTXIFG;                  // Clear USCI_B1 TX int flag
      __bic_SR_register_on_exit(LPM0_bits); // Exit LPM0
    }  
  default: break;
  }
}

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您确定问题出在 MSP430吗?

    您是否可以尝试使用硬件复位而不是软件复位? 此处:

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    从器件可能会等待更多时钟来完成一个字节(从器件发送器)。 这通常可以使用 I2C 规范(UM10204 rev6)第3.1.16节中的"9个时钟"技巧清除:

    1)使引脚远离 I2C (清除相关的 PxSEL 位)。

    2) 2)使用 PxOUT 在 SCL 引脚上发送(8+1)个时钟。

    3) 3)将 PxSELn 位放回原位。

    前几个(最多8个)时钟将允许从器件完成其字节、并为 ACK 周期释放 SDA。 下一个时钟周期看起来像 NACK、从器件将离开总线。