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.

[参考译文] TM4C123GE6PM:MPU6050 SCL 线路在 MPU6050Init 之后保持低电平

Guru**** 2391275 points


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

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/739410/tm4c123ge6pm-mpu6050-scl-line-stays-low-after-mpu6050init

器件型号:TM4C123GE6PM

您好!

我使用以下代码尝试与 MPU6050传感器通信:

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#include 
#include 
#include "driverlib/debug.h"
#include "driverlib/gpio.h"
#include "driverlib/pin_map.h"
#include "driverlib/pwm.h"
#include "driverlib/rom.h"
#include "driverlib/sysctl.h"
#include "inc/hw_gpio.h"
#include "#include "包含"hw_map.h"#include "#include

//使用 NULL 指针

#define PWM_FREQUENCY 55

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//我的 I2C 定义并包括
#include "driverlib/i2c.h"
#include "driverlib/interrv.h"
#include "inc/hw_i2c.h"
#include
"sensorlib/i2cm_drv.h"
#include "sensorlib/mpu6050.h"////

/////////////////////////////////////////////////////////////#////#//////////////////////////#//////////////////////////#///////////////////////////////////////////



//我的 UART 定义并包括
#include "driverlib/uartstdio.h"
#include "utils/uartstdio.h"

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#include "definitions _mpu6050.h"
tI2CMInstance g_sI2CInst;// I2C 主驱动程序结构。 "tI2CMInstance"是在 i2cm_drv.h 文件中定义的。
tMPU6050 g_sMPU6050Inst;// MPU6050传感器驱动程序结构。 "tMPU6050"在 mpu6050.h 文件中定义。
volatile unsigned long g_vui8DataFlag;//数据就绪标志
volatile unsigned long g_vui8ErrorFlag;//错误标志

void
ISL29023I2CIntHandler (void)
{
I2CMIntHandler (&g_sI2CInst);
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
int main (void)
{

//配置时钟
SysCtlClockSet (SYSCTL_SYSDIV_5|SYSCTL_USE_PLL|SYSCTAL_16MHz|SYSCTL_OSC_MAIN);

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//我的 I2C 初始化代码

//启用包含 I2C 2的 GPIO 外设
// SysCtlPeripheralEnable (SYSCTL_Periph_GPIOD);
SysCtlPeripheralEnable (SYSCTL_Periph_GPIOE);

//启用 I2C 模块2
// SysCtlPeripheralEnable (SYSCTL_Periph_I2C3);
SysCtlPeripheralEnable (SYSCTL_Periph_I2C2);

//为端口 E4和 E5上的 I2C2功能配置引脚多路复用。
// GPIOPinConfigure (GPIO_PD0_I2C3SCL);
// GPIOPinConfigure (GPIO_PD1_I2C3SDA);
GPIOPinConfigure (GPIO_PE4_I2C2SCL);
GPIOPinConfigure (GPIO_PE5_I2C2SDA);

//为这些引脚选择 I2C 功能。
// GPIOPinTypeI2CSCL (GPIO_PORTD_BASE、GPIO_PIN_0);
// GPIOPinTypeI2C (GPIO_PORTD_BASE、GPIO_PIN_1);
GPIOPinTypeI2CSCL (GPIO_Porte _BASE、GPIO_PIN_4);
GPIOPinTypeI2C (GPIO_Porte _BASE、GPIO_PIN_5);

IntMasterEnable();

// I2CMInit (&g_sI2CInst、I2C3_base、INT_I2C3、0xFF、 0xFF、SysCtlClockGet ());
I2CMInit (&g_sI2CInst、I2C2_base、INT_I2C2、0xFF、0xFF、 SysCtlClockGet ();
SysCtlDelay (SysCtlClockGet ()/3);

fAccel[3]、fGyro[3];

//如果 MPU6050Init 成功,USER_MPU6050Callback 会将 g_BMPU6050Done 变量修改为 true。
G_bMPU6050Done = false;
//初始化 MPU6050
MPU6050Init (&g_sMPU6050Inst、&g_sI2CInst、MPU6050_I2C_address、USER_MPU6050Callback、&g_sMPU6050Inst);


while (!g_bMPU6050Done){}

//如果 MPU6050ReadModifyWrite 成功,USER_MPU6050Callback 会将 g_BMPU6050Done 变量修改为 true。
G_bMPU6050Done = false;
//将 MPU6050配置为+/- 4 g 加速计范围。
MPU6050ReadModifyWrite (&G) sMPU6050Inst、MPU6050_O_ACCEL_CONFIG、~MPU6050_ACCEL_CONFIG_AFS_SEL_M、MPU6050_ACCEL_CONFIG_AFS_SEL_4G、USER_MPU6050Callback、 &g_sMPU6050Inst);

while (!g_bMPU6050Done){}

while (1)
{
//如果 MPU6050DataRead 成功,USER_MPU6050Callback 会将 g_BMPU6050Done 变量修改为 true。
G_bMPU6050Done = false;
//从 MPU6050请求另一个读数。
MPU6050DataRead (&g_sMPU6050Inst、USER_MPU6050Callback、0);
while (!g_bMPU6050Done){}

//获取新的加速计和陀螺仪读数。
MPU6050DataAccelGetFloat (&g_sMPU6050Inst、&fAccel[0]、&fAccel[1]、&fAccel[2]);
MPU6050DataGyroGetFloat (&G) sMPU6050Inst、&fGyro[0]、&fGyro[1]、&fGyro[2]);
}
} 

我使用 F6逐步运行代码并转至 MPU6050Init 函数。

当这个函数被称为 I See (使用一个示波器)时、SDA 和 SCL I2C 线路正确切换并且 MPU6050确认到地址0x68。  

然而、当传输完成时、MPU6050将 SCL 线路保持在低电平并且不释放它。

根据 I2C 规范-这表示器件正在处理中断。 只有在我的情况下、它才会持续下去。

当我继续按 F6键进入 MPU6050ReadModifyWrite 函数时,将调用并完成该函数-但当我再次按 F6时 ,代码会卡在 while (!g_bMPU6050Done){}条件中。

是否有可能 MPU6050Init 不会使器件从复位状态释放 ?

与本帖子中提到的内容类似:

e2e.ti.com/.../315587

 

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

    您好!

     请查看 MPU6050数据表、了解在什么情况下它会将 SCL 保持在低电平。 I2C 从器件将 SCL 保持在低电平作为等待状态的一种方法是合法的。 但是、它应该在准备好从主器件获取命令后释放 SCL。  

     MPU6050是您连接到 MCU 的专用器件吗? BOOSTXL-SENSHUB 传感器集线器 Booster Pack 具有 MPU9150、其中有一个 TivaWare 示例。  

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

    您好!

    正如我写的那样、SCL 保持低电平表示器件正在处理一个中断...

    但这种情况永远持续下去...

    我没有 SENSHUB -只有 MPU6050。 它也是 Tivaware sensorlib 的一部分。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您好!
    根据 SCL 规范、SCL 保持低电平意味着器件正在处理中断、这意味着什么? 您在哪里阅读了该内容?

    您是否有逻辑分析仪来捕获 SDA 和 SCL 总线事务? 如果是、您能展示吗?
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

     www.nxp.com/.../UM10204.pdf
    第3.1.5节

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

    在波形的中间、有一点难以看到-您可以看到被拉至低电平的蓝色信号、从而确认事务。
    最后、您可以看到、蓝色线上升到稳定的"1"、同时 SCL 继续被 MPU6050拉低(在我很长时间之后查看波形时-它仍然为低电平)。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    我有一些意见。 您写道:

      MPU6050ReadModifyWrite (&G) sMPU6050Inst、MPU6050_O_ACCEL_CONFIG、~MPU6050_ACCEL_CONFIG_AFS_SEL_M、MPU6050_ACCEL_CONFIG_AFS_SEL_4G、USER_MPU6050Callback、 &g_sMPU6050Inst);

    • 首先,我建议您在调用 MPU6050ReadModifyWrite()后检查返回的值。 如果操作不成功、则返回 false。  
    • 传递给 API 的最后一个参数应为回调数据。 但是、您传递 了&g_sMPU6050Inst。 这是有什么原因的?
    • sensorlib 用户指南的第15.3节中提供了一个 MPU6050示例。 请参考此示例并与您的代码进行比较。  

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    感谢您的回答。
    请仔细查看示例-最后一个参数不是回调数据、而是 NULL 参数。
    我将其更改为&g_sMPU6050Inst、因为这是我在 Launchpad 的实验课程14中针对 ISL29023传感器(也是 I2C)看到的-除此之外、我的函数是相同的。
    无论如何、我会像 sensorlib 示例中一样将其更改为"0"、但仍然没有变化。

    一旦我使用 F6调用"MPU6050ReadModifyWrite"、代码就会挂起。
    当我暂停它时-我看到它被困在 FaultISR 内的 while (1)循环中。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好!

     我建议您使用 F5 (步入)而不是 F6 (步越)单步执行代码、以找出导致故障的代码行。 F6执行整个函数、您不知道函数内发生了什么。 很多时候、它可能与您分配的堆栈数量有关。 如果在链接器期间没有保留足够的堆栈、则可以获得堆栈溢出。 检查 CPU 中的 SP 寄存器并查看它指示的内容。 堆栈指针从0x20000000开始、如果您看到 SP 低于该值、则可以得到堆栈溢出故障。 这并不是说您确实遇到了堆栈溢出故障。 要了解导致故障的原因、以下应用手册将提供帮助。

    我还建议您先将堆栈大小增加到更大的值。 不确定您当前拥有的内容。 如果您保留了256字节、则更改为2048、以查看它是否有用。 如果堆栈大小增加不能解决问题、请参阅应用手册以诊断故障。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    我尝试使用堆栈大小、遇到了一些非常奇怪的行为。
    原始值为:100
    起初、我像图片中一样将大小更改为512、但结果不是很好...程序卡在 MPU6050Init (甚至比以前更早)。
    然后、我将堆栈大小更改为90 -这使程序卡在与100相同的位置(在 ReadModifyWrite 函数-比我用512得到的值还要远)。

    之后、我将其更改为150 -使用此值 ReadModifyWrite 可以正常工作。
    我按堆栈大小(100、90、512、150)运行了~10个测试、程序卡滞的点100%一致。

    就像堆栈大小的"甜点"一样、它是150 (!!!!!!!!!)
    什么会导致这种不稳定的行为?
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    更多信息-有关 I2C SCL 线路被拉低并保持在该状态的信息。
    不是 MPU6050将 SCL 拉低-它是 ARM!!

    我进行了以下测试:
    被称为 MPU6050Init 函数(导致 SCL 低电平条件)。
    2.已断开 ARM 和 MPU6050之间的 SCL 接线。
    3、在 MPU6050侧测量 SCL 电压-为3.3V (非拉电流)。
    4、在臂侧测量 SCL 电压-为0V。

    所以、
    我们有一种不稳定的行为、其特征是堆栈大小"甜蜜点"(150 -代码通常不会冻结在该位置)。
    此外、我们还让 ARM 在完成 MPU6050Init 事务后将 SCL 拉低(无论堆栈大小如何)。

    我在这里真的很不了解...
    也许它与某些变量是在主函数之外声明的事实有关系??
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您好!
    首先、我不知道为什么512堆栈大小不起作用、而150将起作用。 这对我来说毫无意义。 我建议您使用1024。 但是、如果您认为150会一直工作、那么请坚持使用它。 如果您从90开始、则它的堆栈大小太小、无法用于某些 API。

    您说过、在 MPU6050Init 被称为之后、SCL 将保持低电平。 但是、当您的代码继续使用 ReadModifyWrite 时、事务仍将继续、是否正确?
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    "您说过、MPU6050Init 被称为 SCL 后、它将保持低电平。 但是、当您的代码继续使用 ReadModifyWrite 时、事务仍将继续、这是否正确?"

    是-但仅当堆栈大小配置为150时。

    "但是、如果您认为150会一直工作、那么请坚持使用它"

    我不想为了 让我的程序以任何成本运行而隐藏地毯下面的灰尘...

    我真的想了解我的程序为何对堆栈大小变化敏感。 您是否查看过该代码? 看起来还可以吗?

    是否要我上传整个项目?

    我在这里真的很不了解...

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    当您有一个复杂的 API 来调用函数、并且其中的一些函数随后可以调用其他函数时、每个函数调用都是一个上下文切换、需要将当前上下文(即寄存器)推送到堆栈中。 如果在函数中声明局部变量、则也会使用栈。 所需的堆栈数量取决于应用。 与您分配的数量相比、TI-RTOS 的 ROV 等一些工具可以分析堆栈的实际使用情况。 当程序使用的堆栈多于指定的堆栈溢出故障所分配的堆栈时、程序将崩溃。 同样、需要多少堆栈取决于应用。 据我所知、所有 TivaWare 示例对小示例至少使用256字节。 一些更复杂的示例保留512或更多。 90最初使用的代码太小、尤其是使用 sensorlib API。 下面是一些讨论堆栈估算的链接。
    stackoverflow.com/.../stack-size-estimation。
    embeddedgurus.com/.../


    因此,有了足够的堆栈(您稍后使用150个堆栈),您会说 ReadModifyWrite 将在 MPU6050Init 之后工作。 当您在 MPU6050Init 上按 F6键、然后停止 CPU 时、您观察到 SCL 为低电平、对吧? 这意味着主器件仍拥有 I2C 总线。 它正在等待下一个事务继续。 我认为这是正常行为。 调用 ReadModifyWrite 后、它将继续执行下一个事务。 也许我应该以另一种方式提出这个问题。 如果您没有放置任何断点或单步执行、只需让它自由运行、它是否会继续运行到末尾、以及主器件是否已将所有预期数据发送到从器件? 如果是、那么我认为它正常工作。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    但是、当我将堆栈大小更改为更大的值-512时、为什么它不起作用?
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您是否以完全相同的方式在不同的堆栈大小下自由运行代码? 我无法理解为什么较大的堆栈尺寸会出现故障、而较小的堆栈尺寸则不会出现故障。 如果程序崩溃、堆栈大小为512、请使用应用手册、我参考调试故障源。 可能由于512堆栈大小的不同原因而发生故障、而不是堆栈溢出。

    此外、在我发送的文章中、您可以使用一些已知模式预加载存储器、然后运行代码。 然后、您将观察分配堆栈的存储器内容、以查看更改了哪些内容、您可以了解与分配的堆栈相比实际使用了多少堆栈。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    我将在几天内获得测试机会。

    当我释放运行 CPU 而不是逐步运行时,CPU 是否可能显示不同的行为?

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    这可能取决于您在代码中何时进行断点以及是否产生中断。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    好消息。

    我将堆栈大小更改为1024、并在没有断点的情况下自由运行代码。

    我在示波器上看到了 I2C 事务、因此不再卡住...

    因此、通过使堆栈像您建议的那样更大来解决问题(如果有)-谢谢!

    但我仍然不明白为什么我的代码在我使用 F6分步运行时会中断。

    您能不能建议一种会引发此类错误的特定方案。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    执行 F6时、您处于单步执行模式。 每次按 F6时、CPU 都会运行一些代码、然后停止。 CPU 可以暂停数小时、直到再次按 F6。 与自由运行模式下的 CPU 相比、这将是一个不同的运行环境、在该模式下、可能会发生中断、从而发生更多的上下文切换。 上下文切换将涉及将上下文推送/保存到将使用额外堆栈内存的堆栈。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    我理解差异-但我的案例会抵消此逻辑。
    根据您的解释、我们可以得出结论、自由运行代码对 CPU 的要求要高得多、我同意。
    这就是为什么我希望在自由运行时会出现更多错误的原因...

    但这不是我的情况-在我的情况下、自由运行代码不会导致使用 F6时出现错误。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    [引用 user="shai kon"]但这不是我的情况-在我的情况下、自由运行代码不会导致错误、而使用 F6则会导致错误。我认为代码需要处理中断才能运行。

    默认的 CCS 行为是在步进时禁用中断、但在自由运行时不禁用中断。 这可能会导致单步执行代码、这需要中断"挂起"。

    如果取消勾选"Disable interrupt while source Steping"(在源步进时禁用中断)选项(请参阅 "Program/Memory Load Options")、是否允许代码在源步进时运行?

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    谢谢!
    我取消选中了它、它现在在源步进时起作用。
    在调试时是否有理由禁用中断?
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    [引用 user="shai kon"]是否有充分的理由在调试时禁用中断?[/quot]如果您有启用的中断(例如计时器)、那么当尝试使用启用的中断单步执行时、您可以发现程序会继续进入中断处理程序(请参阅 Compiler/MSP430G2955中的来自 Britta 的答复: 步进调试时、GIE 被自动禁用 -而被引用的线程用于 MSP430器件、而对于基于 Cortex-M4的 Tiva 器件、此线程也是如此)。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    以下员额是这一员额的延续:
    e2e.ti.com/.../2741848

    请分享您的意见。