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.

[参考译文] MSP430FR2311:MSP430用作 I2C 从时钟、数据均保持在低电平

Guru**** 2811035 points

Other Parts Discussed in Thread: MSP430FR2311

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

https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/830234/msp430fr2311-msp430-acting-as-i2c-slave-clock-and-data-both-stuck-low

器件型号:MSP430FR2311

我在现场测试中遇到了一个奇怪的问题、我们在测试中发现一个 MSP430从器件同时将 SCL 和 SDA 拉低的单元。  我知道这是因为在我们移除 MSP430从器件后、SCL 和 SDA 都返回高电平、所以我知道 MSP430从器件正在驱动总线。  我不确定它是如何进入这种状态的。  遗憾的是、我们没有使用调试器、也没有任何方法让器件回到处于该状态的实验中。  我在下面添加了 I2C 从设备代码。  它基于 MSP430FR2311 SDK 中的示例代码。  我今天刚刚添加了未经测试的代码来实现时钟低电平超时、希望这可以是最后一项工作、至少可以释放 SCL、我想它还可以释放 SDA、因为我们重置了整个 I2C 模块。   

几个问题:

  • 当 USCI_I2C_UCSTPIFG 被置位时、我应该做更多的事情吗?  我想知道一个事务可能会如何损坏、主设备会发送一个停止信号、但我不会重置状态机以接收命令地址。
  • 我的时钟低电平超时配置是否正确?

谢谢

void initI2C()
{
UCB0CTLW0 = UCSWRST; //软件复位被启用
UCB0CTLW0 |= UCMODE_3 | UCSYNC; // I2C 模式、同步模式
UCB0CTLW1 |= UCCLTO_1;// 28ms 时钟低电平超时
UCB0I2COA0 = SLAVE_ADDR | UCOAEN; //自有地址和使能
UCB0CTLW0 &=~UCSWRST; //清除复位寄存器
UCB0IE |= UCRXIE + UCSTPIE + UCCLTOIE;//启用 RX 中断、停止中断、时钟低电平超时中断
}

//
// I2C 中断
//

#if defined (__TI_Compiler_version__)|| defined (__IAR_systems_icc_)
#pragma vector = USCI_B0_vector
__interrupt void USCI_B0_ISR (void)
#Elif defined (__GNU__)
void __attribute__(interrupt (USCI_B0_vector)#USCI_ISR vector (void

)(void)#USCI_ISR vector 0!
#endif
{
//必须从 UCB0RXBUF
uint8_t Rx_val 读取;
switch (_even_in_range (UCB0IV、USCI_I2C_UCBIT9IFG)
){
USCI_NONE 案例: 中断; //向量0:无中断
USCI_I2C_UCALIFG 案例:中断; //向量2:ALIFG
USCI_I2C_UCNACKIFG 案例: //向量4:NACKIFG
中断;
案例 USCI_I2C_UCSTTIFG:中断; //向量6:STTIFG
案例 USCI_I2C_UCSTPIFG:
//如果我们得到一个停止、我们应该在这里做更多的事情???? 例如、重置状态机? 返回 RX_REG_ADDRESS 模式?
UCB0IFG &=~(UCTXIFG0);
中断; //向量8:STPIFG
USCI_I2C_UCRXIFG3案例:中断; //向量10:RXIFG3
USCI_I2C_UCTXIFG3案例:中断; //向量12:TXIFG3
USCI_I2C_UCRXIFG2案例:中断; //向量14:RXIFG2
USCI_I2C_UCTXIFG2案例:中断; //向量16:TXIFG2
USCI_I2C_UCRXIFG1案例:中断; //向量18:RXIFG1
USCI_I2C_UCTXIFG1案例:中断; //向量20:TXIFG1
USCI_I2C_UCRXIFG0案例: //向量22:RXIFG0
RX_val = UCB0RXBUF;
切换(SlaveMode)
{
情况(RX_REG_ADDRESS_MODE):
ReceiveRegAddr = Rx_val;
I2C_Slave_ProcessCMD (ReceiveRegAddr);
中断;
情况(RX_DATA_MODE):
ReceiveBuffer[ReceiveIndex++]= Rx_val;
RXByteCtr---;

IF (RXByteCtr = 0)
{
//完成接收 MSG
SlaveMode = RX_REG_ADDRESS_MODE;
UCB0IE &=~(UCTXIE);
UCB0IE |= UCRXIE; //启用 RX 中断
I2C_Slave_TransactionDone (ReceiveRegAddr);
i2cFlag = 1;//将标志设置为向 main 发出一个要处理的新命令的信号
__BIC_SR_REGISTER_ON_EXIT (LPM0_BITS);//在 RETI 上退出 LPM0
}
中断;
默认值:
__no_operation();
中断;
}
中断;
USCI_I2C_UCTXIFG0案例: //向量24:TXIFG0
//切换(SlaveMode)
//{
//case (TX_DATA_MODE):

UCB0TXBUF =传输缓冲器[TransmitIndex++];
TXByteCtr --;
IF (TXByteCtr = 0)
{
//完成发送 MSG
//SlaveMode = RX_REG_ADDRESS_MODE;
SlaveMode = TX_REG_ADDRESS_MODE;
UCB0IE &=~(UCTXIE);//禁用 TX 中断
UCB0IE |= UCRXIE; //启用 RX 中断
I2C_Slave_TransactionDone (ReceiveRegAddr);
}
//中断;
//默认:
//__no_operation();
//中断;
//}
中断; //中断矢量:I2C 模式:UCTXIFG
情况 UCCLTOIFG:
//如果时钟一直处于低电平则重置 I2C (我们可能出于一些愚蠢的原因而将其保持在低电平...)
UCB0CTLW0 = UCSWRST;//将 I2C 置于复位
SlaveMode = RX_REG_ADDRESS_MODE;//复位状态机
UCB0IE &=~(UCTXIE);//禁用 TX 中断
UCB0IE |= UCRXIE; //启用 RX 中断
UCB0CTLW0 &=~UCSWRST;//使 I2C 退出复位
中断;
默认值:break;
}


void I2C_Slave_ProcessCMD (uint8_t cmd)
{
ReceiveIndex = 0;
TransmitIndex = 0;
RXByteCtr = 0;
TXByteCtr = 0;
uint16_t ui16Value;

开关(cmd)
{
案例(CMD_RD_ID): //无运动强度设定点
ui16Value = id;
中断;
情况(CMD_RD_FW): //无运动强度设定点
ui16Value = FW;
中断;
情况(CMD_RD_D): //如果我们接收到要注册的数据复制缓冲区
ui16Value = d;
中断;
情况(CMD_RD_Strength): //如果我们接收到要注册的数据复制缓冲区
ui16Value =强度;
中断;
情况(CMD_RD_TEMRATURE): //如果我们接收到要注册的数据复制缓冲区
ui16Value =温度;
中断;
情况(CMD_RW_D_E): //如果我们接收到要注册的数据复制缓冲区
ui16Value = d_e;
中断;
默认值:
__no_operation();
中断;
}

setupRXDataMode();
CopyArrayUINT (ui16Value、TransmitBuffer);
}

void I2C_Slave_TransactionDone (uint8_t cmd)
{
//允许写入 FRAM
//获取先前的写保护设置
uint8_t state = HWREG8 (SYS_base + OFS_SYSCFG0_L);
#ifdef DFWP
uint8_t WP = DFWP | PFWP;
其他
uint8_t wp = PFwp;
#endif

ifdef FRWPPW
HWREG16 (SYS_BASE + OFS_SYSCFG0)=~PW |(状态和 Δ V WP);
其他
HWREG8 (SYS_BASE + OFS_SYSCFG0_L)&&~WP;
#endif

uint16_t temp = CopyTwoByteToUINT (ReceiveBuffer);

开关(cmd)
{
案例(CMD_RD_ID):
中断;
情况(CMD_RD_FW):
中断;
情况(CMD_RD_D):
中断;
情况(CMD_RD_Strength):
中断;
情况(CMD_RD_TEMRATURE):
中断;
案例(CMD_RW_CNTL): //控制寄存器
IF (SlaveMode = RX_REG_ADDRESS_MODE) //如果我们接收到要注册的数据复制缓冲区
{
CNTL = temp;//接收新值
}
中断;// wm
情况(CMD_RW_D_E): //控制寄存器
IF (SlaveMode = RX_REG_ADDRESS_MODE) //如果我们接收到要注册的数据复制缓冲区
{
D_e = temp;//接收新值
}
中断;
默认值:
__no_operation();
中断;
}

//恢复以前的写保护设置
ifdef FRWPPW
HWREG16 (SYS_BASE + OFS_SYSCFG0)= FWPW | STUARY;
其他
HWREG8 (SYS_BASE + OFS_SYSCFG0_L)=状态;
#endif

if (SlaveMode!= RX_REG_ADDRESS_MODE)
{
SlaveMode = RX_REG_ADDRESS_MODE; //结束传输模式
}
}

void setupRXDataMode (void)
{
//设置 i2c 以接收数据或传输数据。 将在 RX 模式下继续、但也会启用发送中断标志。 如果 TX 中断标志有一个写标志被置位的重复启动、然后将进行发送
SlaveMode = RX_DATA_MODE;
TXByteCtr = TYPE_1_LENGTH;
RXByteCtr = TYPE_1_LENGTH;
UCB0IE |= UCTXIE; //启用 TX 中断
UCB0IE |= UCRXIE; //启用 RX 中断
}

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

    尊敬的 Andrew:

    I2C 总线上是否有其他东西可能会导致 MSP I2C 从设备卡在奇怪的状态? 我搜索了类似的现象,这篇 E2E 文章( https://e2e.ti.com/support/microcontrollers/msp430/f/166/t/301670 )似乎也有一个 I2C 线路被保持低电平的问题,这是由 I2C 总线上的另一个器件影响 MSP430引起的。

    您是否能够始终如一地重现问题或是否是零星的问题?

    • 当 USCI_I2C_UCSTPIFG 被置位时、我应该做更多的事情吗?  我想知道一个事务可能会如何损坏、主设备会发送一个停止信号、但我不会重置状态机以接收命令地址。
      • 当主控方发送停止命令时、您可以自由执行所需的任何操作
    • 我的时钟低电平超时配置是否正确?

    此致、

    Matt

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

    Matt、

    有两个 MSP430基本上运行相同的 I2C 代码、只是不同的地址和稍微不同的功能。  我拔下了一个从器件、SCL 和 SDA 仍然保持低电平。  拔下第二个从设备、然后释放总线。  我可以解释 SCL 一直处于低电平的唯一方法是、如果 MSP430在时钟扩展操作期间发生混乱、在该操作中、它正在等待读取缓冲区或传输缓冲区让处理器将数据复制到它、 但不知怎么说、CPU 从未这么做过。  由于主器件无法执行任何操作、因此 SCL 一直处于低电平是可能发生的最糟糕的事情。  这就是为什么我要询问我的状态机中的一些缺陷。

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

    Andrew、

    有道理!  当 UCCLTOIFG 中断被触发时、您是否看到 USCI 外设未正确复位? 如果 SCL 线路一直处于低电平、我假设您复位 USCI I2C 模块的 ISR 过程会使 I2C 链路恢复并运行。

    此致、

    Matt

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

    您好!

    我在一个多星期内没有听到有关这个问题的消息,所以我会假设这个问题已经解决。 如果不是这种情况、请继续并评论、提供有关当前状态的更多信息。

    此致、

    Matt

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

    您好、Matt、

    我想我已经实现了时钟低电平超时。  我在测试它、它似乎只是接地 SCL 不会导致中断触发。  I 必须先将 SDA 拉低、同时 SDA 为高电平、然后将 SCL 拉低。  我只是通过连接到 launchpad 的导线来实现这一点。  是否有更多有关如何触发该中断的文档?  用户指南对它的确切工作方式没有太多的说明。  我会首先查找"开始"条件。

    谢谢

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

    您好!

    用户指南的第24.3.7.3节 详细说明了触发时钟低电平超时中断所需的情况:

    此致、

    Matt