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.

[参考译文] MSP432-调试 器:MSP432P401R 无法获取 I2C 重复启动条件以使其正常工作

Guru**** 2524550 points


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

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/1201698/msp432-debuggers-msp432p401r-cannot-get-i2c-repeated-start-condition-to-work-properly

器件型号:MSP432-调试 器

我正在尝试实现 I2C 读取函数来支持 KT0806L_v1.8 FM 调制器器件、 在 MSP432项目中需要一个重复的启动条件。

我运行的是 Bluetopia Stack v4.4.1.1。  但是、当尝试执行具有重复起始条件的读取时、写入工作正常、由于在向写入命令发送地址值之后外设希望发送停止条件、因此我遇到问题。 这将导致序列结束、并且读取返回无效数据。

我已经读取了许多线程、并且已经看到您必须如何在最后一个字节输出之前通过切换模式进行接收等来欺骗 TX ISR 内部的外设  示例驱动程序库(如下)就是这样尝试的、但这对默认示例工程不起作用:  

C:\temp\msp432_driverlib_3_21_00_05\msp432_driverlib_3_21_00_05\examples\MSP432P4xx\i2c\i2c_master_rw_repeed_start-master_code。

我能够获得此论坛上的用户提供的以下代码以在独立的示例项目中工作:

https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/650134/msp432p401r-in-i2c-master-how-to-send-one-byte-to-slave-repeat-start-and-read-one-byte-by-interrupt-method

但是、当我将它移植到我的 A3DPDemo_src 项目时、它不起作用。  停止条件由外设生成并终止重复启动条件、从而全部中断读取函数、并导致 KT Micro 设备上的状态机返回错误数据进行读取。  

这是一本很好的读物、它使用了我从上面的链接获得的示例代码。  您可以看到停止条件发生、读取操作会恢复有效值。

在 My Project 中添加相同的代码时 、您可以看到停止条件出现、读取返回错误数据:

此外、该序列永不结束、使外设处于未知状态。

我注意到 I2C 外设非常依赖时序、因此我想补充一点、示例代码以3MHz MCLK 速度运行、波特率为100Kbps、而我的项目具有24MHz 时钟和100Kbps 波特率。  我基本上试图将代码中的延迟增加8倍、但这不起作用。

这是我将用于示例项目和我正在开发的项目的代码。

    //Turn on FM Mod
    GPIO_setOutputHighOnPin(GPIO_PORT_P4, GPIO_PIN6);
    //GPIO_setOutputHighOnPin(HRDWCFG_FM_EN_PORT_NUM, HRDWCFG_FM_EN_PIN_NUM);
    GPIO_setAsOutputPin(GPIO_PORT_P4, GPIO_PIN6);

    /* Disabling the Watchdog */
    MAP_WDT_A_holdTimer();

    /* Select Port 1 for I2C - Set Pin 6, 7 to input Primary Module Function,
     *   (UCB0SIMO/UCB0SDA, UCB0SOMI/UCB0SCL).
     */
    MAP_GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P1,
            GPIO_PIN6 + GPIO_PIN7, GPIO_PRIMARY_MODULE_FUNCTION);

    /* Initializing I2C Master to SMCLK at 400kbs with no autostop */
    MAP_I2C_initMaster(EUSCI_B0_BASE, &i2cConfig);

    /* Specify slave address */
    MAP_I2C_setSlaveAddress(EUSCI_B0_BASE, SLAVE_ADDRESS);

    /* Set Master in transmit mode */
    //MAP_I2C_setMode(EUSCI_B0_BASE, EUSCI_B_I2C_TRANSMIT_MODE);

    /* Enable I2C Module to start operations */
    MAP_I2C_enableModule(EUSCI_B0_BASE);

    __delay_cycles(10000);

        /* Send out start + address + 1 data byte */
    MAP_I2C_masterSendMultiByteStart(EUSCI_B0_BASE, TXData);

    //wait for first byte to be moved to shift register
    while(!(EUSCI_B0->IFG & EUSCI_B_IFG_TXIFG));
    EUSCI_B0->IFG &= ~(EUSCI_B_IFG_TXIFG);

    // Before the restart is sent, app has to wait for current TX byte + ack to complete
    // This takes 9 cycles at 100kHz = 90uS
    // The MCLK default = ~3MHz
    // to complete the 1 byte TX app needs to wait ~270 MCLK cycles at a minimum
    __delay_cycles(300);

    //clear the TR bit to setup master as receiver
     EUSCI_B0->CTLW0 &= ~(EUSCI_B_CTLW0_TR);
    // Send the start + address
     EUSCI_B0->CTLW0 |= EUSCI_B_CTLW0_TXSTT;
    // wait for address to be sent
    while(!(EUSCI_B0->CTLW0 & EUSCI_B_CTLW0_TXSTT));
    // set stop immediately to ensure only one byte is read
    EUSCI_B0->CTLW0 |= EUSCI_B_CTLW0_TXSTP;
    // poll RX flag
    while(!(EUSCI_B0->IFG & EUSCI_B_IFG_RXIFG0));
    // Read from Receive buffer
    RXData = EUSCI_B0->RXBUF;
    // ensure I2C transaction has completed
    while (MAP_I2C_masterIsStopSent(EUSCI_B0_BASE));

提前感谢您帮助我解决这个问题。

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

    您好 Ozzy、

    很抱歉初始回复的延迟、您提供了很多详细信息、并在这里完成了很多腿的工作。 我们的工程团队正在内部审查这些详细信息、并将于下周提供初步反馈。

    此致、

    拉尔夫·雅各比

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

    您好 Ozzy、

    从我们可以根据您的特定问题确定的问题与之前已解决的问题来看、您所面临的问题在很大程度上取决于您的特定用例的时间、因为您可以使原始解决方案自行运行。 增加延迟将是其中一项建议、可能需要进一步调查、以确定是否存在延迟间隔有效。

    至于其它方法、可探索的一个方法是参考以下包含寄存器级调用的 MSP430示例: https://dev.ti.com/tirex/explore/node?devices=MSP430F5529&devtools=MSP430F5529&node=A__AAgA6nQUp0MrAIFqRqRUrA__msp430ware__IOGqZri__LATEST

    MSP432P4和该 MSP430器件之间的 eUSCI 接口具有相同的工作原理、因此、具有重复启动功能的示例将是超越 MSP432 SDK 现有功能的最佳参考点。

    此致、

    拉尔夫·雅各比

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

    Ralph

    我已经玩了拖延,使它与我的项目的 MCLK 速度相称,但这不起作用。  我也尝试过其他的价值和没有运气。  

    为何执行重复启动条件如此困难?   驱动程序库中的示例无法正常工作、或者至少我无法使其正常工作。

    MCLK 速度是否太快而无法执行此任务?

    Ozzy.

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

    您好 Ozzy、

    上面提到的示例适用于另一个 TI MCU、该 MCU 具有 MSP432P4器件中的 eUSCI 接口、该示例完全依赖于 DRM 级别编码-通过避免使用 DriverLib API、可能可以解决计时问题。 至少这是提供备选代码作为可能的解决方案背后的想法。

    我不会认为 MCLK 速度太快、因为与其他 MCU 相比、MCLK 速度并没有明显降低。

    此致、

    拉尔夫·雅各比

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

    我当前使用的代码也是 DRM 的大部分除了设置和初始发送..   我可以将初始发送部分分解到 DRM 级别、看看 这是否会有所帮助并回复给您。

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

    您好 Ozzy、

    我找到了另一位工程师来审核您的情况、通过审核得出了以下几点想法:

    1. 由于示例项目以3MHz 的频率运行并且这样可以工作、您能否向该示例添加时钟配置代码以使 MCLK 以24MHz 的频率运行? 这将使您能够在工作示例代码中测试较高的系统时钟加上8倍的延迟增量的组合。 如果运行正常、那么问题将更具体地出现在您的应用中、但如果示例代码以比根本原因更高的时钟速率中断、则所提供的权变措施有一个限制。
    2. 如果 以 24MHz 的频率运行、扩展延迟不起作用、则会出现一个问题、即检查标志等的序列是否执行得太快。 例如、初始延迟也许很重要、 但是、如果代码执行速度太快、则重复启动的输出速度会比3MHz 时更快、并改为注册为停止条件-部分原因是重复启动信号的波形看起来是 一个 使 24MHz 代码具有更窄的尖峰。

    如果对于具有基本示例代码且频率为24MHz 的 MSP432 LaunchPad 而言、此问题是可重复的、那么这也将让我们能够复制故障并研究标志等。

    此致、

    拉尔夫·雅各比

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

    Ralph

    我回去,使所有的代码 DRM,这不起作用。

    然后、我检查了与我的应用的 MCLK 相比有效的示例项目的 MCLK 速度。  示例项目以3MHz 的频率运行、而 A3DPDemoSource 项目以24MHz 的频率运行、这是处理 Bluetopia 栈和保持 BT 正常运行所需的 MIPS。 我开始提高采样项目 MCLK 的速度以查看它是否可以处理更快的时钟。  在6MHz 频率下、重复启动条件正常工作、在12MHz 频率下、也是在模块启用后发生的延迟增加后正常工作。  不过、一旦我转到24MHz、它就会中断、我开始看到与我在项目中看到的结果相同。  

    有人在24MHz MCLK 下测试了 I2C 重复启动条件吗?   其他功能正常、但重复启动条件不起作用。

    此致、

    Ozzy.

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

    您好 Ozzy、

    是否有人在24MHz MCLK 下测试过 I2C 重复启动条件?   其他功能有效,但不能重复启动条件。

    我猜可能没有给出之前的 E2E 帖子等

    您能否共享您测试的、在24MHz 频率下无法工作的修改示例代码项目、以及显示与您的 Bluetopia 项目相同的结果? 这将让我们从您所在的同一个点开始、以便我们可以查看时序/延迟等、从而了解随着 MCLK 速度的提高、可能会中断这一过程。

    此致、

    拉尔夫·雅各比

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

    您好 Ozzy、

    在 测试前面提供的示例时、我的同事能够在与另一个 LaunchPad 通信的 MSP432P4 LaunchPad 上以24MHz 频率重新创建代码中断。 基于此、需要在检查标志之后添加停止位之前进行调整。 以进行测试、从而解决问题。

    其代码如下所示:

    /* --COPYRIGHT--,BSD
     * Copyright (c) 2017, Texas Instruments Incorporated
     * All rights reserved.
     *
     * Redistribution and use in source and binary forms, with or without
     * modification, are permitted provided that the following conditions
     * are met:
     *
     * *  Redistributions of source code must retain the above copyright
     *    notice, this list of conditions and the following disclaimer.
     *
     * *  Redistributions in binary form must reproduce the above copyright
     *    notice, this list of conditions and the following disclaimer in the
     *    documentation and/or other materials provided with the distribution.
     *
     * *  Neither the name of Texas Instruments Incorporated nor the names of
     *    its contributors may be used to endorse or promote products derived
     *    from this software without specific prior written permission.
     *
     * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
     * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
     * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
     * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
     * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
     * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
     * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
     * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     * --/COPYRIGHT--*/
    /******************************************************************************
     *  MSP432 I2C - EUSCI_B0 I2C Master TX 1 bytes to MSP432 Slave
     *  and reads one byte back following a repeated start
     *
     *  Description: This demo connects two MSP432 's via the I2C bus. The master
     *  transmits to the slave. This is the MASTER CODE.
     *  _________________________________________________________
     *  |  Start   |      |  Start   |                   |       |
     *  | 0x48Addr | 0x04 | 0x48Addr |  <1 Byte Read>    |  Stop |
     *  |    W     |      |    R     |                   |       |
     *  |__________|______|__________|___________________|_______|
     *
     *  ACLK = n/a, MCLK = HSMCLK = SMCLK = BRCLK = default DCO = ~3.0MHz
     *
     *                                /|\  /|\
     *                MSP432P4111     10k  10k      MSP432P4111
     *                   slave         |    |         master
     *             -----------------   |    |   -----------------
     *            |     P1.6/UCB0SDA|<-|----+->|P1.6/UCB0SDA     |
     *            |                 |  |       |                 |
     *            |                 |  |       |                 |
     *            |     P1.7/UCB0SCL|<-+------>|P1.7/UCB0SCL     |
     *            |                 |          |                 |
     *
      *****************************************************************************/
    /* DriverLib Defines */
    #include <ti/devices/msp432p4xx/driverlib/driverlib.h>
    
    /* Slave Address for I2C Slave */
    #define SLAVE_ADDRESS       0x48
    #define NUM_OF_REC_BYTES    1
    
    /* Variables */
    const uint8_t TXData[] = {0x41,0x42};
    unsigned char RXData=0;
    
    /* I2C Master Configuration Parameter */
    const eUSCI_I2C_MasterConfig i2cConfig =
    {
            EUSCI_B_I2C_CLOCKSOURCE_SMCLK,          // SMCLK Clock Source
            24000000,                                // SMCLK = 3MHz
            EUSCI_B_I2C_SET_DATA_RATE_100KBPS,      // Desired I2C Clock of 100khz
            0,                                      // No byte counter threshold
            EUSCI_B_I2C_NO_AUTO_STOP                // No Autostop
    };
    
    int main(void)
    {
        /* Disabling the Watchdog  */
        MAP_WDT_A_holdTimer();
    
        /* Select Port 1 for I2C - Set Pin 6, 7 to input Primary Module Function,
         *   (UCB0SIMO/UCB0SDA, UCB0SOMI/UCB0SCL).
         */
    
        MAP_CS_initClockSignal(CS_MCLK, CS_MODOSC_SELECT, CS_CLOCK_DIVIDER_1);
        MAP_CS_initClockSignal(CS_SMCLK, CS_MODOSC_SELECT, CS_CLOCK_DIVIDER_1);
    
        MAP_GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P1,
                GPIO_PIN6 + GPIO_PIN7, GPIO_PRIMARY_MODULE_FUNCTION);
        MAP_GPIO_setAsOutputPin(GPIO_PORT_P3, GPIO_PIN0);
    
        /* Initializing I2C Master to SMCLK at 100khz with no autostop */
        MAP_I2C_initMaster(EUSCI_B0_BASE, &i2cConfig);
    
        /* Specify slave address */
        MAP_I2C_setSlaveAddress(EUSCI_B0_BASE, SLAVE_ADDRESS);
    
        /* Enable I2C Module to start operations */
        MAP_I2C_enableModule(EUSCI_B0_BASE);
    
        /* Send out start + address + 1 data byte */
        MAP_I2C_masterSendMultiByteStart(EUSCI_B0_BASE, TXData[1]);
    
        //wait for first byte to be moved to shift register
        while(!(EUSCI_B0->IFG & EUSCI_B_IFG_TXIFG));
        EUSCI_B0->IFG &= ~(EUSCI_B_IFG_TXIFG);
    
        // Before the restart is sent, app has to wait for current TX byte + ack to complete
        // This takes 9 cycles at 100kHz = 90uS
        // The MCLK default = ~3MHz
        // to complete the 1 byte TX app needs to wait ~270 MCLK cycles at a minimum
        __delay_cycles(2500);
    
        //clear the TR bit to setup master as receiver
         EUSCI_B0->CTLW0 &= ~(EUSCI_B_CTLW0_TR);
    
        // Send the start + address
         EUSCI_B0->CTLW0 |= EUSCI_B_CTLW0_TXSTT;
    
         __delay_cycles(250);
    
        // wait for address to be sent
        while(!(EUSCI_B0->CTLW0 & EUSCI_B_CTLW0_TXSTT));
        // set stop immediately to ensure only one byte is read
        EUSCI_B0->CTLW0 |= EUSCI_B_CTLW0_TXSTP;
        // poll RX flag
        while(!(EUSCI_B0->IFG & EUSCI_B_IFG_RXIFG0));
        // Read from Receive buffer
        RXData = EUSCI_B0->RXBUF;
        // ensure I2C transaction has completed
        while (MAP_I2C_masterIsStopSent(EUSCI_B0_BASE));
    
        while(1);
    }
    

    插入的延迟为250个周期、从测试来看、100个周期是不够的、但200个以上的周期可以正常工作。 选择250来留下一些缓冲。

    请查看该调整是否适用于您的示例项目和 Bluetopia 项目。 如果它不适用于您的示例项目、我们需要公布您的示例项目以比较设置等

    此致、

    拉尔夫·雅各比

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

    Ralph

    这达到了目的。  

    谢谢!

    Ozzy.