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:I2C 代码在 MAP_I2C_masterSendMultiByteStart 处挂起

Guru**** 2553450 points


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

https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/594348/msp432p401r-i2c-code-hangs-at-map_i2c_mastersendmultibytestart

器件型号:MSP432P401R

我已经构建了一个新的电路板、我正在尝试使 I2C 功能正常工作。 每当我调用 MAP_I2C_masterSendMultiByteStart 时、我的代码就会挂起。 具体而言、在 driverlib 函数中的这一点上:  

while (!BITBAND_peri (EUSCI_B_CMSIS (模态)->rIFG.r、UCTXIFG_OFS))
;

我正在使用示例、针对我正在使用的 SCL 和 SDA 引脚进行了更新(P6.6 - UCB3SDA、和 P6.7 - UCB.S)。

附件是我的代码。 是什么导致它挂起?

当我从逻辑分析仪查看我的代码时、它表明只有 SDA 发送数据、而 SCL 上没有发生任何情况。

我修复了 SCL 线路上的硬件错误(Toombstoned 终端电阻器)、现在我的逻辑分析仪上根本没有任何东西。 总线上的所有连接似乎都是完整的、并且似乎没有任何其他硬件错误。 终端电阻器为3.3K 欧姆。

 e2e.ti.com/.../i2c_5F00_master_5F00_rw_5F00_repeated_5F00_start_2D00_master_5F00_code.ce2e.ti.com/.../6708.startup_5F00_msp432p401r_5F00_ccs.c

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    所示为您的电路原理图。
    μ I²C 信号的电压电平是多少?
    此软件是原始示例代码、还是您更改了某个内容?
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    随附了电路原理图。 当 jerry 像在原始示例代码中那样操纵到引脚1.6和1.7时、它工作正常。

    上传的代码不是原始示例。 B0已更改为 B3、我已将 EUSCI_B_I2C_Transmit INTERRUPT0更改为 EUSCI_B_I2C_Transmit INTERRUPT3

    我使用的代码如下、我使用的是 MSP432 SDK (driverlib)

    /*
    --------------------------------
    * MSP432 DriverLib - v4_00_00_11
    *----------------------
    *
    *-版权所有-、BSD、BSD
    *版权所有(c) 2017、德州仪器(TI)公司
    *保留所有权利。
    *
    *
    只要
    符合以下条件*、允许以源代码和二进制形式重新分发和使用:
    *
    *源代码的重新分发必须保留上述版权
    声明*、此条件列表和以下免责声明。
    *
    ***二进制形式的再发行必须在
    
    *随发行提供的文档和/或其他材料中复制上述版权声明、本条件列表和以下免责声明。
    *
    ***未经
    
    事先书面许可、不得使用德州仪器公司的名称或*其贡献者的名称认可或推广从本软件衍生的产品*。
    *
    *本软件由版权所有者和贡献者"按原样"提供
    *、
    
    不承担任何明示或暗示的保证、包括但不限于*适销性和特定用途适用性的暗示保证*。 在任何情况下、版权所有者或
    *贡献者都不对任何直接、间接、偶然、特殊、
    *模范、 或相应的损害(包括但不限于
    *采购替代产品或服务;丧失使用、数据或利润;
    *或业务中断)、但出于任何责任理论
    、*无论是在合同中、严格责任还是由于
    使用本软件而以任何方式产生的侵权行为(包括疏忽或*其他)
    、*即使已获悉可能会发生此类损坏。
    *--/版权--*/
    
    * MSP432 I2C - EUSCI_B3_base I2C 主器件 TX 字节到 MSP432从器件-重复启动
    *
    说明:此演示通过 I2C 总线连接两个 MSP432。 主
    设备*发送到从设备。 这是主代码。 它持续
    *传输一组数据、并演示如何实现 I2C
    *主发送器、发送多个字节、后跟重复起始
    *和读取多个字节。
    这是从传感器等 I2C 从器件读取寄存器值的常见操作。
    写入的 I2C 的*事务如下所示:
    *
    *______________________________
    *|开始| | |开始| | |
    *| 0x48Addr | 0x04 | 0x00 | 0x48Addr |<10 Byte Read>| Stop |
    *| W | | | R | | |
    *|_________________ _________________ _________________ _________________ _________________________________ _________________ |
    *
    * ACLK = n/a、MCLK = HSMCLK = SMCLK = BRCLK =默认 DCO =~3.0MHz
    *
    /|\/|\
    * MSP432P401 10k 10k MSP432P401
    * 从器件 || Master
    * -------- |||---
    * | P1.6/UCB3SDA|-|--+-|P1.6/UCB3SDA |
    * | || | |
    * | || | |
    * | P1.7/UCB.S.|<!---- >|P1.7/UCB.S. |
    * | | | |
    *
    作者:Timothy Logan
    /*
    DriverLib 定义了*/
    #include 
    
    /*标准定义*/
    #include 
    
    #include 
    #include 
    
    /* I2C 从机的从机地址*/
    #define SLAVE_ADDRESS 0x48
    #define NUM_OF_REC_Bytes 10
    
    /*变量*/
    const uint8_t TXData[2]={0x04、0x00};
    static uint8_t RXData[NUM_OF_REC_Bytes];
    static volatile UINT32_t xferIndex;
    static volatile bool MasterSent;
    
    /* I2C Master Configuration parameter */
    
    {i2i2ec_stopeConfig_bytes}
    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 (void)
    {
    volatile uint32_t ii;
    
    /*禁用看门狗*/
    MAP_WDT_A_HOLDTimer();
    
    /*为 I2C 选择端口1 -将引脚6、7设置为输入主模块功能、
    (UCB3SIMO/UCB3SDA、UCB3SOMI/UCB.S.)。
    *
    MAP_GPIO_setPeripheralModuleFunctionInputPin (GPIO_PORT_P6、
    GPIO_PIN6 + GPIO_PIN7、GPIO_PRIMARY_MODULE_FUNCTION);
    stopSent = false;
    memset (RXData、0x00、NUM_OF_REC_Bytes);
    
    /*以100kHz 的频率将 I2C 主设备初始化为 SMCLK,而不进行自动停止*/
    MAP_I2C_initMaster (EUSCI_B3_base、&i2cConfig);
    
    /*指定从地址*/
    MAP_I2C_setSlaveAddress (EUSCI_B3_base、SLAVE_ADDRESS);
    
    /*将主设备设置为传输模式*/
    MAP_I2C_setMode (EUSCI_B3_base、EUSCI_B_I2C_Transmit);
    
    /*启用 I2C 模块以启动操作*/
    MAP_I2C_enableModule (EUSCI_B3_base);
    
    /*启用和清除中断标志*/
    MAP_I2C_clearInterruptFlag (EUSCI_B3_base、
    EUSCI_B_I2C_Transmit INTERRUPT3 + EUSCI_B_I2C_Receive_INTERRUPT3);
    //启用主机接收中断
    MAP_I2C_enableInterrupt (EUSCI_B3_base、EUSCI_B_I2C_Transmit、INTERRUPT3);
    MAP_Interrupt_enableSlepOnIsrExit();
    MAP_Interrupt_enableInterrupt (INT_EUSCIB3);
    
    while (1)
    {
    /*确保最后一个交易已完全发送*/
    while (MAP_I2C_masterIsStopSent (EUSCI_B3_base)= EUSCI_B_I2C_Sending _stop);
    
    /*发送开始和发送缓冲区的第一个字节。 我们必须发送
    *两个字节、用于清理缓冲区中的任何内容
    *发送*/
    MAP_I2C_masterSendMultiByteStart (EUSCI_B3_base、TXData[0]);
    MAP_I2C_masterSendMultiByteNext (EUSCI_B3_base、TXData[0]);
    
    
    /*在发送 STOP 后启用传输中断*/
    MAP_I2C_enableInterrupt (EUSCI_B3_base、EUSCI_B_I2C_Transmit、INTERRUPT3);
    
    /*当停止条件尚未发出时... *
    while (!stopSent)
    {
    MAP_PCM_gotoLPM0InterruptSafe ();
    }
    
    stopSent = false;
    }
    }
    
    /*********
    * eUSCIB3 ISR。 重复的启动和发送/接收操作在
    该 ISR 内发生*。
    秘书长的报告 /
    void EUSCIB3_IRQHandler (void)
    {
    uint_fast16_t status;
    
    STATUS = MAP_I2C_getEnabledInterruptStatus (EUSCI_B3_base);
    MAP_I2C_clearInterruptFlag (EUSCI_B3_base、status);
    
    /*如果我们到达发送中断、则意味着我们位于的索引1
    *传输缓冲区。 重复启动时、我们才会到达
    *我们需要将模式更改为接收模式的最后一个字节、设置开始
    *条件发送位、然后将最终字节加载到 TXBUF 中。
    *
    IF (STATUS 和 EUSCI_B_I2C_Transmit INTERRUPT3)
    {
    MAP_I2C_masterSendMultiByteNext (EUSCI_B3_base、TXData[1]);
    MAP_I2C_DisableInterrupt (EUSCI_B3_base、EUSCI_B_I2C_Transmit、INTERRUPT3);
    MAP_I2C_setMode (EUSCI_B3_base、EUSCI_B_I2C_Receive_mode);
    xferIndex = 0;
    MAP_I2C_masterReceiveStart (EUSCI_B3_base);
    MAP_I2C_enableInterrupt (EUSCI_B3_base、EUSCI_B_I2C_Receive_INTERRUPT3);
    
    }
    
    /*将字节接收到接收缓冲区中。 如果我们已接收所有字节、
    *发送停止条件*/
    IF (STATUS & EUSCI_B_I2C_Receive_INTERRUPT3)
    {
    if (xferIndex = NUM_OF_REC_Bytes - 2)
    {
    MAP_I2C_masterReceiveMultiByteStop (EUSCI_B3_base);
    RXData[xferIndex++]= MAP_I2C_ReceivmasterMultiByteNext (EUSCI_B3_base);
    }
    否则、如果(xferIndex = NUM_OF_REC_Bytes - 1)
    {
    RXData[xferIndex++]= MAP_I2C_ReceivmasterMultiByteNext (EUSCI_B3_base);
    MAP_I2C_DisableInterrupt (EUSCI_B3_base、EUSCI_B_I2C_Receive_INTERRUPT3);
    MAP_I2C_setMode (EUSCI_B3_base、EUSCI_B_I2C_Transmit);
    xferIndex = 0;
    stopSent = true;
    MAP_Interrupt_disableSlepOnIsrExit();
    }
    其他
    {
    RXData[xferIndex++]= MAP_I2C_ReceivmasterMultiByteNext (EUSCI_B3_base);
    }
    
    }
    
    
    

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    eUSCI 模块有四个中断标志、能够处理四个不同的从器件地址。

    在主控模式下、每个模块只有一个中断、因此必须使用 EUSCI_B_I2C_Transmit INTERRUPT0。 (不同的模块具有不同的中断矢量。)
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    我明白了。 我需要将引脚设置为次级侧而不是初级侧。