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.

[参考译文] 为什么 MDR (I2C 主机内核)寄存器不更新??

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

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/938284/why-is-mdr-i2c-master-core-register-is-not-updating

器件型号:TM4C1294NCPDT

我正在尝试以下 I2C 驱动程序是代码。 ()我使用的代码来自(软件开发套件\TM4C1294XL 固件开发包\examples\peripherals\i2c)。

在这里、通过使用      I2CMasterDataPut (I2C0_BASE、pui32DataTx[ui32Index]); 我尝试将数据写入 MDR (I2C 内核)寄存器、但该值不会被写入相同的值!! 这就是我 也无法从从器件接收到的数据 ACK 的原因。

是否有人可以向我推荐该解决方案?

//
//
//// master_slave_loopback.c -演示简单 I2C 消息的示例
// 传输和接收。
//
//版权所有(c) 2010-2020 Texas Instruments Incorporated。 保留所有权利。
//软件许可协议
//
以源代码和二进制形式重新分发和使用,无论是否
进行//修改,只要
满足以下条件//:
//
重新分发源代码必须保留上述版权
//声明、此条件列表和以下免责声明。
//
//二进制形式的再发行必须复制上述版权
//声明、此条件列表和//

分发随附的//文档和/或其他材料中的以下免责声明。
////
未经

事先书面许可,不能使用德州仪器公司的名称或//其贡献者的名称来认可或推广源自此软件的产品//。
////
本软件由版权所有者和贡献者提供
//“按原样”,不

承认任何明示或暗示的保证,包括但不限于//适销性和对//特定用途适用性的暗示保证。 在任何情况下、版权
//所有者或贡献者都不对任何直接、间接、偶然、
//特殊、模范、 或相应的损害(包括但不
限于采购替代产品或服务;丧失使用、
//数据或利润; 或业务中断)、无论

出于何种原因使用
本软件(即使被告知可能会造成此类损坏)、还是出于任何原因而产生的任何//责任理论(无论是合同、严格责任还是侵权行为)//(包括疏忽或其他)。
//
//这是 Tiva 固件开发包2.2.0.295修订版的一部分。
////
*****************

#include 
#include 
#include "inc/hw_i2c.h"
#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "driverlib/gpio.h"
#include "driverlib/i2c.h"
#include "driverlib/pin_map.h"
#include "driverlib/sysctio.uarth"
#include "UART"



//
//! \addtogroup i2c_examples_list
//! 

I2C 主设备环回(i2c_master_slave_loopback)

//! //! 此示例说明了如何将 I2C0模块配置为环回模式。 //! 这包括设置主模块和从模块。 回送模式 //! 在内部将主从数据线和时钟线连接在一起。 //! 设置从机模块的地址、以便从 //! 主器件。 然后检查数据以确保接收到的数据与 //! 传输的数据。 此示例使用//的轮询方法 ! 发送和接收数据。 //! //! 此示例使用以下外设和 I/O 信号。 您必须 //! 查看这些内容并根据您自己的董事会需要进行更改: //! - I2C0外设 //! - GPIO 端口 B 外设(用于 I2C0引脚) //! - I2C0SCL - PB2 //! - I2C0SDA - PB3 //! //! 以下 UART 信号仅配置为显示控制台 //! 消息。 I2C 操作不需要这些。 //! - UART0外设 //! - GPIO 端口 A 外设(用于 UART0引脚) //! - UART0RX - PA0 //! - UART0TX - PA1 //! //! 此示例使用以下中断处理程序。 要使用此示例 //! 在您自己的应用程序中、您必须将这些中断处理程序添加到 您的//! 矢量表。 //! -无。 //// ***************** // // //要发送的 I2C 数据包数量。 //// ***************** #define NUM_I2C_DATA 3 //********* // //设置从机模块的地址。 这是以 //以下格式发送的7位地址: // [A6:A5:A4:A3:A2:A1:A0:RS] // 第一个字节的"RS"位置为零表示主 设备//向所选的从设备发送(发送)数据,而在该位置为1 表示主设备从设备接收数据。 //// ***************** #define SLAVE_ADDRESS 0x3C //********* // //此函数将 UART0设置为用于控制台,以便 在示例运行时显示信息//。 //// ***************** void InitConsole (void) { // //启用用于 UART0引脚的 GPIO 端口 A。 // TODO:将其更改为您正在使用的 GPIO 端口。 // SysCtlPeripheralEnable (SYSCTL_Periph_GPIOA); // //为端口 A0和 A1上的 UART0功能配置引脚复用。 //如果您的器件不支持引脚复用、则无需执行此步骤。 // TODO:更改此选项以选择您正在使用的端口/引脚。 // GPIOPinConfigure (GPIO_PA0_U0RX); GPIOPinConfigure (GPIO_PA1_U0TX); // //启用 UART0以便我们可以配置时钟。 // SysCtlPeripheralEnable (SYSCTL_Periph_UART0); // //使用内部16MHz 振荡器作为 UART 时钟源。 // UARTClockSourceSet (UART0_BASE、UART_CLOCK_PIOSC); // //为这些引脚选择替代(UART)功能。 // TODO:更改此选项以选择您正在使用的端口/引脚。 // GPIOPinTypeUART (GPIO_Porta_base、GPIO_PIN_0 | GPIO_PIN_1); // //初始化控制台 I/O 的 UART // UARTStdioConfig (0、115200、16000000); } //********* // //配置 I2C0主机和从机,并使用环回模式连接它们。 //// ***************** int main (void) { #if defined (target_IS_TM4C129_RA0)|| \ 已定义(TARGET_IS_TM4C129_RA1)|| \ 已定义(TARGET_IS_TM4C129_RA2) uint32_t ui32SysClock; #endif uint32_t pui32DataTx[NUM_I2C_DATA]; uint32_t pui32DataRx[NUM_I2C_DATA]; uint32_t ui32Index; // //将时钟设置为直接从外部晶振/振荡器运行。 // TODO:必须更改 SYSCTL_XTAL_VALUE 以匹配的值 板上的//晶体。 // #if defined (target_IS_TM4C129_RA0)|| \ 已定义(TARGET_IS_TM4C129_RA1)|| \ 已定义(TARGET_IS_TM4C129_RA2) ui32SysClock = SysCtlClockFreqSet ((SYSCTL_XTAL_25MHz | SYSCTL_OSC_MAIN | SYSCTL_USE_OSC)、25000000); #else SysCtlClockSet (SYSCTL_SYSDIV_1 | SYSCTL_USE_OSC | SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHz); #endif // //使用前必须启用 I2C0外设。 // SysCtlPeripheralEnable (SYSCTL_Periph_I2C0); // //对于本示例,I2C0与 PortB[3:2]一起使用。 实际端口和 //使用的引脚可能与您的器件不同、请参阅的数据表 //更多信息。 GPIO 端口 B 需要启用、因此这些引脚可以 //使用。 // TODO:将其更改为您正在使用的 GPIO 端口。 // SysCtlPeripheralEnable (SYSCTL_Periph_GPIOB); // //为端口 B2和 B3上的 I2C0功能配置引脚复用。 //如果您的器件不支持引脚复用、则无需执行此步骤。 // TODO:更改此选项以选择您正在使用的端口/引脚。 // GPIOPinConfigure (GPIO_PB2_I2C0SCL); GPIOPinConfigure (GPIO_PB3_I2C0SDA); // //为这些引脚选择 I2C 功能。 此函数也会 //为 I2C 操作配置 GPIO 引脚,将其设置为 //开漏操作,弱上拉。 请参阅数据表 //查看每个引脚分配了哪些功能。 // TODO:更改此选项以选择您正在使用的端口/引脚。 // GPIOPinTypeI2CSCL (GPIO_PORTB_BASE、GPIO_PIN_2); GPIOPinTypeI2C (GPIO_PORTB_BASE、GPIO_PIN_3); // //启用环回模式。 环回模式是一个内置的特性 //可用于调试 I2C 操作。 它在内部连接 I2C //主机和从机终端,这可以有效地让您按发送数据 //主设备并作为从设备接收数据。 //注意:对于外部 I2C 操作,您需要使用外部上拉电阻 //比内部上拉电阻器强。 请参阅的数据表 //更多信息。 // I2CLoopbackEnable (I2C0_BASE); // //启用和初始化 I2C0主机模块。 使用的系统时钟 // I2C0模块。 最后一个参数设置 I2C 数据传输速率。 //如果为 false,则数据速率设置为100kbps,如果为 true,则数据速率将设置为 //设置为400kbps。 在本示例中、我们将使用100kbps 的数据速率。 // #if defined (target_IS_TM4C129_RA0)|| \ 已定义(TARGET_IS_TM4C129_RA1)|| \ 已定义(TARGET_IS_TM4C129_RA2) I2CMasterInitExpClk (I2C0_BASE、ui32SysClock、false); #else I2CMasterInitExpClk (I2C0_BASE、SysCtlClockGet ()、false); #endif // //启用 I2C0从机模块。 此模块仅用于测试 //目的。 无需启用它即可正常运行 // I2Cx 主机模块。 // I2CSlaveEnable (I2C0_BASE); // //将从地址设置为 SLAVE_ADDRESS。 在回送模式下、它是一个 //发送到的任意7位数(在上面的宏中设置) // I2CMasterSlaveAddrSet 函数。 // I2CSlaveInit (I2C0_BASE、SLAVE_ADDRESS); // //告诉主模块何时将在总线上放置什么地址 //与从设备通信。 将地址设置为 SLAVE_ADDRESS //(在从机模块中设置)。 接收参数设置为 false //表示 I2C 主设备正在向从设备发起写入操作。 如果 // true、这表示 I2C 主设备正在启动读取 //从器件。 // I2CMasterSlaveAddrSet (I2C0_BASE、SLAVE_ADDRESS、FALSE); // //设置用于显示消息的串行控制台。 这是 //仅用于此示例程序,I2C 操作不需要。 // InitConsole(); // //在控制台上显示示例设置。 // UARTprintf ("I2C 环回示例->"); UARTprintf ("\n 模块= I2C0"); UARTprintf ("\n 模式=单次发送/接收"); UARTprintf ("\n 速率= 100kbps\n"); // //初始化要发送的数据。 // pui32DataTx[0]='I'; pui32DataTx[1]='2'; pui32DataTx[2]="C"; // //初始化接收缓冲区。 // for (ui32Index = 0;ui32Index < NUM_I2C_DATA;ui32Index++) { pui32DataRx[ui32Index]= 0; } // //指示数据的方向。 // UARTprintf ("来自主设备的转环->从设备\n"); // //从主设备向从设备发送3个 I2C 数据表。 // for (ui32Index = 0;ui32Index < NUM_I2C_DATA;ui32Index++) { // //显示 I2C0主机正在传输的数据。 // UARTprintf ("正在发送:'%c'。 。 。 "、pui32DataTx[ui32Index]); // //将要发送的数据放在数据寄存器中 // I2CMasterDataPut (I2C0_BASE、pui32DataTx[ui32Index]); // //开始从主器件发送数据。 自回送起 //模式被启用、主控和受控单元被连接 //允许我们接收我们发送的相同数据。 // I2CMasterControl (I2C0_BASE、I2C_MASTER_CMD_SINGLE_SEND); // //等待从机接收并确认数据。 // while (!(I2CSlaveStatus (I2C0_BASE)& I2C_SLAVE_ACT_RREQ)) { } // //从从从器件读取数据。 // pui32DataRx[ui32Index]= I2CSlaveDataGet (I2C0_BASE); // //等待主机模块完成传输。 // while (I2CMasterBusy (I2C0_BASE)) { } // //显示从机已接收到的数据。 // UARTprintf ("已接收:'%c'\n"、pui32DataRx[ui32Index]); } // //重置接收缓冲区。 // for (ui32Index = 0;ui32Index < NUM_I2C_DATA;ui32Index++) { pui32DataRx[ui32Index]= 0; } // //指示数据的方向。 // UARTprintf ("\n\n"从从属设备->主设备进行转接来电"); // //将数据方向修改为 true,以便查看地址 //表示 I2C 主设备正在从设备发起读取。 // I2CMasterSlaveAddrSet (I2C0_BASE、SLAVE_ADDRESS、TRUE); // //进行虚拟接收以确保您在第一次接收时不会收到垃圾。 // I2CMasterControl (I2C0_BASE、I2C_MASTER_CMD_SINGLE_Receive); // //虚拟确认并等待主控方发出的接收请求。 //这样做是为了清除不应设置的任何标志。 // while (!(I2CSlaveStatus (I2C0_BASE)& I2C_SLAVE_ACT_TREQ)) { } for (ui32Index = 0;ui32Index < NUM_I2C_DATA;ui32Index++) { // //显示 I2C0从机模块正在传输的数据。 // UARTprintf ("正在发送:'%c'。 。 。 "、pui32DataTx[ui32Index]); // //将要发送的数据放在数据寄存器中 // I2CSlaveDataPut (I2C0_BASE、pui32DataTx[ui32Index]); // //告诉主设备读取数据。 // I2CMasterControl (I2C0_BASE、I2C_MASTER_CMD_SINGLE_Receive); // //等待从机完成发送数据。 // while (!(I2CSlaveStatus (I2C0_BASE)& I2C_SLAVE_ACT_TREQ)) { } // //从主设备读取数据。 // pui32DataRx[ui32Index]= I2CMasterDataGet (I2C0_BASE); // //显示从机已接收到的数据。 // UARTprintf ("已接收:'%c'\n"、pui32DataRx[ui32Index]); } // //告诉用户测试已完成。 // UARTprintf ("\nDone.\n\n"); // //返回无错误 // 返回(0); }

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

    您好!

     我只运行该示例、我对它没有任何问题。 请参见下面的。 我还在连接 CCS 项目。  

    e2e.ti.com/.../8080.i2c_5F00_master_5F00_slave_5F00_loopback.zip

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

    你(们)好,查尔斯

    您是否已禁用回路模式?  根据 TM4C1294NCPDT 数据表中针对主器件到从器件通信给出的流程图、可以清楚地看到、在将从器件地址写入 I2CMSA 之后、下一步是将数据写入 I2CMDR 寄存器、这意味着根据 SI7021数据表向 I2CMDR 寄存器发出温度命令。 但是、当我在调试期间检查它们是否正在更新时、我发现 MDR 寄存器未更新、这就是我在论坛上提出此问题的原因。 您能不能帮助我了解为何 MDR 不更新。

    此外、我要附加我的 CCS 项目 zip 文件。

    此致

    Omkar

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

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

    您好!

     我还可以看到、当我运行 TivaWare 示例时、MDR 为零。 我想原因是 MDR 寄存器是 TX 和 RX FIFO 的地址。 您可以使用 MDR 寄存器写入 TXFIFO。 您还可以使用相同的 MDR 寄存器从 RXFIFO 读取数据。 当您写入 MDR 寄存器时、它会将数据管道化到 TXFIFO 中。 它并不能真正反映写入的值。 但是、如果您查看示波器或逻辑分析仪、您将看到数据移出。 另请注意、在您调用 I2CMasterControl 之前、数据不会移出。 您是否未看到数据移出?

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

    您好、Charles、

    好的、谢谢最后有人告诉我、我正在互联网上的任何地方搜索这个东西。 在本例中

            I2CMasterDataPut(I2C0_BASE, pui32DataTx[ui32Index]);
            //
            // Initiate send of data from the master.  Since the loopback
            // mode is enabled, the master and slave units are connected
            // allowing us to receive the same data that we sent out.
            //
            I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_SINGLE_SEND);
            //
            // Wait until the slave has received and acknowledged the data.
            //
            while(!(I2CSlaveStatus(I2C0_BASE) & I2C_SLAVE_ACT_RREQ))
            {
            }
    如果您在调试过程中看到上述代码、则其会卡在 while 循环中、这意味着在我的情况下、从器件发送地址后不会将 ACK 发送回主器件。 会出现什么误差。 请帮帮我。
    此致、
    Omkar
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您正在运行哪个程序? 您是否像我之前发送的那样运行 i2c_master_slave_loopback? 您显示的代码适用于启用内部回送模式的 TivaWare 示例。 那么、请告诉我您是在运行环回项目、还是有一些外部 I2C 从器件连接到您的电路板。  

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

    是的、我正在使用相同的代码、但我禁用了环回模式。 我还使用外部从器件、即温度传感器 s7021。 我检查了从器件的地址、即0x40、这与我在代码中使用的地址相同、但从器件仍然不发送回 ACK。 我认为从器件必须将 SDA 线路下拉、但情况并非如此。 我说  

    "检查= I2CSlaveStatus (I2C0_BASE);"

    从器件发送地址以查看 I2CSLaveStatus 发送回什么、但在这里、作为返回、我也得到0。 不从从从器件获取 ACK 的可能性是什么?

    此致、

    Omkar

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

    您好!

     回送模式是否是您唯一要删除的内容?

     SCL 和 SDA 总线上是否有上拉电阻器? 如果您没有上拉电阻器、则它将不起作用。 如果您已经有上拉电阻器并且没有从器件看到 ACK、那么调试的最佳方法是使用示波器或逻辑分析仪。  

     我不熟悉 si7021传感器、我认为您无法使用环回示例(禁用环回模式)与传感器进行连接。 您需要检查 si7021传感器的命令协议。 回送示例是与自身进行通信。 没有可遵循的协议。 使用真实的传感器、您可能需要发送命令字节或其他寄存器地址字节、然后才能读取/写入 I2C 器件。 您需要自己对此进行处理。  

     您可以参考另一个示例。 它连接到外部湿度传感器。  

    C:\ti\TivaWare_C_Series-2.2.0.295\examples\boards\ek-tm4c1294xl-bootstxl-senshub\humid_sh21_simple

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

    您好!

    最终解决了问题。 我将 "humidy_sh21_sample"与我的代码进行了比较、它对我来说很有用。 非常感谢您的建议。

    此致、

    Omkar