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.

[参考译文] RTOS/TM4C123GH6PM:与 TI-RTOS 的 I2C 协议

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

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/744837/rtos-tm4c123gh6pm-i2c-protocol-with-ti-rtos

器件型号:TM4C123GH6PM
Thread 中讨论的其他器件:EK-TM4C123GXL

工具/软件:TI-RTOS

您好!

我正在尝试使用 TI-RTOS 从 MPU-6050获取数据。 我尝试了不同的解决方法并进行了调试。 不幸的是、"I2C_transfer (i2c、&i2cTransaction)"始终返回 false。  

我使用非 RTOS 找到了代码。 但我想使用 RTOS 实现。

请在这个问题上帮助我。  

非常感谢您的参与、

Yashwanth。

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

    请找到我的追踪代码。
    请改正我的问题。 我出错了

    e2e.ti.com/.../i2cmpu6050.c

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

    您对 I2C API 的使用是正确的。 我怀疑 MPU6050没有应答从器件地址。

    您应该使用逻辑分析仪检查 I2C 总线以进一步调试。

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

    在向寄存器0x6B 写入0x80复位 MPU6050后、需要让器件完成复位序列、然后才能禁用睡眠模式并将时钟写入0x01至0x6B。 执行此操作的一种方法是读取寄存器0x6B、直到您读取到 SLEEP 位已置位(0x40)。 然后写入0x01。

    (在2018年11月9日将0x68更正为0x6B)

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    建议:在将0x80写入寄存器0x68后。 我尝试使用 do - while 循环来获取寄存器0x68的寄存器值。 我将寄存器0x68读取为0x7f。 这意味着睡眠位被设置为1是它吗?
    即使在这之后、如果它尝试从0x3B 读取寄存器14寄存器、我也会获得7F 02 CF E3 14 EC B4 F6 AD...即使通过改变传感器的位置、这些值也会持续变化。

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

    我很抱歉。 从机地址为0x68、但电源管理寄存器的地址为0x6B。 (对我而言、他们看起来是一样的。) 将0x80写入寄存器0x6B。 然后读取寄存器0x6B。 您应该得到几次0x00、然后是0x40。 读取0x40后、将0x01写入该寄存器。 下面是一个非 RTOS 示例、其工作原理如下:

    /cfs-file/__key/communityserver-discussions-components-files/908/6646.MPU6050_2D00_2.zip

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

    e2e.ti.com/.../i2cmpu6050.zipHiBob Crosby、

    首先、感谢您耐心回答我的问题

    寄存器正确。

    请找到 我随附的 RTOS 代码并帮助我。

    注:大多数情况下 I2C_Transfer()为 false。

    谢谢、此致、

    Yashwanth

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

    好的、我认为我看到了问题。 MPU-6050寄存器地址和命令为8位、而不是16位。 您的代码编写如下:

    它实际上将0x6B 写入寄存器0、将0x80写入寄存器1、将0x00写入寄存器2。 它应如下所示:

    现在、您可以看到它从寄存器0x6B 读取0x40。 下面是对 writeRegister 和 readRegister 例程的一些简单修改。

    void writeRegister (I2C_Handle handle、uint16_t regAddr、uint16_t value)
    {
    uint8_t txBuffer[4];
    I2C_Transaction i2c 交易;
    
    i2cTransaction.slaveAddress = MPU6050_I2C_address;
    
    /*写入16位状态寄存器*/
    i2cTransaction.writeBuf = txBuffer;
    i2cTransaction.writeCount = 2;
    i2cTransaction.ReadCount = 0;
    
    txBuffer[0]= regAddr & 0xFF;//LB Addr
    TxBuffer[1]=值和0xFF;
    
    if (!I2C_transfer (handle、&i2cTransaction)){
    GPIO_WRITE (Board_LED2、Board_LED_ON);
    system_abort (" I2C 传输错误!");
    }
    }
    
    空 readRegister (I2C_Handle handle、
    uint16_t regAddr、
    uint8_t *数据、
    size_t length)
    {
    uint8_t txBuffer[2];
    I2C_Transaction i2c 交易;
    
    i2cTransaction.slaveAddress = MPU6050_I2C_address;
    
    /*写入16位状态寄存器*/
    i2cTransaction.writeBuf = txBuffer;
    i2cTransaction.readBuf =数据;
    i2cTransaction.writeCount = 1;
    i2cTransaction.ReadCount =长度;
    
    txBuffer[0]= regAddr & 0xFF;//LB Addr
    
    if (!I2C_transfer (handle、&i2cTransaction)){
    GPIO_WRITE (Board_LED2、Board_LED_ON);
    system_abort (" I2C 传输错误!");
    }
    }
    

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

    非常感谢您的调试和代码共享。 它确实对我有所帮助。

    我遇到了一个问题。 如果我在正常运行中运行代码并使用示波器点击 i2c 线、我能够在 SDA 线上查看数据。 当我尝试调试代码以在表达式窗口中获取值时,大多数情况下,在 First writeRegister()中调用 I2C_Transfer()本身返回 false,并且示波器中的数据始终为零。 您是否知道它的行为为何如此?

    即使按下复位按钮、该零值也是连续的。 如果我拔下电路板并进行连接、则其工作正常。

    注:要检查是否有任何 I2C_Transfer()失败,我将打开 LED。 以便 LED 在第一次调用 I2C_Transfer 后亮起。

    希望您的解释能让我清楚地了解这个问题及其工作原理。

    再次感谢您的帮助。

    此致、
    Yashwanth。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    听起来 MPU-6050有点混乱。 当您拔下电路板时、它是否也会关闭 MPU-6050的电源? 问题可能是当代码中有断点时、MPU-6050不会处理被挂起的 I2C 命令。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    是的。 当我拔下电源插头时、MPU 6050正在断电。 但是当我复位 MPU 6050时、它不会复位(我是说 MPU 6050上的 LED 不闪烁)

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    当我按下 Launchpad 上的重置按钮时。 I2C 通信将变为"I2C BAD 传输"。 这将一直持续到我拔下并插入 LaunchPad。 上电后、它将正常工作。
    Bob Crosby、您能在这个问题上帮我吗?

    此致、
    Yashwanth Kumar Gandeti
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    我可以重现您的问题。 由于您正在执行连续读取操作、因此当您在 EK-TM4C123GXL 上按 RESET 时、I2C 通信会在操作过程中停止。 MPU6050通过将 SDA 保持在低电平进行响应。 这会阻止进一步的 I2C 通信。

    首先、让我提醒您、MPU6050不是 TI 器件、我不是该器件的专家。

    为了最大限度地减小影响、我建议您不要连续读取。 通过将 INT 引脚配置为输出并对其进行采样(或将其用作中断)、您可以将读取次数最小化到仅在计算新读数时才读取。 这样可以最大限度地减少问题、但不能解决问题。 我将对它进行一些处理、看看如果 SDA 在复位后保持低电平、我是否可以通过位拆裂 I2C SCL 来强制 I2C 接口。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    非常感谢 Bob Crosby、
    我对你对议题的明确解释完全满意。

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

    以下是当 MPU6050将 SDA 保持在低电平时、我添加了要解决的代码(在"Board_initGPIO()"和"Board_initI2C()"之间添加的行)。

    int main (void)
    {
    Task_Params taskParams;
    
    /*呼叫板初始化函数*/
    Board_initGeneral();
    Board_initGPIO();
    //检查 I2C SDA 是否未被保持在低电平
    //如果是,切换 I2C SCL 直到它被释放
    GPIOPinTypeGPIOInput (GPIO_PORTD_BASE、GPIO_PIN_1);
    GPIOPinTypeGPIOOutput (GPIO_PORTD_base、GPIO_PIN_0);
    while (GPIOPinRead (GPIO_PORTD_base、GPIO_PIN_1)!= GPIO_PIN_1)
    {
    GPIOPinWrite (GPIO_PORTD_BASE、GPIO_PIN_0、0);
    GPIOPinWrite (GPIO_PORTD_base、GPIO_PIN_0、GPIO_PIN_0);
    }
    Board_initI2C();
    
    SysCtlClockSet (SYSCTL_SYSDIV_4|SYSCTL_USE_PLL|SYSCTL_XTAL_16MHz|
    SYSCTL_OSC_MAIN);
    
    /*构造 nfcLoad Task 线程*/
    Task_Params_init (&taskParams);
    taskParams.STACKSIZE = TASKSTACKSIZE;
    taskParams.stack =_task0Stack;
    taskParams.instance->name ="传感器";
    taskParams.priority = 1;
    Task_construct(&task0Struct,(Task_Functr) imuTask、&taskParams、NULL);
    
    GPIO_WRITE (Board_LED0、Board_LED_ON);
    
    system_printf ("启动 I2C 示例\n 系统提供程序设置为 SysMin。"
    "停止目标以查看 ROV 中的任何 SysMin 内容。\n");
    /* SysMin 仅在您调用 flush 或 exit 时才会打印到控制台*/
    system_flush();
    
    srand (0xBEA5);
    
    /*启动 BIOS */
    BIOS_start();
    
    返回(0);
    }
    

    SCL 中的脉冲太短、基本上被触发线隐藏、但您可以看到它会导致 MPU6050让 SDA 变为高电平。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    我非常感谢您 Bob Crosby。 您已清除与此问题相关的所有问题。 您的代码片段对我帮助很大。
    您对问题的持续支持和跟进非常出色。
    谢谢 TI。

    此致、
    Yashwanth Kumar Gandeti。