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.

[参考译文] TMS570LC4357:通过 I2C 从 MPU 6050读取信息

Guru**** 2482105 points
Other Parts Discussed in Thread: TMS570LC4357, HALCOGEN

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

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/898914/tms570lc4357-reading-information-from-mpu-6050-via-i2c

器件型号:TMS570LC4357
主题中讨论的其他器件: HALCOGEN

您好!

我正在尝试从连接到 TMS570LC4357微控制器的 MPU 6050传感器获取信息(加速度和角速率)。

我能够获取将此传感器连接到 Arduino Mega 板的此信息。 但是、当我尝试为 Hercules 微控制器复制中的代码时、我不会获得相同的数据(我获得随机数)。 我在这两种情况下都执行相同的操作、我确信 MPU 6050会返回信息。 只是这些信息毫无意义。 我只能获得几次正确的信息、但当我第二次尝试时、它再次返回随机数。

我将 Arduino MEGA、MPU 6050和 Hercules Micro 连接到同一总线。 我曾尝试过中断、禁用内部上拉电阻器和使用外部电阻器等、但似乎不起作用。 Arduino 与 Hercules 的连接完全正常(Hercules 作为主站)、Arduino MPU6050也是正确的。  

您是否有什么想法会导致这种奇怪的行为?

感谢您抽出宝贵的时间进行思考。 此致、

塞尔吉奥

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

    您好!

    为了读取内部 MPU6050寄存器、主器件发送一个起始条件、后跟 I2C 从器件地址和写入位、然后是要读取的寄存器地址。 在接收到来自 MPU6050的 ACK 信号时、主器件发送一个 START 信号、后跟从器件地址和读取位。 因此、MPU6050发送 ACK 信号和数据。 通信以一个不确认(NACK)信号和一个来自主器件的停止位结束。

    您可以在 TMS570上共享 I2C 代码吗?

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

    这是从从从器件读取数据的示例代码:

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    //主接收功能//
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    /********* /
    ////设置从机以接收数据
    /********* /

    /*等待 MST 位被清零,这将进行
    *清除总线忙后的几个周期*/
    while (i2cIsMasterReady (i2cREG1)!= true);

    /*配置要与*/通话的从机地址
    i2cSetSlaveAdd (i2cREG1、PCF8570_address);

    /*将方向设置为发送器*/
    /*注意:可选-在 Init 中完成*/
    i2cSetDirection (i2cREG1、I2C_transmitter);

    /*配置数据计数*/
    /*读取之前从器件地址+字地址写入操作*/
    i2cSetCount (i2cREG1、receive_data_setup);

    /*将模式设置为主设备*/
    i2cSetMode (i2cREG1、I2C_MASTER);

    /*设置编程计数后停止*/
    i2cSetStop (i2cREG1);

    /*发送开始条件*/
    i2cSetStart (i2cREG1);

    /*发送字地址*/
    i2cSendByte (i2cREG1、Slave_Word_address);

    /*等待总线忙被清除*/
    while (i2cIsBusy (i2cREG1)=true);

    /*等待直到检测到停止*/
    while (i2cIsStopDetected (i2cREG1)=0);

    /*清除停止条件*/
    i2cClearSCD (i2cREG1);

    /********* /
    ////开始从从属方接收数据
    /********* /

    /*等待 MST 位被清零,这将进行
    *清除总线忙后的几个周期*/
    while (i2cIsMasterReady (i2cREG1)!= true);

    /*配置要与*/通话的从机地址
    i2cSetSlaveAdd (i2cREG1、PCF8570_address);

    /*将方向设置为接收器*/
    i2cSetDirection (i2cREG1、I2C_RECEIVER);

    /*配置数据计数*/
    /*注:可选-在 Init 中完成,除非用户想要更改*/
    i2cSetCount (i2cREG1、data_count);

    /*将模式设置为主设备*/
    i2cSetMode (i2cREG1、I2C_MASTER);

    /*设置编程计数后停止*/
    i2cSetStop (i2cREG1);

    /*发送开始条件*/
    i2cSetStart (i2cREG1);

    /*轮询模式下的 Transmit data_count 数据数量*/
    i2cReceive (i2cREG1、DATA_COUNT、RX_Data_Master);

    /*等待总线忙被清除*/
    while (i2cIsBusy (i2cREG1)=true);

    /*等待直到检测到停止*/
    while (i2cIsStopDetected (i2cREG1)=0);

    /*清除停止条件*/
    i2cClearSCD (i2cREG1);

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

    QJ Wang、您好!

    感谢你的帮助。 我真的很感谢。

    我有一个与您发布的代码类似的代码。 我想回顾一下、在将 TMS570与两个1080iinos 连接时、此代码能够完美地工作。 它是与 MPU6050的连接失败。  

    现在、我能够写入 MPU6050的寄存器(我检查了该值是否实际被修改)、但我无法接收信息。 为了测试这一点、我尝试将数据写入寄存器(0x6B)、然后读取写入的数据。 这可以使用 Arduino、该案例的代码非常简单:

    Wire.beginTransmission(MPU_addr);
    Wire.write (0x6B);
    Wire.write (8);//写入8
    Wire.endTransmission (真);

    Wire.beginTransmission(MPU_addr);
    Wire.write (0x6B);
    Wire.endTransmission (false);
    Wire.requestFrom (MPU_addr、1、true);


    这是完美的。 我必须在此强调、当我想接收时、我正在写入 Wire.endTransmission (false)、因为我不想发送停止条件、而是重新启动条件。  

    我正在对 TMS570LC43微控制器执行完全相同的操作(或者至少我认为我是)。 下面是我使用的代码:

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    //主接收功能//
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    /********* /
    ////将数据发送到从机以写入寄存器0x68
    /********* /

    /*等待 MST 位被清零,这将进行
    *清除总线忙后的几个周期*/
    while (i2cIsMasterReady (i2cModule)!= true);

    /*配置要与*/通话的从机地址
    i2cSetSlaveAdd (i2cModule、MPU6050address);

    /*将方向设置为发送器*/
    /*注意:可选-在 Init 中完成*/
    i2cSetDirection (i2cModule、I2C_transmitter);

    /*配置数据计数*/
    /*读取之前从器件地址+字地址写入操作*/
    i2cSetCount (i2cModule、2);

    /*将模式设置为主设备*/
    i2cSetMode (i2cModule、I2C_MASTER);

    /*设置编程计数后停止*/
    i2cSetStop (i2cModule);

    /*发送开始条件*/
    i2cSetStart (i2cModule);

    /*发送字地址*/
    i2cSendByte (i2cModule、register_adress);
    i2cSendByte (i2cModule、8);

    //等待总线忙被清除
    while (i2cIsBusy (i2cModule)=true);

    //等待,直到检测到停止
    while (i2cIsStopDetected (i2cModule)= 0);

    //清除停止条件
    i2cClearSCD (i2cModule);

    /********* /
    ////在0x68寄存器中接收到我之前写入的数据
    /********* /

    //发送0x68寄存器的地址

    /*配置要与*/通话的从机地址
    i2cSetSlaveAdd (i2cModule、MPU6050address);

    /*将方向设置为发送器*/
    /*注意:可选-在 Init 中完成*/
    i2cSetDirection (i2cModule、I2C_transmitter);

    /*配置数据计数*/
    //不是必需的,因为在这种情况下我不想发送停止条件
    i2cSetCount (i2cModule、1);

    /*将模式设置为主设备*/
    i2cSetMode (i2cModule、I2C_MASTER);

    /*发送开始条件*/
    i2cSetStart (i2cModule);//无停止条件被设定

    /*发送字地址*/
    i2cSendByte (i2cModule、register_adress);


    //接收数据

    //配置要与之通信的从机地址
    i2cSetSlaveAdd (i2cModule、MPU6050address);

    //将方向设定到接收器
    i2cSetDirection (i2cModule、I2C_receiver);

    //配置数据计数
    //注:可选-除非用户想要更改,否则它是在 Init 中完成的
    i2cSetCount (i2cModule、1);

    //将模式设置为主机
    i2cSetMode (i2cModule、I2C_MASTER);

    //设置编程计数后的停止
    i2cSetStop (i2cModule);

    //发送启动条件
    i2cSetStart (i2cModule);

    //轮询模式中的 Transmit data_count 个数据
    i2c 接收器(i2c 模块、1、Rx_Data_Master);

    //等待总线忙被清除
    while (i2cIsBusy (i2cModule)=true);

    //等待直到检测到停止
    while (i2cIsStopDetected (i2cModule)= 0);

    //清除停止条件
    i2cClearSCD (i2cModule);

    printf ("到达结尾\n");

     

    该序列结束后、寄存器的内容不是8。 我知道我在该寄存器中写入了8、因为 Arduino 告诉我我我是。 因此、我的接收操作不正确。 我认为问题是在重新启动条件下。 在发送寄存器地址后、我想读取信息。

    感谢您投入宝贵的时间和精力。 祝你一切顺利、

    塞尔吉奥

    --编辑--

    我已经读出、如果 BB 位和 STT 位都设置为1、则会生成 START 条件。 使用之前的代码、我看到当我尝试接收时、在 i2cSetStop 语句之后 BB 位被设置为零。 如果我在 i2csetStartCondition 之后移动 i2csetStop 条件、我会希望它能够正常工作。 但是、我仍然看不到寄存器中的8值。

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

    请通过配置 PINMUX 寄存器(HALCoGen 中的选项卡)来检查 I2C 信号是否在分配的终端上被启用为输出。

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

    您好、Sunil、

    在 Halcogen 的 PINMUX 选项卡中、我已经启用了 I2C2模块的 SCL 和 SDA 信号、这是我要使用的模块。 在你的注释之后、我还在 Halcogen 的 I2C2选项卡中启用了两个信号的输出方向。 但结果与以前相同。 我可以写入、但我无法读取。

    您是否认为这可能是重复启动条件?

    此致、

    塞尔吉奥

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

    您好、Sergio、

    可以使用重复模式。 如果要使用重复模式、应设置 RM 位。  

    您未在代码中设置 RM 位和 STP 位:

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

    QJ Wang、您好!

    非常感谢您的回答。 我更改了代码以在接收字节之前设置 RM 位和 STP 位强制(我只想接收一个字节)、但它不起作用。 我还尝试在 i2cReceive 语句之后设置 STP 位、但结果相同。 您认为我应该在其他地方设置这些位吗?

    /*等待 MST 位被清零,这将进行
    *清除总线忙后的几个周期*/
    while (i2cIsMasterReady (i2cModule)!= true);

    //发送0x68寄存器的地址

    //配置要与之通信的从机地址
    i2cSetSlaveAdd (i2cModule、MPU6050address);

    //设置发送器的方向
    i2cSetDirection (i2cModule、I2C_transmitter);

    //配置数据计数
    i2cSetCount (i2cModule、1);

    //将模式设置为主机
    i2cSetMode (i2cModule、I2C_MASTER);

    //启用重复模式
    i2cModule->MDR |= 0x80;

    //发送启动条件
    i2cSetStart (i2cModule);

    //发送字地址
    i2cSendByte (i2cModule、register_adress);

    //接收数据

    //配置要与之通信的从机地址
    i2cSetSlaveAdd (i2cModule、MPU6050address);

    //将方向设定到接收器
    i2cSetDirection (i2cModule、I2C_receiver);

    //配置数据计数
    i2cSetCount (i2cModule、1);

    //将模式设置为主机
    i2cSetMode (i2cModule、I2C_MASTER);

    //发送启动条件
    i2cSetStart (i2cModule);

    //设置编程计数后的停止
    i2cSetStop (i2cModule);

    //轮询模式中的 Transmit data_count 个数据
    i2cReceive (i2cModule、1、&receivedDataArray[0]);

    //等待总线忙被清除
    while (i2cIsBusy (i2cModule)=true);

    //等待直到检测到停止
    while (i2cIsStopDetected (i2cModule)= 0);

    //清除停止条件
    i2cClearSCD (i2cModule);

    感谢你能抽出时间。 此致、

    塞尔吉奥

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

    我已经意识到(因为我处于调试模式并放置一个断点)如果是加号

    for (delay = 0;delay<10000;delay)

    在发送包含我要读取的地址的字节后、我可以读取刚才写入的数据。 您对这种行为的原因有什么看法吗?

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

    如果使用停止条件、则需要在下一次传输之前检查总线是否空闲。

    如果不使用 STOP、请在开始下一次传输前检查 ARDY 位和 NACK 位:

    例如:

    while (((i2cREG1->STR & I2C_NACK)=0)&&((i2cREG1->STR & I2C_ARDY)=0));

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

    QJ Wang、您好!

    实际上、将延迟循环替换为您建议的句子、最终得到相同的正确结果。 我可以从 MPU 6050读取。 但是、我不理解这里的逻辑。

    我确实理解 ARDY 位(当它为1表示我们已将数据发送到从器件)、但为什么我们必须等到 NACK 位等于1? 我希望在发送字节后立即从器件接收 ACK、因此 NACK 位应为0。

    我显然错了、因为这条线解决了我的问题、但我仍然不知道原因。

    感谢你能抽出时间。 这真的是很好的支持。