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.

[参考译文] MSP430FR2355:Driverlib I2C masterSendMultiByteStart 出现问题

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

https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/1167721/msp430fr2355-issue-with-driverlib-i2c-mastersendmultibytestart

器件型号:MSP430FR2355
主题中讨论的其他器件:TMP102

您好!

我使用 MSP430通过 I2C 与一些温度器件通信。 我使用的是 driverlib 库、并且在使用该库时遇到了 I2C 通道的奇怪行为。

当尝试重复发送多字节消息时、不会发送消息的第一个字节。 下面 是一个代码示例:

 

空 I2C_EUSCI_B1_Config ()

               Param.selectClockSource = EUSCI_I2C_CLOCKSOURCE_SMCLK;

               param.i2cClk = CS_getSMCLK ();

               param.datarate = EUSCI_B_I2C_SET_DATA_RATE_100KBPS;

               Param.autoSTOPGeneration = EUSCI_B_I2C_NO_AUTO_STOP;

               

               EUSCI_B_I2C_initMaster (EUSCI_B1_BASE、param);

               EUSCI_B_I2C_ENABLE (EUSCI_B1_BASE);

 

void main()

               while (1)

        {

               // I2C Tx 消息–0x01、0xAA

               EUSCI_B_I2C_setSlaveAddress (EUSCI_B1_BASE、TMP102_ADDRESS);

               EUSCI_B_I2C_masterSendMultiByteStart (EUSCI_B1_BASE、0x01);

               EUSCI_B_I2C_masterSendMultiByteNext (EUSCI_B1_BASE、0xAA);

        EUSCI_B_I2C_masterSendMultiByteStop (EUSCI_B1_BASE);

               

               // I2C Tx 消息–0x01、0xBA

               EUSCI_B_I2C_masterSendMultiByteStart (EUSCI_B1_BASE、0x01);

               EUSCI_B_I2C_masterSendMultiByteNext (EUSCI_B1_BASE、0xBA);

        EUSCI_B_I2C_masterSendMultiByteStop (EUSCI_B1_BASE);

        }

第一次进入 while 循环时、第一条消息被正确发送- 0x01、然后是0xAA。 但在接下来的消息中、不会再次发送0x01。

在所有消息中、只发送0xAA 和0xBA。

我看到另一个奇怪的行为、在发送第一条消息(0x01、0xAA)然后尝试发送单字节消息后、不发送数据字节... 仅提供地址。  

出于某种原因、它似乎会丢弃传输的第一个字节。

感谢您的帮助、

谢谢!

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

    我没有看到这种特定症状、但我怀疑它与非常早地请求停止有关、然后在发出停止前执行(重复)启动有关。 我认为这可能会导致"幻象"TXIFG 丢失下一个字节。

     EUSCI_B_I2C_masterSendMultiByteFinish 处理这个序列、所以在写入最后一个字节后请求停止。 对于您的两字节事务,请尝试用 SendMultiByteFinish 的调用替换对 SendMultiByteNext 的调用,并删除对 MultiByteStop 的调用。

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

    您好、Bruce、  

    感谢您的回复!

    我尝试了完全符合您的建议,但它不能解决问题。

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

    尝试在每次调用 SendMultiByteStop 后添加此行:

    > while (EUSCI_B_I2C_Sending _stop = EUSCI_B_I2C_masterIsStopSent (EUSCI_B1_base));//等待停止完成

    停止函数请求停止(UCTXSTP)、但不会等待它被发出、因此这会暂停、直到它完成。 由于这是一种写后操作、因此您也可以在调用"开始"之前执行此操作、这样您就可以同时执行其他操作(大约2字节时间)。

    正如我提到过的、这不是在停止等待时请求启动的"常见"症状、但当我添加该代码时、症状消失了。

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

    我尝试添加这一行、但它没有解决问题。 第一条消息仍然正常、但以下所有消息都是在没有第一个字节的情况下发送的(不发送0x01)。

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

    当我添加此行(两处)时、症状消失。

    我使用的是 LIS3DH、因为我没有 TMP102。

    除此之外、我不确定我们的表现如何。

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

    我注意到、在第一次0x01之后、0xF0消息被正确发送、如果我尝试发送一个单字节消息、那么无论我在代码中写入什么值、该消息中的值始终为0xFF。。。

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

    我无法复制您的设置。 您能描述您的平台吗? 您如何判断字节丢失? (我使用了 Launchpad、Adafruit 分线板和示波器。)

    您是否还没有发布其他代码? 具体而言:不应启用任何 I2C 中断。

    我想下一步是回到基础知识。 TI 在此处发布 eUSCI 故障排除文档:

    https://www.ti.com/lit/an/slaa734a/slaa734a.pdf

    您可以尝试一个(或多个) TI 示例、可能从 eusci_b_i2c_ex3_masterTxMultiple 开始(您必须自定义它):

    https://dev.ti.com/tirex/explore/node?node=A__AGgUyb0qJAc26U45ojcLdw__msp430ware__IOGqZri__LATEST

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

    MSP430安装在定制板上、我将使用示波器对其进行调试。 使用示波器、我可以看到字节丢失。

    我没有发布其他代码...  

    我注意到程序卡在"Wait for Stop Completion"循环中:
    while (EUSCI_B_I2C_Sending _stop = EUSCI_B_I2C_masterIsStopSent (EUSCI_B1_base));//等待停止完成

    通过查看 EUSCI_B1寄存器、我可以看到:

    UCB1STATW 寄存器:
    UCSCLLOW ='1'
    UCBBUSY='1'  

    UCB1CTLW0寄存器:
    UCTXSTT ="1"
    UCTXSTP='1'

    它不会在第一次迭代中卡住、而是在运行一段时间后卡住。

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

    这是一个奇怪的症状。 据我所知、如果 STT=1、您无法退出 SendMultiByteNext、而如果 STP=1、您无法退出该旋转环路、因此我不知道如何设置它们(避免这种情况是本练习的目标)。

    一个(通常是快速)诊断实验是减慢总线速度,这通常会改变症状--有时会变得更好,有时甚至更糟,但无论哪种方式都是一个线索。 SET_DATA_RATE 100KBPS 只是数字100000、因此您可以在其中放置一些其他数字。

    您的"param"变量是否位于全局存储中(即启动时初始化为0)?

    [编辑:少量澄清。]

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

    我刚刚在没有停机的情况下运行了半个多小时的设置(无中断)。 我想各个从器件的运行方式可能会有所不同、但 TMP102尤其声称它从未驱动 SCL、因此我不知道它会如何影响主器件。

    总之、为了清楚起见、我一直在使用以下内容:

    #include "driverlib.h"
    #define HZ          1000000UL   // 1MHz since we don't change it
    #define USE_I2CS    0           // Didn't replicate
    #define USE_FINISH  0           // Didn't fix
    #define WAIT_FOR_STOP 1         // Seems to work
    #if USE_I2CS
    #include "i2cs.h"               // Loopback slave on UCB0
    #define TMP102_ADDRESS  I2CS_ADDR
    #define REG_ADDR        0x01    // From the original
    #else
    #define TMP102_ADDRESS  0x18    // LIS3DH
    #define REG_ADDR        0x08    // Don't try to write reg 1
    #endif
    EUSCI_B_I2C_initMasterParam Param;
    void I2C_EUSCI_B1_Config()
    {
        P4OUT  |= (BIT6|BIT7);
        P4REN  |= (BIT6|BIT7);      // Enable pullups
        P4SEL0 |= (BIT6|BIT7);      // P4.6/7 as UCB1SDA/SCL per ds Table 6-66
        Param.selectClockSource = EUSCI_B_I2C_CLOCKSOURCE_SMCLK; // EUSCI_I2C_CLOCKSOURCE_SMCLK;
        Param.i2cClk = CS_getSMCLK();
        Param.dataRate = EUSCI_B_I2C_SET_DATA_RATE_100KBPS;
        Param.autoSTOPGeneration = EUSCI_B_I2C_NO_AUTO_STOP;
        EUSCI_B_I2C_initMaster(EUSCI_B1_BASE, &Param);
        EUSCI_B_I2C_enable(EUSCI_B1_BASE);
    }
    
    void main()
    {
        WDT_A_hold(WDT_A_BASE);
        PM5CTL0 &= ~LOCKLPM5;
        I2C_EUSCI_B1_Config();
    #if USE_I2CS
        i2cs_init();
    #endif // USE_I2CS
        __enable_interrupt();
        while(1)
        {
            // I2C Tx message – 0x01, 0xAA
            EUSCI_B_I2C_setSlaveAddress(EUSCI_B1_BASE, TMP102_ADDRESS);
            EUSCI_B_I2C_masterSendMultiByteStart(EUSCI_B1_BASE, REG_ADDR);
    #if USE_FINISH
            EUSCI_B_I2C_masterSendMultiByteFinish(EUSCI_B1_BASE, 0xAA);
    #else
            EUSCI_B_I2C_masterSendMultiByteNext(EUSCI_B1_BASE, 0xAA);
            EUSCI_B_I2C_masterSendMultiByteStop(EUSCI_B1_BASE);
    #endif // USE_FINISH
    #if WAIT_FOR_STOP
            while (EUSCI_B_I2C_SENDING_STOP == EUSCI_B_I2C_masterIsStopSent(EUSCI_B1_BASE));
    #endif // WAIT_FOR_STOP
    
            // I2C Tx message – 0x01, 0xBA
            EUSCI_B_I2C_masterSendMultiByteStart(EUSCI_B1_BASE, REG_ADDR);
    #if USE_FINISH
            EUSCI_B_I2C_masterSendMultiByteFinish(EUSCI_B1_BASE, 0xBA);
    #else
            EUSCI_B_I2C_masterSendMultiByteNext(EUSCI_B1_BASE, 0xBA);
            EUSCI_B_I2C_masterSendMultiByteStop(EUSCI_B1_BASE);
    #endif // USE_FINISH
    #if WAIT_FOR_STOP
            while (EUSCI_B_I2C_SENDING_STOP == EUSCI_B_I2C_masterIsStopSent(EUSCI_B1_BASE));
    #endif // WAIT_FOR_STOP
    
           // __delay_cycles(HZ/2);       // Pause to read the scope
        }
    }