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.

[参考译文] TM4C129XNCZAD:I2C 主机发送多个数据字节问题

Guru**** 2425930 points


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

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/677860/tm4c129xnczad-i2c-master-transmit-of-multiple-data-bytes-issue

器件型号:TM4C129XNCZAD

您好!

我正在尝试按照数据表中给出的流程图从 I2C 向外传输4个字节。 但是、我只能看到0x34和0x78从示波器发出、而另外2个字节在空中丢失。 下面是供参考的代码和流程图。 我需要再用两双眼睛来查看 我在代码中遗漏的内容。 谢谢。

我的代码:

int main (空)

//启用 I2C 和 GPIO 端口 A 的时钟
*((uint32_t *)(SYSCTL_RCGCI2C))|=(0x01 <<9);
*((uint32_t *)(SYSCTL_RCGCGPIO))|=(0x00001 << 0);

//等待 SSI 接口和 GPIO 端口 A 外设就绪
while (!(*(uint32_t *)(SYSCTL_PRI2C)&(0x001 << 9)));
while (!(*(uint32_t *)(SYSCTL_PRGPIO)&(0x00001 << 0)));

//将 GPIO 备用功能配置为 I2C
*(((uint32_t *)(GPIO_PORta_AHB + GPIO_AFSEL))|=(0x03 << 0);
*((uint32_t *)(GPIO_Porta_AHB + GPIO_O_ODR))|=(0x01 << 1);
*(((uint32_t *)(GPIO_PORta_AHB + GPIO_PCTL))=(0x2 << 4 | 0x2 << 0);
*(((uint32_t *)(GPIO_PORta_AHB + GPIO_DEN))|=(0x03 << 0);

//将时钟源配置为使用 PIOSC
*((uint32_t *)(SYSCTL_PLLFREQ0))|=(0x1 << 23);
while (!(*(uint32_t *)(SYSCTL_PLLSTAT)));
*((uint32_t *)(SYSCTL_PLLFREQ0)))&=~(0x1 <<23);

//将 I2C 配置为主模式
*((uint32_t *)(I2C9 + I2C_O_MCR))|=(0x1 << 4);

//将 SCL 时钟速度配置为100kHz
*((uint32_t *)(I2C9 + I2C_O_MTPR))= 0x08;

//配置从机地址并在发送模式下运行
*((uint32_t *)(I2C9 + I2C_O_MSA))=(0x76 << 1 | 0x0 << 0);

//等待总线空闲
while (*(uint32_t *)(I2C9 + I2C_O_MCS)和0x00000001);
while (*(uint32_t *)(I2C9 + I2C_O_MCS)和0x00000040);

//发送1个字节的数据
*((uint32_t *)(I2C9 + I2C_O_MDR))= 0x12;

//启动1字节传输
*((uint32_t *)(I2C9 + I2C_O_MCS)= 0x03;

//等待 I2C 空闲且无错误
while (*(uint32_t *)(I2C9 + I2C_O_MCS)和0x00000001);
while (*(uint32_t *)(I2C9 + I2C_O_MCS)和0x00000002);

//发送1个字节的数据
*((uint32_t *)(I2C9 + I2C_O_MDR)= 0x34;

//启动1字节传输
*((uint32_t *)(I2C9 + I2C_O_MCS)= 0x01;

//等待 I2C 空闲且无错误
while (*(uint32_t *)(I2C9 + I2C_O_MCS)和0x00000001);
while (*(uint32_t *)(I2C9 + I2C_O_MCS)和0x00000002);

//发送1个字节的数据
*(((uint32_t *)(I2C9 + I2C_O_MDR))= 0x56;

//启动1字节传输
*((uint32_t *)(I2C9 + I2C_O_MCS)= 0x01;

//等待 I2C 空闲且无错误
while (*(uint32_t *)(I2C9 + I2C_O_MCS)和0x00000001);
while (*(uint32_t *)(I2C9 + I2C_O_MCS)和0x00000002);

//发送1个字节的数据
*((uint32_t *)(I2C9 + I2C_O_MDR)= 0x78;

//启动1字节传输
*((uint32_t *)(I2C9 + I2C_O_MCS)= 0x05;

//等待 I2C 空闲且无错误
while (*(uint32_t *)(I2C9 + I2C_O_MCS)和0x00000001);
while (*(uint32_t *)(I2C9 + I2C_O_MCS)和0x00000002);

while (1);

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

    请允许我注意、您的发帖揭示了许多关怀和技能-但这是 (大多数)供应商代理的"偏好"-我们会考虑(有时)帮助者。   这证明了这一点、因为您只使用了"直接寄存器操作"(DRM)代码样式-该代码样式要求 MCU 手册为"准备就绪"- 引入了很多复杂度-同时增加了(两者)帮助者的"时间和精力"负担。

    使用供应商"API"是(非常)的首选-尤其是在 "速度、易用性和增强"的最全面 MCU 代码开发中、这一点得到了充分的注意。   API 经过长期 的"测试、验证-同时提供"代码效率"-数量级超过"DRM 或 ASM"。   您最好考虑切换到 API。

    • 您会注意到、"two bytes"从 I2C 外设中发出-而另外2个字节丢失。   这本身看起来很奇怪、但如果您注意到每个发往 I2C 输出的字节是否都看到了其"完整且正确"的代码执行、那么诊断工作是否会有所帮助?    
    • "早期的 I2C 字节传输"是否可能具有 "无法生成从器件的"ACK"、这证明了"丢失 I2C 输出"的原因?
    • 如果您更改两个"成功字节"的"字节序列中的位置"、会产生什么结果?   (0x34和0x78)  我们"在这里测试"是否存在任何 "位置依赖性"。
    • 如果您将这些(过去)后续字节的数据值(0x34/0x78)更改为这些(其他、失败)值、会产生什么结果?   (0x12和0x56)

    请注意、您的一个代码块不同于"所有其他代码块"。   这是故意的吗?

    //等待总线空闲
    while (*(uint32_t *)(I2C9 + I2C_O_MCS)和0x00000001);
    while (*(uint32_t *)(I2C9 + I2C_O_MCS)和0x00000040);

    所有(相似)代码块(大多数代码块)显示为:

    //等待 I2C 空闲且无错误
    while (*(uint32_t *)(I2C9 + I2C_O_MCS)和0x00000001);
    while (*(uint32_t *)(I2C9 + I2C_O_MCS)和0x00000002);

    我对这一问题抱有"高希望"、因为您的"问题"-但是、当涉及"多数"代码块时、"后续字节"都产生了。

    我自己/他人说 、"永远不会对 MCU 内部上拉电阻器的有效性产生疑问"-仅当(这些)使用 I2C 总线进行部署时。   外部10K 电阻器-已证明比以前强大得多...

    我们相信、您 的"采用供应商的 API"-丰富的 I2C 代码示例-将使供应商代理和我们的"外部人员"提供最佳支持。

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

    这是因为我的工作性质需要了解直接寄存器操作。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    大家好、上一页、

    当"理解是以过时的、充满错误的方法为前提"时、你会感到哀悼、而(经证明卓越的)方法是"绕过了!"   我们可以注意到、(所称)理解-源于 DRM -在这里失败了(正如它所具有的那样-很多其他人!)

    您可能会注意到(并可能转发给您的讲师或上司)、"使用 API -绝不会排除您的、"深入检查所有密钥/关键 MCU 寄存器!"   这是" DRM 支持者"通常提出的"错误选择"、他们竭力逃避经过测试和验证的 API 明显的"速度、易用性和效率"。   (没有任何 DRM 代码经过如此程度的测试和测试、因此 DRM 的使用始终存在风险!)    "复杂性"-仅为了"复杂性"是否有意义?

    代表您介绍了多个故障排除元素(不需要您从 DRM "移动")-您是否打算采用(任何)这些元素?    (您的写作-提供了"无线索"。)

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您好!
    CB1提供了许多建议和调试提示。 为什么在发送0x12后不停止 I2C 传输? 如果您不执行接下来的三个字、您是否可以得到0x12来工作?
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    Good Charles -又一次-"强迫使用"这种"过于苛刻的方法"-未能达到海报目标!

    与往常一样、"增强理解"的(不可支持的)诉求被提出、作为海报时间和工作量(大幅)增加的理由、而这是由低效的"DRM"引起的。  

    是否应该出现"强化学习"-海报不会"快速、轻松"成功-从而避免他们(无尽)来到这里?

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

    您好!

    你(们)好 它适用于1字节传输。 下面是我使用的代码。

    int main (空)

    uint32_t ui32RxData[2]={0x00、0x00};

    //启用 I2C 和 GPIO 端口 A 的时钟
    //等待 SSI 接口和 GPIO 端口 A 外设就绪
    *((uint32_t *)(SYSCTL_RCGCI2C))|=(0x01 <<9);
    *((uint32_t *)(SYSCTL_RCGCGPIO))|=(0x00001 << 0);
    while (!(*(uint32_t *)(SYSCTL_PRI2C)&(0x001 << 9)));
    while (!(*(uint32_t *)(SYSCTL_PRGPIO)&(0x00001 << 0)));

    //将 GPIO 备用功能配置为 I2C
    *(((uint32_t *)(GPIO_PORta_AHB + GPIO_AFSEL))|=(0x03 << 0);
    *((uint32_t *)(GPIO_Porta_AHB + GPIO_O_ODR))|=(0x01 << 1);
    *(((uint32_t *)(GPIO_PORta_AHB + GPIO_PCTL))=(0x2 << 4 | 0x2 << 0);
    *(((uint32_t *)(GPIO_PORta_AHB + GPIO_DEN))|=(0x03 << 0);

    //将 I2C 配置为主模式
    *((uint32_t *)(I2C9 + I2C_O_MCR))|=(0x1 << 4);

    //将 SCL 时钟速度配置为100kHz
    *((uint32_t *)(I2C9 + I2C_O_MTPR))= 0x07;

    //配置从机地址并以写模式运行
    *((uint32_t *)(I2C9 + I2C_O_MSA))=(0x76 << 1 | 0x0 << 0);

    //发送1个字节的数据
    *((uint32_t *)(I2C9 + I2C_O_MDR))= 0x12;

    //等待总线空闲
    while (*(uint32_t *)(I2C9 + I2C_O_MCS)和0x00000040);

    //启动1字节传输
    *((uint32_t *)(I2C9 + I2C_O_MCS)= 0x07;

    while (*(uint32_t *)(I2C9 + I2C_O_MCS)和0x00000001);
    while (*(uint32_t *)(I2C9 + I2C_O_MCS)和0x00000002);

    while (1);

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

    实际上、它在我执行了检查中断而不是按照流程图中所示检查状态寄存器之后能够很好地工作。 我想知道流程图实施是否真的有效。 或许 TI 工程师可以帮助验证这一点。 下面是工作代码。

    int main (空)

    uint32_t ui32RxData[2]={0x00、0x00};

    //启用 I2C 和 GPIO 端口 A 的时钟
    //等待 SSI 接口和 GPIO 端口 A 外设就绪
    *((uint32_t *)(SYSCTL_RCGCI2C)) =(0x01 << 9);
    *((uint32_t *)(SYSCTL_RCGCGPIO)) =(0x00001 << 0);
    while (!(*(uint32_t *)(SYSCTL_PRI2C)&(0x001 << 9)));
    while (!(*(uint32_t *)(SYSCTL_PRGPIO)&(0x00001 << 0)));

    //将 GPIO 备用功能配置为 I2C
    *(((uint32_t *)(GPIO_PORta_AHB + GPIO_AFSEL))|=(0x03 << 0);
    *((uint32_t *)(GPIO_Porta_AHB + GPIO_O_ODR))|=(0x01 << 1);
    *(((uint32_t *)(GPIO_PORta_AHB + GPIO_PCTL))=(0x2 << 4 | 0x2 << 0);
    *(((uint32_t *)(GPIO_PORta_AHB + GPIO_DEN))|=(0x03 << 0);

    //将 I2C 配置为主模式
    *((uint32_t *)(I2C9 + I2C_O_MCR) =(0x1 << 4);

    //将 SCL 时钟速度配置为100kHz
    *((uint32_t *)(I2C9 + I2C_O_MTPR)) = 0x07;

    //配置从机地址并以写模式运行
    *((uint32_t *)(I2C9 + I2C_O_MSA) =(0x76 << 1 | 0x0 << 0);

    //发送1个字节的数据
    *((uint32_t *)(I2C9 + I2C_O_MDR) = 0x12;

    //等待总线空闲
    while (*(uint32_t *)(I2C9 + I2C_O_MCS)和0x00000040);

    //启动1字节传输
    *((uint32_t *)(I2C9 + I2C_O_MCS) = 0x03;

    while (!(*(uint32_t *)(I2C9 + I2C_O_MRI))& 0x00000001);
    *((uint32_t *)(I2C9 + I2C_O_MICR) |= 0x1;

    //发送1个字节的数据
    *((uint32_t *)(I2C9 + I2C_O_MDR) = 0x34;

    //启动1字节传输
    *((uint32_t *)(I2C9 + I2C_O_MCS) = 0x01;

    while (!(*(uint32_t *)(I2C9 + I2C_O_MRI))& 0x00000001);
    *((uint32_t *)(I2C9 + I2C_O_MICR) |= 0x1;

    //发送1个字节的数据
    *((uint32_t *)(I2C9 + I2C_O_MDR) = 0x56;

    //启动1字节传输
    *((uint32_t *)(I2C9 + I2C_O_MCS) = 0x01;

    while (!(*(uint32_t *)(I2C9 + I2C_O_MRI))& 0x00000001);
    *((uint32_t *)(I2C9 + I2C_O_MICR) |= 0x1;

    //发送1个字节的数据
    *((uint32_t *)(I2C9 + I2C_O_MDR) = 0x78;

    //启动1字节传输
    *((uint32_t *)(I2C9 + I2C_O_MCS) = 0x05;

    while (!(*(uint32_t *)(I2C9 + I2C_O_MRI))& 0x00000001);
    *((uint32_t *)(I2C9 + I2C_O_MICR) |= 0x1;

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

    您好!

     很高兴您使用中断解决了问题、这是针对以下勘误表建议的解决方法。