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:MSP432 I2C 重复启动示例代码在发送中断轮询时挂起

Guru**** 2577385 points


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

https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/601074/msp432p401r-msp432-i2c-repeat-start-example-code-hanging-at-transmit-interrupt-poll

器件型号:MSP432P401R

需要一些帮助。 我一直在尝试使用 driverlib 示例 I2C 重复启动程序来连接到 Si7051x 温度芯片、运气很差。  

问题1:只能在按下 RESET 按钮后对逻辑分析仪上的 I2C 进行采样。 在按下复位按钮后立即捕获时、这就是我从分析仪获得的结果。

 

 

 

 

 

不带时钟拉伸的 Si7051的测量序列见本文档第14页。

http://www.silabs.com/documents/public/data-sheets/Si7050-1-3-4-5-A20.pdf

问题2:暂停调试时在以下行停止。 就好像没有任何东西进入 TXBUF 一样  

//轮询发送中断标志。
while (!BITBAND_peri (EUSCI_B_CMSIS (模态)->rIFG.r、UCTXIFG_OFS))

我使用的代码如下:感谢您的帮助。

#include "driverlib.h"

/*标准定义*/

#include

#include

#include

#include

/* I2C 从机的从机地址*/

#define SLAVE_ADDRESS IC_ADDRESS_TMP7051_ADDRESS

#define NUM_OF_REC_Bytes 2.

/*变量*/

//const uint8_t TXData[2]= 0;

静态 uint8_t RXData[NUM_OF_REC_BYes];

静态易失性 uint32_t xferIndex;

静态易失性 bool stopSent;

/* I2C 主配置参数*/

const eUSCI_I2C_MasterConfig i2cConfig =

EUSCI_B_I2C_CLOCKSOURCE_SMCLK、// SMCLK 时钟源

3000000、// SMCLK = 3MHz

EUSCI_B_I2C_SET_DATA_RATE 100KBPS//所需的100kHz I2C 时钟

0、//无字节计数器阈值

EUSCI_B_I2C_NO_AUTO_STOP //无自动停止

};

int main (空)

静态易失性 uint32_t ii;

/*禁用看门狗*/

MAP_WDT_A_HOLDTimer();

/*为 I2C 选择端口1 -将引脚6、7设置为输入主模块功能、

(UCB0SIMO/UCB0SDA、UCB0SOMI/UCB.S.)。

*

MAP_GPIO_setPeripheralModuleFunctionInputPin (GPIO_PORT_P1、

GPIO_PIN6 + GPIO_PIN7、GPIO_PRIMARY_MODULE_FUNCTION);

//stopSent = false;

memset (RXData、0x00、NUM_OF_REC_Bytes);

/*以100kHz 的频率将 I2C 主设备初始化为 SMCLK,而不进行自动停止*/

MAP_I2C_initMaster (EUSCI_B0_BASE、&i2cConfig);

/*指定从地址*/

MAP_I2C_setSlaveAddress (EUSCI_B0_BASE、SLAVE_ADDRESS);

/*将主设备设置为传输模式*/

MAP_I2C_setMode (EUSCI_B0_BASE、EUSCI_B_I2C_Transmit 模式);

/*启用 I2C 模块以启动操作*/

MAP_I2C_enableModule (EUSCI_B0_BASE);

/*启用和清除中断标志*/

MAP_I2C_clearInterruptFlag (EUSCI_B0_BASE、EUSCI_B_I2C_Receive_INTERRUPT0);

MAP_I2C_clearInterruptFlag (EUSCI_B0_BASE、EUSCI_B_I2C_NAK_INTERRUPT);

MAP_I2C_clearInterruptFlag (EUSCI_B0_BASE、EUSCI_B_I2C_Transmit _INTERRUPT0);

//启用主机发送中断

MAP_I2C_enableInterrupt (EUSCI_B0_BASE、EUSCI_B_I2C_NAK_INTERRUPT);

MAP_I2C_enableInterrupt (EUSCI_B0_BASE、EUSCI_B_I2C_Receive_INTERRUPT0);

MAP_I2C_enableInterrupt (EUSCI_B0_BASE、EUSCI_B_I2C_Transmit INTERRUPT0);

MAP_Interrupt_enableSlepOnIsrExit();

MAP_Interrupt_enableInterrupt (INT_EUSCIB0);

while (1)

MAP_I2C_enableInterrupt (EUSCI_B0_BASE、EUSCI_B_I2C_Transmit INTERRUPT0);

///map_I2C_enableInterrupt (EUSCI_B0_BASE、EUSCI_B_I2C_Receive_INTERRUPT0);

/*确保最后一个交易已完全发送*/

while (MAP_I2C_masterIsStopSent (EUSCI_B0_BASE)== EUSCI_B_I2C_Sending _stop);

/*发送开始和发送缓冲区的第一个字节。 我们必须发送

*两个字节、用于清理缓冲区中的任何内容

*发送*/

//map_I2C_masterSendSingleByte (EUSCI_B0_BASE、MEAS_TEMP_HOLD_register);

while (MAP_I2C_isBusBusy (EUSCI_B0_BASE)== EUSCI_B_I2C_BUS_BUS_BUSY);

//{

MAP_I2C_masterSendStart (EUSCI_B0_BASE);

MAP_I2C_masterSendMultiByteStart (EUSCI_B0_BASE、MEAS_TEMP_NOHOLD_register);

MAP_I2C_masterSendMultiByteNext (EUSCI_B0_BASE、MEAS_TEMP_NOHOLD_register);

/*在发送 STOP 后启用传输中断*/

MAP_I2C_enableInterrupt (EUSCI_B0_BASE、EUSCI_B_I2C_Transmit _INTERRUPT0 + EUSCI_B_I2C_Receive_INTERRUPT0);

//map_Interrupt_enableSlepOnIsrExit();

//map_PCM_gotoLPM0InterruptSafe ();

/*当停止条件尚未发出时... *

// while (!stopSent)

//{

//map_PCM_gotoLPM0InterruptSafe ();

//}

//stopSent = false;

/*传输之间的延迟*/

/*********

* eUSCIB0 ISR。 发生重复的启动和发送/接收操作

*。

秘书长的报告 /

EUSCIB0_IRQHandler ()

uint_fast16_t status;

STATUS = MAP_I2C_getEnabledInterruptStatus (EUSCI_B0_BASE);

MAP_I2C_clearInterruptFlag (EUSCI_B0_BASE、STATUS);

// IF (状态& EUSCI_B_I2C_NAK_INTERRUPT)

//{

//map_I2C_masterSendSingleByte (EUSCI_B0_BASE、MEAS_TEMP_NOHOLD_register);

//}

/*如果我们到达发送中断、则意味着我们位于的索引1

*传输缓冲区。 重复启动时、我们才会到达

*我们需要将模式更改为接收模式的最后一个字节、设置开始

*条件发送位、然后将最终字节加载到 TXBUF 中。

*

IF (STATUS & EUSCI_B_I2C_Transmit _INTERRUPT0)

//map_I2C_masterSendSingleByte (EUSCI_B0_BASE、MEAS_TEMP_HOLD_register);

MAP_I2C_masterSendMultiByteNext (EUSCI_B0_BASE、MEAS_TEMP_NOHOLD_register);

MAP_I2C_DisableInterrupt (EUSCI_B0_BASE、EUSCI_B_I2C_Transmit INTERRUPT0);

MAP_I2C_setMode (EUSCI_B0_BASE、EUSCI_B_I2C_Receive_mode);

xferIndex = 0;

MAP_I2C_masterReceiveStart (EUSCI_B0_BASE);

MAP_I2C_enableInterrupt (EUSCI_B0_BASE、EUSCI_B_I2C_Receive_INTERRUPT0);

//map_I2C_masterReceiveMultiByteNext (EUSCI_B0_BASE);

/*将字节接收到接收缓冲区中。 如果我们已接收所有字节、

*发送停止条件*/

IF (STATUS & EUSCI_B_I2C_Receive_INTERRUPT0)

if (xferIndex = NUM_OF_REC_Bytes - 2)

MAP_I2C_masterReceiveMultiByteStop (EUSCI_B0_BASE);

RXData[0]= MAP_I2C_masterReceiveMultiByteNext (EUSCI_B0_BASE);

xferIndex++;

否则、如果(xferIndex = NUM_OF_REC_Bytes - 1)

RXData[1]= MAP_I2C_masterReceiveMultiByteNext (EUSCI_B0_BASE);

MAP_I2C_DisableInterrupt (EUSCI_B0_BASE、EUSCI_B_I2C_Receive_INTERRUPT0);

MAP_I2C_setMode (EUSCI_B0_BASE、EUSCI_B_I2C_Transmit 模式);

xferIndex = 0;

//stopSent = true;

//map_Interrupt_disableSlepOnIsrExit();

其他

RXData[xferIndex++]= MAP_I2C_ReceivmasterMultiByteNext (EUSCI_B0_BASE);

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

    逻辑分析仪屏幕截图已剪切。 但愿如此。

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

    我想为您介绍一下。 请给我一点时间深入了解、我会尽快返回给您。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    InovBlue、

    几个问题。

    问题1)
    1) 1)当您启动调试和闪存时、当您单击运行时、您在 I2C 线路上看不到任何内容?
    2) 2)复位后、您是否在 RxData 数组中看到任何数据? 它会发生什么变化?

    第二个问题)
    1) 1)当您在下面的代码行上挂起时、它在您正在开发的主程序中停止了什么 I2C DriverLib 函数调用?
    //轮询发送中断标志。
    while (!BITBAND_peri (EUSCI_B_CMSIS (模态)->rIFG.r、UCTXIFG_OFS))

    暂停调试时、RxData 数组中是否有任何内容?
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    Evan、感谢您的支持。

    回答您的问题。

    当我连接到器件并单击调试按钮并运行时、SCL 线路被拉低并在每次捕获期间保持低电平。 我对这个问题的想法是、由于我没有将它完全转换到 while (1)循环的末尾、它会在  中的 while (!BITBAND_peri (EUSCI_B_CMSIS (moduleInstance)->rIFG.r、UCTXIFG_OFS))挂起  

    MAP_I2C_masterSendMultiByteStart (EUSCI_B0_BASE、MEAS_TEMP_NOHOLD_register)例程。  

    还注意到、 除非我第一次重启(拔下/重新插上)、否则它不会进入 EUSCIB0_IRQHandler。 在我进行调试时、我能够单步执行代码、并通过 EUSCIB0_IRQHandler 将其完全实现  

    暂停时、它始终在 MAP_I2C_masterSendMultiByteStart 例程中挂起。

    只有在上电后我单步执行例程时、RXData 才会在 RxData[0]中接收数据。  

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

    是否可以删除 I2C_sendMultiByteStart()调用之前的以下行?

    MAP_I2C_masterSendStart (EUSCI_B0_BASE);

    SendMultiByteStart()已经发送了一个 start 命令,我认为这是以某种方式挂起的,因为 Si 设备只需要一个 start 命令。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    我将会因内在活动而关闭此主题。 如果您有与上述主题无关的另一个问题、请发布另一个主题、如果您有任何其他与此相关的问题、请随时在此处发布、主题将重新打开。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    InovBlue、

    您正在处理的有关主/从重复启动 I2C 示例的示例实际上有更新。 您可以查看并重试吗? 这是为了帮助缓解看起来与您所看到的类似的错误。  
    dev.ti.com/.../

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

    Evan、

    感谢您的跟进并让我意识到这一变化。 我看了一下、ISR 更加清晰、并遵循了技术参考手册的重复启动顺序。 稍后测试。 谢谢。

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

    由于不活动、我将关闭此线程。 如果您对本主题有其他问题、请随时回复重新打开主题。