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.

[参考译文] CCS/TM4C1294KCPDT:I2C 发送错误的从器件地址

Guru**** 2560390 points
Other Parts Discussed in Thread: TM4C1294KCPDT, EK-TM4C1294XL

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

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/783269/ccs-tm4c1294kcpdt-i2c-send-wrong-slave-address

器件型号:TM4C1294KCPDT
Thread 中讨论的其他器件: EK-TM4C1294XL

工具/软件:Code Composer Studio

大家好、

我正在尝试 TM4C1294KCPDT 的 I2C0为12位 DAC (Microchip 的 MSP4725评估板)发送数据、以熟悉微控制器硬件接口。

设置为:

I2C:SCL-->PortB PIN2

SDA-->端口 B 引脚3

速度为100kbps 或400kbps

 

从器件(MSP4725)地址为0xC0。

VDD:3.3V

 

我可以在示波器上看到 I2C 发送地址0x80而不是0xC0、这会导致通信停止、因为未选择从器件。

我使用 PICkit 串行分析器试用了 MSP4725评估板、该评估板按预期工作、因为我可以根据需要更改 DAC 输出的电压。

在 TM4C1294的 I2C 中、似乎存在故障。

 

PICkit 串行分析器: https://www.microchip.com/Developmenttools/ProductDetails/DV164122:

MSP4725评估板: http://ww1.microchip.com/downloads/en/devicedoc/51669a.pdf

 

I2C 不起作用让我有点惊讶。 有人可以帮帮我吗?

 下面是一个简单的示例:

 

//
////
main()//

*********
int
main (void)
{

static uint32_t ui32SysClkFreq、u32GetClkFreq
= SysCtlClockFreqSet ((SYSCTL_XTAL_25MHz |
SYSC_MAIN | SYSC1200TL_USE_PLL | SysCtl_VCO_GPIOPTL





)







;SYSCB2_Periptl (SYSC0_IPB2_0_RESETH);SYSC0_IPB0 (SYSCB0_IPPEPTL)(SYSC0_IPB0_IP_IP_IPB0);SYSCB0_IP_IP_IPPECTL (SYSC0_IPPEPTL_0_IPPEPTH) //为 LED 启用端口 N 以进行调试

//配置 SDA o PORTB PIN3
GPIOPinConfigure (GPIO_PB3_I2C0SDA);
GPIOPINTypeI2C (GPIO_PORTB_BASE、GPIO_PIN_3);

//配置 SCL o PORTB PIN2 GPIOP2_BASE
(GPIOP2C0_PHASE



);//将 GPIOPT0_GPIOPT0_PIN_INTS0



和 GPIOPT0_GPIOPT0_PIN_GPIO0/ GPIO0_GPIO0_GPIO0_GPIO0_GPIO0_GPIO0_GPIO0_GPIO0_GPIO0_GPIO0_GPIOPT_GPIO0_GPIOPT_GPIO0_GPIOPT_PHASE;//将 GPIO0_GPIO0_GPIO0_GPIO0_GPIO0_GPIO0_GPIO0_GPIO0_GPIO0_GPIO0_GPIO0_GPIO0_GPIO0_GPIOPT_GPIO0_GPIOPT_GPIO0_GPIO0_GPIO0_GPIO
// a120Mhz

while (I2CMasterBusy (I2C0_BASE));

I2CMasterSlaveAddrSet (I2C0_BASE、0xC0、false);设置从地址 I2CMasterBusy (

I2C0_BASE、I2C_MASTER、I2CMD_



SIMP_SIMP_0



)


;I2CM0_I2CM0_SIaster0_I2CM0_SIBT_SIMP_SIMP_SION_SIMP_SIMP_SIMP_SION_SIMP_SIMP_SIMP_SIMP_SIMP_SIMP_SION_SIMP_SIMP_SIMP_SION_SIMP_SIMP_SIMP_SION_SIMP_SIMP_SION_SION_SIMP_SION_SIMP_SION_SION_SION_SIMPIST/ I2CM0_SIST_SIMP_SIMP_SIMP_SIMP_SIMP_SIMP_SIMP_SIMP_SIMP_SIMP_SIMP_SIMP_SIMP



3);

while (1)
{
SysCtlDelay (ui32SysClkFreq /(3 * 5));
GPIOPinWrite (GPIO_PORTN_BASE、GPIO_PIN_0、1);
SysDelay (ui32SysClkFreq /(3 * 5)));
GPIOPinWrite (GPIO_PORTN_BASE
)
;0}SysPIN_BASE、GPIO 

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

     连接:

    TM4C1294                        MCP4725评估板

    Pb3.                         SDA

    PB2.                        SCL

    GND                       GND

    3.3V                        VDD

     

    示波器图例:蓝色 SCL

    红色:SDA

     

     


     

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

    请交换 DataPut 和 Control 调用、以便 DataPut 在 Control 调用之前、因为 Control 调用会触发要发送的数据、因此如果 DataPut 在之后使用、则实际上不会为该传输加载数据。 查看是否设置了正确的序列、然后还允许正确输出从地址、我认为在尚未提供数据时、I2C 驱动器可能会因您尝试发送数据而变得有点混乱。

    此外、您可能会发现此 I2C 文档对您使用 I2C 模块非常有用: www.ti.com/.../spma073.pdf
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、Ralph、感谢您的回复。

    "请交换 DataPut 和 Control 调用、以便 DataPut 在 Control 调用之前"  

    我已经尝试过、但它 不起作用。

    我 认为问题是上拉电阻器。 DAC 评估板使用5K 上拉电阻器、我认为它会产生类似波形的 SAW。 考虑到 TM4C1294由3.3V 电源供电、这可能就像开路。  Microchip PICkit 串行分析器可用于试用 DAC 评估板。 我尝试了5V 和3.3V、两次都正常工作

    我想尝试较低的值、看看这是否能解决问题。

     

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

    一次更新!

    我将上拉电阻器减小到1K 并再次尝试、但仍然得到相同的结果;从器件地址为0xC0、I2C0发送0x7F。 我还尝试了 I2C2 (端口 N (4:5))、但又不幸运了。

    我对故障感到乐观、但现在我开始对微控制器 I2C 引擎本身产生怀疑。 由于  I2CMasterSlaveAddrSet (I2C0_BASE、0xC0、false)中设置了从器件地址、因此未发送正确的从器件地址。  

    我再次尝试 使用原始 Microchip PICkit 串行分析器、它按预期工作。

    I2C 是否首先适用于 TM4C129x 微控制器?我是否缺少什么?

    此致、

    使用 Microchip PICkit 串行分析器尝试时的 I2C 结果  

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

    I2C 正常工作、您提供的代码对我来说看起来不错。 周一我回到办公室时、我将尝试运行该代码、并查看是否可以在我自己的 EK-TM4C1294XL LaunchPad 上重现此问题。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    我拉尔夫、感谢您对这个主题的关注。

    "I2C 工作正常":出于"绝望"、我一开始有疑问、但在内部、I2C 无法正常工作、至少硬件无法正常工作。  

    "我在星期一回到办公室、我将尝试运行该代码":请尝试以下代码吗?

    我查看了从寄存器 I2C_MCA_SA、它包含0x80而不是0xC0。 值0x80也显示了示波器屏幕截图。 API  I2CMasterSlaveAddrSet (I2C0_BASE、0xC0、false)可能会导致所有此问题。 再说一次、这是写入操作、但它显示了一个接收操作。

    我将尝试将从器件地址直接写入寄存器 I2C_MCA_SA、看看发生了什么情况?

    代码:

     

    //
    //
    // main()
    //
    //
    内部
    main (空)
       静态 uint32_t ui32SysClkFreq、u32GetClock;
       ui32SysClkFreq = SysCtlClockFreqSet ((SYSCTL_XTAL_25MHz |
                                              SYSCTL_OSC_MAIN | SYSCTL_USE_PLL |
                                              SYSCTL_CFG_VCO_480)、120000000);
      // u32GetClock=SysCtlClockGet ();
       SysCtlPeripheralEnable (SYSCTL_Periph_I2C0); //启用 I2C0
       while (!SysCtlPeripheralReady (SYSCTL_Periph_I2C0));//等待 I2C0模块准备就绪。

       SysCtlPeripheralReset (SYSCTL_Periph_I2C0); //重置 I2C0
       while (!SysCtlPeripheralReady (SYSCTL_Periph_I2C0));

       SysCtlPeripheralEnable (SYSCTL_Periph_GPIOB); //为 I2C0启用端口 B (PIN_B3和引脚 B2)
       while (!SysCtlPeripheralReady (SYSCTL_Periph_GPIOB));
       SysCtlPeripheralEnable (SYSCTL_Periph_GPION);   //为 LED 启用端口 N
       while (!SysCtlPeripheralReady (SYSCTL_Periph_GPION));//给它建立的时间
       //在 PORTB PIN3上配置 SDA
       GPIOPinConfigure (GPIO_PB3_I2C0SDA);
       GPIOPinTypeI2C (GPIO_PORTB_BASE、GPIO_PIN_3);
       while (!SysCtlPeripheralReady (SYSCTL_Periph_I2C0));//给它稳定的时间
       //配置 SCL o PORTB PIN2
       GPIOPinConfigure (GPIO_PB2_I2C0SCL);
       GPIOPinTypeI2CSCL (GPIO_PORTB_BASE、GPIO_PIN_2);
       while (!SysCtlPeripheralReady (SYSCTL_Periph_I2C0));//给它稳定的时间
       //将 PORTN PIN0和 PIN1配置为调试输出
     GPIOPinTypeGPIOOutput (GPIO_PORTN_BASE、GPIO_PIN_0|GPIO_PIN_1);

     //将 I2C 时钟和速度设置为100Kbps
     I2CMasterInitExpClk (I2C0_BASE、ui32SysClkFreq、false);  //尝试过此操作
    // I2CMasterInitExpClk (I2C0_BASE、SysCtlClockGet ()、false); //和这个
     while (I2CMasterBusy (I2C0_BASE));//给它稳定的时间
     // HWREG (I2C0_BASE_I2C_O_FIFOCTL);
     I2CMasterSlaveAddrSet (I2C0_BASE、0xC0、false); //设置从地址
     SysCtlDelay (ui32SysClkFreq /(3 * 5));//允许初始化趋稳
     I2CMasterDataPut (I2C0_BASE、0x0A); // DAC 的第一个字节
     I2CMasterControl (I2C0_BASE、I2C_MASTER_CMD_BURST_SEND_START);
     while (I2CMasterBusy (I2C0_BASE)); //非忙
     I2CMasterDataPut (I2C0_BASE、0xAA);// DAC 的第2个字节
     I2CMasterControl (I2C0_BASE、I2C_MASTER_CMD_BURST_SEND_FINISH);
     while (I2CMasterBusy (I2C0_BASE)); //非忙
     I2CMasterControl (I2C0_BASE、I2C_MASTER_CMD_BURST_SEND_STOP);
     while (I2CMasterBusy (I2C0_BASE)); //非忙

     GPIOPinWrite (GPIO_PORTN_BASE、GPIO_PIN_0|GPIO_PIN_1、3);

       while (1)
       {
           SysCtlDelay (ui32SysClkFreq /(3 * 5));
           GPIOPinWrite (GPIO_PORTN_BASE、GPIO_PIN_0、1);
           SysCtlDelay (ui32SysClkFreq /(3 * 5));
           GPIOPinWrite (GPIO_PORTN_BASE、GPIO_PIN_0、0);
        }
    调试输出:
     
     

     

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

    只是一次更新。

    我添加 了 I2CMasterSlaveAddrSet (I2C0_base、0xC0、false)注释并将其替换为  HWREG (I2C0_base+0x0000)=0xC0、以便我可以将从地址直接写入 I2CMCA 寄存器。

    我还评论了第149-150行。

    现在、我可以在调试器中看到 I2CMCA 寄存器的地址是0xC0。 此外、DAC 评估板输出正确的编程电压。 我当时尝试了一个值、它按预期工作。 我需要在循环中尝试它、看看。

    到目前为止、API  I2CMasterSlaveAddrSet 似乎正在将错误的从器件地址写入寄存器 I2CMCA。 我不知道这是错误还是其他问题

    我在 CCS 8.3.0下使用的是 TIvAware c_series_2_1_4_178。


     

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

    您好 Rab、

    感谢您发表这篇最新的文章、它让我的想法得到了正确的发展。 当我试图成为一名周末勇士时、我忘记了 I2C 从机寻址如何与 I2CMasterSlaveAddrSet API 一起工作的一些基本知识。 它需要一个7位地址。 如果您在 driverlib 的 i2c.c 中查看 API 详细信息、您将看到它将地址位移1、然后在其末尾附加接收标志。 因此、您将需要像这样使用 API:

    I2CMasterSlaveAddrSet (I2C0_BASE、0x60、false); 

    然后、这将在位移位并将接收位(即0)放置到末尾之后、实际在总线上输出0xC0

    很抱歉、我没有马上记住这一点。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    你(们)好
    感谢您继续发帖、很抱歉影响您的周末。 )
    现在这是有道理的、但我没有想到会是这样。 使用术语"从器件地址"使我朝完全不同的方向前进。
    对于该器件、值0xC0是要写入从器件的从器件地址、值0xC1是要从器件读取或接收数据的从器件地址。 在这两种情况下、第一个 LSB 位指示数据的方向。
    尽管 API 采用用户输入的值、并将7位值分配给 I2CMCA 寄存器、将 LSB 位(0或1)分配给 R/S 位。

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

    您好!

    我的发言似乎太快了。

    当使用 API 开始和结束发送数据的示例2字节时、该问题得到了解决、但如果您希望使用 API CONT 发送数据、例如以2的倍数发送数据、则程序似乎仅发送第一个(开始) 最后一个字节(已完成)并忽略 CONT 语句。 另一方面、如果我按步骤运行程序、即开始、然后检查、然后继续、检查范围、我可以看到 API CONT 正在发送字节。

    我要发送的数据是  

    从器件地址:0xC0 被发送到示波器上  

    第1个字节:0x00在示波器上发送  

    第2个字节:0xAA 在示波器上看不到

    3D 字节:0x0B 在示波器上看不到  

    在 示波器上发送了第4个字节:0x66  

    在我看来、行  I2CMasterControl (I2C0_BASE、I2C_MASTER_CMD_BURST_SEND_CONT)由于未知原因未运行

    请参阅 下面的代码和示波器屏幕截图:

    //
    //
    // main()
    //
    //
    内部
    main (空)
       静态 uint32_t ui32SysClkFreq、u32GetClock;
       ui32SysClkFreq = SysCtlClockFreqSet ((SYSCTL_XTAL_25MHz |
                                              SYSCTL_OSC_MAIN | SYSCTL_USE_PLL |
                                              SYSCTL_CFG_VCO_480)、120000000);
      // u32GetClock=SysCtlClockGet ();
       SysCtlPeripheralEnable (SYSCTL_Periph_I2C0); //启用 I2C0
       while (!SysCtlPeripheralReady (SYSCTL_Periph_I2C0));//等待 I2C0模块准备就绪。

       SysCtlPeripheralReset (SYSCTL_Periph_I2C0); //重置 I2C0
       while (!SysCtlPeripheralReady (SYSCTL_Periph_I2C0));

       SysCtlPeripheralEnable (SYSCTL_Periph_GPIOB); //为 I2C0启用端口 B (PIN_B3和引脚 B2)
       while (!SysCtlPeripheralReady (SYSCTL_Periph_GPIOB));
       SysCtlPeripheralEnable (SYSCTL_Periph_GPION);   //为 LED 启用端口 N
       while (!SysCtlPeripheralReady (SYSCTL_Periph_GPION));//给它建立的时间
       //在 PORTB PIN3上配置 SDA
       GPIOPinConfigure (GPIO_PB3_I2C0SDA);
       GPIOPinTypeI2C (GPIO_PORTB_BASE、GPIO_PIN_3);
       while (!SysCtlPeripheralReady (SYSCTL_Periph_I2C0));//给它稳定的时间
       //配置 SCL o PORTB PIN2
       GPIOPinConfigure (GPIO_PB2_I2C0SCL);
       GPIOPinTypeI2CSCL (GPIO_PORTB_BASE、GPIO_PIN_2);
       while (!SysCtlPeripheralReady (SYSCTL_Periph_I2C0));//给它稳定的时间
       //将 PORTN PIN0和 PIN1配置为调试输出
     GPIOPinTypeGPIOOutput (GPIO_PORTN_BASE、GPIO_PIN_0|GPIO_PIN_1);

     //将 I2C 时钟和速度设置为100Kbps
     I2CMasterInitExpClk (I2C0_BASE、ui32SysClkFreq、false);  //尝试过此操作
    // I2CMasterInitExpClk (I2C0_BASE、SysCtlClockGet ()、false); //和这个
     while (I2CMasterBusy (I2C0_BASE));//给它稳定的时间
      //HWREG (I2C0_BASE_I2C_O_FIFOCTL);
    // I2CMasterSlaveAddrSet (I2C0_BASE、0xC0、false); //设置从地址
     HWREG (I2C0_BASE+0x0000)= 0xC0;
     SysCtlDelay (ui32SysClkFreq /(3 * 5));//允许初始化趋稳
     I2CMasterDataPut (I2C0_BASE、0x00); // DAC 的第一个字节
     I2CMasterControl (I2C0_BASE、I2C_MASTER_CMD_BURST_SEND_START);
     while (I2CMasterBusy (I2C0_BASE)); //非忙
     I2CMasterDataPut (I2C0_BASE、0xAA);// DAC 的第2个字节
     I2CMasterControl (I2C0_BASE、I2C_MASTER_CMD_BURST_SEND_CONT);
     while (I2CMasterBusy (I2C0_BASE)); //非忙
     I2CMasterDataPut (I2C0_BASE、0x0B); // DAC 的第一个字节
     I2CMasterControl (I2C0_BASE、I2C_MASTER_CMD_BURST_SEND_CONT);
     while (I2CMasterBusy (I2C0_BASE)); //非忙

       I2CMasterDataPut (I2C0_BASE、0x66);// DAC 的第二个字节
     I2CMasterControl (I2C0_BASE、I2C_MASTER_CMD_BURST_SEND_FINISH);
     while (I2CMasterBusy (I2C0_BASE)); //非忙
     GPIOPinWrite (GPIO_PORTN_BASE、GPIO_PIN_0|GPIO_PIN_1、3);

       while (1)
       {
           SysCtlDelay (ui32SysClkFreq /(3 * 5));
           GPIOPinWrite (GPIO_PORTN_BASE、GPIO_PIN_0、1);
           SysCtlDelay (ui32SysClkFreq /(3 * 5));
           GPIOPinWrite (GPIO_PORTN_BASE、GPIO_PIN_0、0);
        }
    示波器屏幕截图:

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

    您好、RAB、

    在我看来、这可能是该分析仪的硬件问题或问题、就像您的代码一样、我在另一个 TM4C LaunchPad 上获得了以下输出。 明天我将尝试使用 TM4C1294、但我没有时间设置一个板上有上拉电阻的板来进行测试。

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

    您使用的分析仪的名称是什么?
    我使用的是 Picoscope 2205A、这是一款 USB 示波器、可将其设置为解码 I2C 等串行接口。
    令人困惑的是,当我使用分步调试(使用运行到行)时,我可以看到 API CONTR 正在发送字节。
    但是、当我尝试一次发送4个字节时、这不起作用。
    当我使用 Microchip PICkit Serial 试用 DAC 评估板时、它可以正常工作、我可以看到发送的所有 Salve 地址加4个字节。
    这是令人困惑的吗?
    此致、
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Rab:

     您能否在此帖子中引用变通办法并查看它是否有所不同?  

    基本上、替换以下行中出现的所有内容  

     while (I2CMasterBusy (I2C0_BASE)); //非忙

    作者   

     while (!I2CMasterBusy (I2C0_BASE)); //除了原始行外,还添加此行

     while (I2CMasterBusy (I2C0_BASE)); //非忙

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

    您好、Charles、

    很棒!  

    非常感谢您的帮助。

    它现在正在工作。 我可以在 API 开始和结束之间发送尽可能多的字节

    我从未想到会这么说。 我试图拖延。 这是最合乎逻辑的事情。

    我不知道这只是一个案例、还是需要在 Tiva C Serie Library 手册中突出显示、因此其他用户 不必经历这种混乱的情况。

    此致、

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    尊敬的 Rab:
    很高兴它能正常工作。 我同意需要强调这一点、这样人们就不会再次遇到同样的问题。