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.

[参考译文] MSP430FR5994:I2C 主器件通信问题

Guru**** 2813875 points

Other Parts Discussed in Thread: MSP430FR5994

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

https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/1597924/msp430fr5994-i2c-master-communication-issue

器件型号: MSP430FR5994

大家好、

我正在尝试实现中的 I2C 主器件读写操作 MSP430FR5994 使用可用的库函数与从设备(RTC 和计数器)进行通信、如下所示、但遗憾的是、它无法按预期工作


我们在调试时没有观察到以下要点、

->调试时任何无限循环卡住的情况

->不存在上拉等硬件侧问题

(项目执行优先级较高)

/*  代码开始  ***************** * ***************** /

void i2cPinInt()

  GPIO_setAsPeripheralModuleFunctionInputPin (GPIO_PORT_P5、
                        GPIO_PIN0 | GPIO_PIN1、
                        GPIO_PRIMARY_MODULE_FUNCTION
                        );
}

// U16_i2cBase -> EUSCI_B1_BASE
void EUSCI_B_I2C_INIT (uint16_t U16_i2cBase、uint32_t u32_dataate)

  EUSCI_B_I2C_initMasterParam i2cParam ={0};

  // i2c 参数
  i2cParam.selectClockSource = EUSCI_B_I2C_CLOCKSOURCE_SMCLK;
  i2cParam.i2cClk = CS_getSMCLK ();
  i2cParam.datrate = u32_datrate;
  i2cParam.byteCounterThreshold = 0;
  i2cParam.autoSTOPGeneration = EUSCI_B_I2C_NO_AUTO_STOP;

  //初始化主设备
  EUSCI_B_I2C_initMaster (U16_i2cBase、&i2cParam);

  //启用 I2C 模块
  EUSCI_B_I2C_ENABLE (U16_i2cBase);

  EUSCI_B_I2C_setMode (U16_i2cBase、EUSCI_B_I2C_TRANSMIT_MODE);

  返回;
}

void i2cReadByte (uint16_t U16_i2cBase、
        uint8_t u8_slaveId、uint8_t u8_regAddr、
        uint8_t *pu8_data
        )

  //在 i2c 总线中设置从器件 ID
  EUSCI_B_I2C_setSlaveAddress (U16_i2cBase、u8_slaveId);

  //切换到传输模式
  EUSCI_B_I2C_setMode (U16_i2cBase、EUSCI_B_I2C_TRANSMIT_MODE);

  //首先发送寄存器地址
  EUSCI_B_I2C_masterSendSingleByte (U16_i2cBase、u8_regAddr);
  while (EUSCI_B_I2C_isBusBusy (U16_i2cBase));

  //接收数据
  *pu8_DATA = EUSCI_B_I2C_masterReceiveSingleByte (U16_i2cBase);
  while (EUSCI_B_I2C_isBusBusy (U16_i2cBase));

  返回;
}


void i2cReadBytes (uint16_t U16_i2cBase、
         uint8_t u8_slaveId、uint8_t u8_regAddr、
         uint8_t *pu8_data、uint16_t U16_length
         )

  uint16_t U16_INDEX = 0;

  //在 i2c 总线中设置从器件 ID
  EUSCI_B_I2C_setSlaveAddress (U16_i2cBase、u8_slaveId);

  //切换到传输模式
  EUSCI_B_I2C_setMode (U16_i2cBase、EUSCI_B_I2C_TRANSMIT_MODE);

  //首先发送寄存器地址
  EUSCI_B_I2C_masterSendSingleByte (U16_i2cBase、u8_regAddr);
  while (EUSCI_B_I2C_isBusBusy (U16_i2cBase));

  //主器件接收开始
  EUSCI_B_I2C_MASTERReceiverveStart (U16_i2cBase);

  //接收数据
  for (U16_INDEX = 0;U16_INDEX < U16_LENGTH - 1;+U16_INDEX)
  {
    while(!EUSCI_B_I2C_getInterruptStatus (U16_i2cBase、EUSCI_B_I2C_RECEIVE_INTERRUPT0));
    pu8_data[U16_index]= EUSCI_B_I2C_masterReceiveMultiByteNext (U16_i2cBase);
  }

  //接收最后一个字节
  pu8_data[U16_index]= EUSCI_B_I2C_masterReceiveMultiByteFinish (U16_i2cBase);

  返回;
}


void i2cWriteByte (uint16_t U16_i2cBase、
        uint8_t u8_slaveId、uint8_t u8_regAddr、
        uint8_t *pu8_data
        )

  //在 i2c 总线中设置从器件 ID
  EUSCI_B_I2C_setSlaveAddress (U16_i2cBase、u8_slaveId);

  //切换到传输模式
  EUSCI_B_I2C_setMode (U16_i2cBase、EUSCI_B_I2C_TRANSMIT_MODE);

  EUSCI_B_I2C_masterSendMultiByteStart (U16_i2cBase、u8_regAddr);

  while(!EUSCI_B_I2C_getInterruptStatus (U16_i2cBase、EUSCI_B_I2C_TRANSMIT_INTERRUPT0));

  //发送数据
  EUSCI_B_I2C_masterSendMultiByteFinish (U16_i2cBase、pu8_data[0]);

  返回;
}


void i2cWriteBytes (uint16_t U16_i2cBase、
         uint8_t u8_slaveId、uint8_t u8_regAddr、
         uint8_t *pu8_data、uint16_t U16_length
         )

  uint8_t u8_index = 0;

  //在 i2c 总线中设置从器件 ID
  EUSCI_B_I2C_setSlaveAddress (U16_i2cBase、u8_slaveId);

  //切换到传输模式
  EUSCI_B_I2C_setMode (U16_i2cBase、EUSCI_B_I2C_TRANSMIT_MODE);

  //首先发送寄存器地址
  EUSCI_B_I2C_masterSendMultiByteStart (U16_i2cBase、u8_regAddr);

  //传输数据
  for (u8_INDEX = 0;u8_INDEX <(U16_LENGTH - 1);++u8_INDEX)
  {
    while(!EUSCI_B_I2C_getInterruptStatus (U16_i2cBase、EUSCI_B_I2C_TRANSMIT_INTERRUPT0));
    EUSCI_B_I2C_masterSendMultiByteNext (U16_i2cBase、pu8_data[u8_index]);
  }

  //发送最后一个字节
  EUSCI_B_I2C_masterSendMultiByteFinish (U16_i2cBase、pu8_data[u8_index]);

  返回;
}

/**************** * *************** 代码结束  */

请协助我们验证相同内容

谢谢

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

    有两点:

    1) 为您的代码使用编辑器的“插入:代码“功能。

    2) 它是如何工作的? 无法启动? 从器件没有响应? 数据无法读取? 是否已写入?

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

    2) 它是如何工作的? 无法启动? 从器件没有响应? 数据无法读取? 是否已写入?

    我认为、要么没有向器件写入正确的数据、要么没有从器件中读取正确的数据。

    从逻辑上讲、如果我考虑 I2C 操作、那么库函数序列为通信保留的内容 看起来是正确的

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

    1) 为您的代码使用编辑器的“插入:代码“功能。
    根据我的理解、您要求在工程创建期间包含驱动程序代码、如果是、我们在创建工程时也执行了相同的操作

    2) 它是如何工作的? 无法启动? 从器件没有响应? 数据无法读取? 是否已写入?

    我认为、没有向器件写入正确的数据或从器件读取正确的数据。

    从逻辑上讲、如果我考虑 I2C 操作、那么为 i2c 操作保持的库函数序列看起来是正确的

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

    void EUSCI_B_I2C_INIT(uint16_t u16_i2cBase, uint32_t u32_dataRate)
    {
        EUSCI_B_I2C_initMasterParam i2cParam = {0};
    
        // i2c parameters
        i2cParam.selectClockSource = EUSCI_B_I2C_CLOCKSOURCE_SMCLK;
        i2cParam.i2cClk = CS_getSMCLK();
        i2cParam.dataRate = u32_dataRate;
        i2cParam.byteCounterThreshold = 0;
        i2cParam.autoSTOPGeneration = EUSCI_B_I2C_NO_AUTO_STOP;
    
        // Initializing Master
        EUSCI_B_I2C_initMaster(u16_i2cBase, &i2cParam);
    
        // Enable I2C module
        EUSCI_B_I2C_enable(u16_i2cBase);
    
        EUSCI_B_I2C_setMode(u16_i2cBase, EUSCI_B_I2C_TRANSMIT_MODE);
    
        return;
    }
    
    
    void i2cReadByte(uint16_t u16_i2cBase,
                    uint8_t u8_slaveId, uint8_t u8_regAddr,
                    uint8_t *pu8_data
                    )
    {
        // Set slave id in i2c bus
        EUSCI_B_I2C_setSlaveAddress(u16_i2cBase, u8_slaveId);
    
        // Switch to transmit mode
        EUSCI_B_I2C_setMode(u16_i2cBase, EUSCI_B_I2C_TRANSMIT_MODE);
    
        // Send register address first
        EUSCI_B_I2C_masterSendSingleByte(u16_i2cBase, u8_regAddr);
        while(EUSCI_B_I2C_isBusBusy(u16_i2cBase));
    
        // Receive data
        *pu8_data = EUSCI_B_I2C_masterReceiveSingleByte(u16_i2cBase);
        while(EUSCI_B_I2C_isBusBusy(u16_i2cBase));
    
        return;
    }
    
    
    void i2cReadBytes(uint16_t u16_i2cBase,
                      uint8_t u8_slaveId, uint8_t u8_regAddr,
                      uint8_t *pu8_data, uint16_t u16_length
                      )
    {
        uint16_t u16_index = 0;
    
        // Set slave id in i2c bus
        EUSCI_B_I2C_setSlaveAddress(u16_i2cBase, u8_slaveId);
    
        // Switch to transmit mode
        EUSCI_B_I2C_setMode(u16_i2cBase, EUSCI_B_I2C_TRANSMIT_MODE);
    
        // Send register address first
        EUSCI_B_I2C_masterSendSingleByte(u16_i2cBase, u8_regAddr);
        while(EUSCI_B_I2C_isBusBusy(u16_i2cBase));
    
        // Master receive begin
        EUSCI_B_I2C_masterReceiveStart(u16_i2cBase);
    
        // Receive data
        for(u16_index = 0; u16_index < u16_length - 1; ++u16_index)
        {
            while(!EUSCI_B_I2C_getInterruptStatus(u16_i2cBase, EUSCI_B_I2C_RECEIVE_INTERRUPT0));
            pu8_data[u16_index] = EUSCI_B_I2C_masterReceiveMultiByteNext(u16_i2cBase);
        }
    
        // Receive last byte
        pu8_data[u16_index] = EUSCI_B_I2C_masterReceiveMultiByteFinish(u16_i2cBase);
    
        return;
    }
    
    
    void i2cWriteByte(uint16_t u16_i2cBase,
                    uint8_t u8_slaveId, uint8_t u8_regAddr,
                    uint8_t *pu8_data
                    )
    {
        // Set slave id in i2c bus
        EUSCI_B_I2C_setSlaveAddress(u16_i2cBase, u8_slaveId);
    
        // Switch to transmit mode
        EUSCI_B_I2C_setMode(u16_i2cBase, EUSCI_B_I2C_TRANSMIT_MODE);
    
        EUSCI_B_I2C_masterSendMultiByteStart(u16_i2cBase, u8_regAddr);
    
        while(!EUSCI_B_I2C_getInterruptStatus(u16_i2cBase, EUSCI_B_I2C_TRANSMIT_INTERRUPT0));
    
        // Send data
        EUSCI_B_I2C_masterSendMultiByteFinish(u16_i2cBase, pu8_data[0]);
    
        return;
    }
    
    
    void i2cWriteBytes(uint16_t u16_i2cBase,
                      uint8_t u8_slaveId, uint8_t u8_regAddr,
                      uint8_t *pu8_data, uint16_t u16_length
                      )
    {
        uint8_t u8_index = 0;
    
        // Set slave id in i2c bus
        EUSCI_B_I2C_setSlaveAddress(u16_i2cBase, u8_slaveId);
    
        // Switch to transmit mode
        EUSCI_B_I2C_setMode(u16_i2cBase, EUSCI_B_I2C_TRANSMIT_MODE);
    
        // Send register address first
        EUSCI_B_I2C_masterSendMultiByteStart(u16_i2cBase, u8_regAddr);
    
        // Transmit data
        for(u8_index = 0; u8_index < (u16_length - 1); ++u8_index)
        {
            while (!EUSCI_B_I2C_getInterruptStatus(u16_i2cBase, EUSCI_B_I2C_TRANSMIT_INTERRUPT0));
            EUSCI_B_I2C_masterSendMultiByteNext(u16_i2cBase, pu8_data[u8_index]);
        }
    
        // Transmit last byte
        EUSCI_B_I2C_masterSendMultiByteFinish(u16_i2cBase, pu8_data[u8_index]);
    
        return;
    }

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

    因此、您不知道它会失败的位置、甚至还没有尝试使用调试器逐步执行代码。

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

    I2C 初始化 成功(成功初始化时,LED 根据程序亮起)

    所有库函数的返回类型都是 void、没有成功/失败指示

    ->在写操作中,正在写入准确的数据

    ->在读取操作中、读取数据不同

    背后的原因无法确定它到底在哪里错了,因为

    ->读/写操作中维护的顺序

    (根据我的理解,它看起来是正确的)

    -> 应该包括的任何其他功能,但它是 从我们这边漏掉的

    所以我共享了代码、h/w 侧一切都很好

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

    我看不到代码有任何明显的问题。  

    1) 你如何调用这些函数? 也许有一条线索。

    2) 您的读取序列不使用重复启动。 有些器件需要 R-S、有些器件禁止它、大多数无关器件(从数据表中判断并不总是容易)。 您能给我们提供所用特定器件的器件型号吗?

    3) 一般: driverlib 函数不能用 NACK 从容地处理,所以要注意这一点。

    如果有示波器、可能会非常有帮助。

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

    连接的设备为 DS3231 (RTC) 和计数器

    (两个器件使用 TI-RTOS 封装运行正常,没有失败)

    根据最新观察结果、

    ->读取操作正常,默认值没有任何问题

    ->但当我们执行写入操作时,读取值变得 随机