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.

[参考译文] MSP432P401R:移除 while 环路会使 I2C 读取不同的值

Guru**** 2586895 points


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

https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/604195/msp432p401r-removing-while-loop-makes-i2c-read-different-values

器件型号:MSP432P401R

 

你好! 我正在尝试将 Fuel Tank MKII 电池 BoosterPack 插件模块与 MSP-EXP432P401R 版本2.0 Launchpad 配合使用。 我正在使用 MSP432 Simplelink SDK 1.40.00.28 (boostxl_batpakmki_fulgauge _MSP_EXP432P401R_nortos_ccs)中提供的示例、我想通过让 CPU 休眠而不是在 while 循环中等待接收到的字节来优化它。  

问题是 、当使用我的代码时、它从 BQ27441读取不同的响应(当它应该读取0x0108时、它读取0xB000)。 我使用的代码:

volatile bool i2cRxFlag = false;

void I2C_init (void)
{
/*初始化 USCI_B0和 I2C 主设备以与从属设备通信*/
I2C_initMaster (EUSCI_B1_base、&i2cConfig);

/*禁用 I2C 模块进行更改*/
I2C_DisableModule (USCI_B1_base);

/*启用 I2C 模块以启动操作*/
I2C_enableModule (USCI_B1_base);

MAP_I2C_clearInterruptFlag (EUSCI_B1_base、EUSCI_B_I2C_Transmit INTERRUPT0 + EUSCI_B_I2C_Receive_INTERRUPT0 + EUSCI_B_I2C_STOP_INTERRUPT0);
MAP_I2C_enableInterrupt (EUSCI_B1_BASE、EUSCI_B_I2C_Transmit INTERRUPT0 + EUSCI_B_I2C_Receive_INTERRUPT0 + EUSCI_B_I2C_STOP_INTERRUPT0);
MAP_Interrupt_enableInterrupt (INT_EUSCIB1);

return;
}

void EUSCIB1_IRQHandler (void)
{
unsigned int status;
STATUS = MAP_I2C_getEnabledInterruptStatus (EUSCI_B1_BASE);
MAP_I2C_clearInterruptFlag (EUSCI_B1_BASE、STATUS);

IF (STATUS & EUSCI_B_I2C_Transmit _INTERRUPT0)
{
i2cTxFlag = true;
}
IF (STATUS & EUSCI_B_I2C_STOP_INTERRUPT)
{
i2cStopFlag = true;
}
IF (STATUS & EUSCI_B_I2C_Receive_INTERRUPT0)
{
i2cRxFlag = true;
}
map_Interrupt_disableSlepOnIsrExit();
}

bool I2C_read16 (unsigned char 指针、short * result、unsigned int timeout)
{
uint8_t val = 0;
uint8_t valScratch = 0;
短接 r = 0;

/*将主设备设置为发送模式 PL */
I2C_setMode (EUSCI_B1_BASE、
EUSCI_B_I2C_Transmit 模式);

/*清除任何现有的中断标志 PL */
I2C_clearInterruptFlag (EUSCI_B1_base、
EUSCI_B_I2C_Transmit INTERRUPT0);

/*启动开始并发送第一个字符*/
if (!I2C_masterSendSingleByteWithTimeout (EUSCI_B1_base、指针、超时))
返回0;

/*
*生成开始条件并将其设置为接收模式。
*这会发出从器件地址并继续读取
*直到您发出停止
*
I2C_masterReceiveStart (EUSCI_B1_BASE);

/*等待 RX 缓冲区填充*/
//while (!(I2C_getInterruptStatus (EUSCI_B1_BASE、
// EUSCI_B_I2C_Receive_INTERRUPT0)));
if (!(MAP_I2C_getInterruptStatus (EUSCI_B1_BASE、EUSCI_B_I2C_Receive_INTERRUPT0))))
{
while (i2cRxFlag = false)
{
MAP_PCM_gotoLPM0InterruptSafe ();
MAP_Interrupt_enableMaster();
}
i2cRxFlag = false;
}

/*从 I2C RX 寄存器读取*/
valScratch = I2C_masterReceiveMultiByteNext (EUSCI_B1_BASE);

/*接收第二个字节、然后发送停止条件*/
if (!I2C_ReceivmasterMultiByteFinishWithTimeout (EUSCI_B1_BASE、&V、超时))
返回0;

/*将 val 移动到顶部 MSB */
R =(val << 8);

/*从 I2C RX 寄存器读取并写入 r 的 LSB */
R |= valScratch;

/*返回温度值*/
*结果= r;

返回1;
} 

如您所见、我只添加了几行代码。 等待 RX 缓冲区填充后、如果我使用原始 while ()循环(在上面注释) 、它将读取0x0108、但如果我使用代码(上面的 if 语句)、则会读取0xB000。

问题可能出在哪呢?

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    克里斯蒂安
    我看不到数据损坏的明显原因、需要尝试在我的一侧重新创建数据。 看一下您提供的代码片段、我认为您不需要在第70、71和78行上使用 if 语句。 在 ISR 将标志设置为 true 之前、i2cRxFlag 上的 while 循环不会继续。 我担心接收中断的状态检查可能是冗余的、因为您在 ISR 中再次检查它。 明天我将尝试得到更明确的答案。

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

    您好、Chris! 是的、你是对的。 if 语句是多余的、但不应影响程序。 我将其删除。 请测试代码并告诉我您将发现的内容。 谢谢!

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

    e2e.ti.com/.../HAL_5F00_I2C.c

    克里斯蒂安

      我认为问题在于 I2C_masterReceiveMultiByteFinishWithTimeout API 的使用。  由于您已经为停止条件启用了中断 、正在检查停止 IFG 的 API 内的轮询函数在 ISR 清除它之前看不到该标志被置位。  

      我对代码进行了一些更改、这似乎可以正常工作。  请确认吗?

    Chris

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    我已经测试了代码、但它不能按预期工作。 它确实读取了正确的值,但问题是程序有时会在 I2C_masterReceiveSingleByte()中挂起,而在 while (!BITBAND_peri (EUSCI_B_CMSIS (moduleInstance)->IFG、EUSCI_B_IFG_RXIFG_OFS)中挂起;有时是 I2C_SendWithTimeouts。 有趣的是、每次我运行程序时、它都会在不同的函数中挂起、例如:
    /*读取块数据校验和*/
    if (!BQ27441_readChecksum (&old_chksum、1000))

    /*读取旧设计容量*/
    if (!BQ27441_read16 (0x4A、&OLD_designCapacity、1000))
    返回0;

    在每次运行程序之前、我还负责对电池 Booster Pack 模块进行下电上电。 您是否测试了整个初始化序列或仅测试了 BQ27441_read16()函数?
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    克里斯蒂安
    我只需通过上述修改运行代码、并验证了终端窗口中的操作和 I2C 总线通信。 我将要求一位同事确认。

    此致、
    Chris
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    我今天再次测试了代码。 现在、它只会挂起:

    uint8_t I2C_masterReceiveSingleByte (uint32_t 模量)

    //轮询接收中断标志。
    while (!BITBAND_peri (EUSCI_B_CMSIS (模态)->IFG、
    EUSCI_B_IFG_RXIFG_OFS))


    如果我使用原始代码、它会起作用。 我希望我们使用相同的 SDK (我使用的是 SimpleLink MSP432 SDK - v1.40.00.28中的 boostxl_batpakmki_fualgauge 演示)。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    我已经验证了修订版2.1电路板上的代码、但遗憾的是、它的行为是相同的。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    我再次测试了代码、现在它看起来工作正常。 当时我不知道问题是什么。