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/LAUNCHXL-F28069M:I²C 24C04的问题 E²PROM

Guru**** 2609895 points
Other Parts Discussed in Thread: CONTROLSUITE

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

https://e2e.ti.com/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/684501/ccs-launchxl-f28069m-i2c-issue-with-24c04-e2prom

器件型号:LAUNCHXL-F28069M
Thread 中讨论的其他器件:controlSUITE

工具/软件:Code Composer Studio

我需要使用 LAUNCHXL-F280969的 μ I²C 通信接口(异步输入 GPIO32 (SDAA)和异步输入 GPIO33 (SCLA))从/到24C04 μ e²prom 读取和写入非易失性参数。 我对24C04使用了以下相同的连接电路。

 

VCC 为3.3V、因为其数据表显示 VCC=1.8V 至5.5V。 +3.3V 和接地连接来自我的 launchxl 套件。 而不是来自不同的来源。

我在附件中使用了示例。

但我的代码卡在这里:

我的 I2caRegs.I2CSTR 状态寄存器如下所示:

我对 μ I²C 配置不熟悉、我认为我读取 EEPROM 1次、但不应该连续读取? XSMT 或 SCD 位有什么问题? 感谢您的关注。

e2e.ti.com/.../3276.0081.Example_5F00_2802xI2C_5F00_24LC256.c

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

    您能告诉我您是否在 LaunchPad 上看到了 I2C 信号?
    您是否收到一个 NACK、并在卡滞之前将其清除?

    此外、您还提到了您使用的是 F28069M Launchpad、但使用的是最初为 F2802x 编写的代码。 这些器件以不同的 SYSCLK 频率运行。 请检查您的 SYSCLK 频率配置、并确保内部 I2C 时钟分频器设置为 I2C 时钟预分频器将输入时钟(SYSCLK)分频至7MHz 至12MHz 之间。

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

    Labbato 先生、您好!

    "您能告诉我您是否在 LaunchPad 上看到了 I2C 信号? "

    32和33引脚在示波器上仅显示3.3V 电压。

    "你是否收到一个 NACK、它在卡滞之前被清除了?"

    是的。 下面:

    "您提到您使用的是 F28069M Launchpad、但使用的是最初为 F2802x 编写的代码。 这些器件以不同的 SYSCLK 频率运行。  请检查您的 SYSCLK 频率配置、并 确保内部 I2C 时钟分频器设置为 I2C 时钟预分频器将输入时钟(SYSCLK)分频 至7MHz 至12MHz 之间。"

    F28069的代码流程相同、但我没有检查 I2C 时钟。 谢谢、我将进行检查。  

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    请在您访问时告诉我时钟配置的结果。 如果这不正确、则无法保证 I2C 正常运行。

    谢谢、
    标记
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    OID I2CA_Init(void)
    {
    I2caRegs.I2CMDR.ALL = 0x0000;
    //初始化 I2C
    I2caRegs.I2CSAR = 0x0050; //从机地址—EEPROM 控制代码
    
    // I2CCLK = SYSCLK/(I2CPSC+1)
    
    I2caRegs.I2CPSC.all = 6;//6 //预分频器-模块时钟需要7-12MHz
    
    
    I2caRegs.I2CCLKL = 10; //注:必须为非零
    I2caRegs.I2CCLKH=5; //注:必须为非零
    // I2caRegs.I2CIER.ALL = 0x24; //启用 SCD 和 ARDY 中断
    
    I2caRegs.I2CMDR.ALL = 0x0020;//使 I2C 退出复位
    //挂起时停止 I2C
    
    I2caRegs.I2CFFTX.ALL = 0x6000;//启用 FIFO 模式和 TXFIFO
    I2caRegs.I2CFFRX.ALL = 0x2040;//启用 RXFIFO、清除 RXFFINT、
    
    
    返回;
    } 

    我还尝试了"Example_2806xI2C_EEPROM"示例,其中的 F2806x_CpuTimers.c 如下所示:

    //######################################################################################################################
    //
    ////文件:F2806x_CpuTimers.c
    //
    //标题:CPU 32位计时器初始化和支持函数。
    //
    //备注:
    //
    ////##################################################################################################################
    //$TI 发布:F2806x C/C++头文件和外设示例 V151 $
    //$发布 日期:2016年2月2日$
    //$版权:版权所有(C) 2011-2016德州仪器(TI)公司-
    //             http://www.ti.com/ 保留所有权利$
    //############################################################################################################
    
    #include "F2806x_Device.h" //头文件包含文件
    #include "F2806x_examples.h"//示例包括文件
    
    
    结构 CPUTIME_VARS CpuTimer0;
    结构 CPUTIME_VARS cpuTimer1;
    结构 CPUTIME_VARS cpuTimer2;
    
    //------------
    // InitCpuTimers:
    //-----------------
    //此函数将所有三个 CPU 计时器初始化为已知状态。
    //
    void InitCpuTimers (void)
    {
    // CPU 定时器0
    //初始化指向相应定时器寄存器的地址指针:
    CpuTimer0.RegsAddr =&CpuTimer0Regs;
    //初
    
    始化定时器周期到最大值:CpuTimer0Regs.PRD.All = 0xFFFFFFFF;//预分频计数器1 (SYSCLKOUT):CpuTimer0Regs.PRD.All = 0xFFFFFFFF;//
    
    
    确保 Timer0Pudp Timer0Tps.Tps.Tps.Tkr = 0r.TcpuTimer0r.Tps.Tps.Tps.Tps.Tps.Tps.Tps.Tps.Tps.Tps.Tps.Tps.Tps.
    
    //
    
    
    
    
    
    
    
    
    重新加载周期值为 CpuTimer0Regs.TCR.bit.TRB = 1的所有计数器寄存器;//重置中断计数器://CpuTimer0.InterruptCount = 0;//初始化指向相应定时器寄存器的地址指针:CpuTimer1.RegsAddr =&CpuTimer1FFFFs;CpuRegTimer2= 0xPRD;最大 CpuTimer2PRD
    
    ;CpuTimer2PRD = 0xP= 0xPureTimer2PRD;Timer1rf.TimerAddr;CpuTimer1rfr = 0xpTimer0rfr;CpuTimer0rfr;CpuTimer1rfr = 0xp
    //初始化预分频计数器以除以1 (SYSCLKOUT):
    CpuTimer1Regs.TPR.all = 0;
    CpuTimer1Regs.TPRHall = 0;
    CpuTimer2Regs.TPR.all = 0;
    CpuTimer2Regs.TPRH.all = 0;
    //确保定时器被停止:
    CpuTimer1Regs.TCR.bit.TSS = 1;
    CpuTimer2Regs.TCR.bit.TSS = 1;
    //重新加载周期值为
    CpuTimer1Regs.TCR.bit.TRB = 1;
    CpuTimer2Regs.TCR.BIT.BIT.B--的所有计数器寄存器---
    
    
    
    
    
    
    
    // ConfigCpuTimer:
    //-------------------------------------------------------
    //此函数将所选计时器初始化为
    "Freq"和"Period"参数指定的//周期。 "Freq"输入为"MHz"
    //周期、以"uSeconds "为单位。
    配置后、定时器保持在已停止状态//。
    //
    空 ConfigCpuTimer (struct CPUTIME_VARS *计时器、浮点频率、浮点周期)
    {
    uint32PeriodInClocks;
    
    //初始化计时器周期:
    Timer->CPUFreqInMHz =频率;
    Timer->PeriodInUSec =周期;
    PeriodInClocks =(长)(Freq *周期);
    每个 PRD 计数器
    
    1 +周期数1 +计数器1次;每个周期1个定期 InRegs =周期数1个 PRD 计数器1个+计数器1个计数器1个周期
    Timer->RegsAddr->TPR.All = 0;
    Timer->RegsAddr->T公 屋.all = 0;
    
    //初始化定时器控制寄存器:
    Timer->RegsAddr->TCR.bit.TSS = 1; // 1 =停止计时器,0 =启动/重新启动计时
    器->RegsAddr->TCR.bit.TRB = 1; // 1 =重新加载定时器
    Timer->RegsAddr->TCR.bit.Soft = 0;
    Timer->RegsAddr->TCR.bit.FREE = 0; //计时器自由运行已禁用
    计时器->RegsAddr->TCR.bit.tie = 1; // 0 =禁用/ 1 =启用计时器中断
    
    //重置中断计数器:
    Timer->InterruptCount = 0;
    
    }//============================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================
    
    
    //文件结束。
    //============================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================
    

    当我调试 C:\ti\controlSUITE\device_support\f2806x\v151\F2806x_examples_ccsv5\i2c_EEPROM 时、不会发生任何情况。 示波器在 SDAA 和 SCLA 引脚上显示+3V3。

    C:\ti\controlSUITE\device_support\f2806x\v150\F2806x_examples_ccsv5\i2c_eeprom 有点热情。 :D SDAA 和 SCLA 上没有发生任何事情,但至少 D7 LED 在 launchxl 上闪烁。 )

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

    您想对共享的代码和屏幕截图说些什么? 该示例现在起作用了吗?

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


    +3.3V 和接地连接来自我的 launchxl 套件、我认为这是问题所在。 我将为24c04提供不同的源。 我在示波器上没有看到任何通信或时钟信号、因此 NACK 始终处于激活状态。

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

    我还没有解决这个问题。

    I2cMsgIn1.MsgStatus 通常为33 (十进制)、有时为32 (十进制)。

    I2cMsgIn1.MsgBuffer[0]、I2cMsgIn1.MsgBuffer[1]、 I2cMsgIn1.MsgBuffer[2]、 I2cMsgIn1.MsgBuffer[3]为"0"  

    另一方面;

    I2cMsgOut1.MsgBuffer[0]= 18

    I2cMsgOut1.MsgBuffer[1]= 52

    I2cMsgOut1.MsgBuffer[2]= 42092

    I2cMsgOut1.MsgBuffer[3]= 6940

     I2CMSG 结构的 I2C 消息命令(C:\ti\controlSUITE\device_support\f2806x\v151\F2806x_common\include\f2806x_I2C_defins.h)如下所示 :

    #define I2C_MSGSTAT_INACTIVE 0x0000
    #define I2C_MSGSTAT_SEND_WITHSTOP 0x0010
    #define I2C_MSGSTAT_WRITE_BUSY 0x0011
    #define I2C_MSGSTAT_SEND_NOSTOP 0x0020
    #define I2C_MSGSTAT_SEND_NOSTOP_BUSY 0x0021
    #define I2C_MSGSTAT_RESTART 0x0022
    #define I2C_MSGSTAT_READ_BUSY 0x0023 

    这些是十六进制值、因此32表示"I2C_MSGSTAT_SEND_NOSTOP"、33表示"I2C_MSGSTAT_SEND_NOSTOP_BUSY"

    再说一次、

    该项目为 C:\ti\controlSUITE\device_support\f2806x\v151\F2806x_examples_ccsv5\i2c_EEPROM

    编译器版本为 TI v16.9.3.LTS

    当我使用"步入(F5)"时、这里有一个循环。

    //////////////////////////////////////////////////////////////////////
    //将数据写入 EEPROM 部分//
    //////////////////////////////////////////////////////////////////////
    
    //检查外发消息是否应发送。
    //在本例中,初始化后发送一个停止位。
    if (I2cMsgOut1.MsgStatus = I2C_MSGSTAT_SEND_WITHSTOP)
    {
    错误= I2CA_WriteData (&I2cMsgOut1);
    //如果通信已正确启动,请将 msg 状态设置为忙
    //并更新中断服务例程的 CurrentMsgPtr。
    //否则,不执行任何操作,然后重试下一个循环。 发送一条消息
    //启动后、I2C 中断将处理其余中断。 搜索
    //此文件中的 i2c_int1a_isr。
    如果(错误= I2C_Success)
    {
    CurrentMsgPtr =&I2cMsgOut1;
    I2cMsgOut1.MsgStatus = I2C_MSGSTAT_WRITE_BUSY;
    }
    }//写入段结束
    
    ////////////////////////////////////////////////////////////////////////
    //从 EEPROM 部分读取数据//
    ////////////////////////////////////////////////////////////////////////
    
    //检查外发消息状态。 如果状态为、则绕过读取段
    //未处于非活动状态。
    IF (I2cMsgOut1.MsgStatus = I2C_MSGSTAT_INACTIVE)
    {
    //检查传入消息状态。
    if (I2cMsgIn1.MsgStatus = I2C_MSGSTAT_SEND_NOSTOP)
    {
    // EEPROM 地址设置部分
    while (I2CA_ReadData (&I2cMsgIn1)!= I2C_Success)
    {
    //可以设置一个尝试计数器来打破无限 while
    //循环。 EEPROM 将在执行时发回一个 NACK
    //写入操作。 即使是写公报
    //完成此时,EEPROM 仍可能处于忙状态
    //对数据进行编程。 因此、会多次尝试
    //必需。
    }
    //更新当前消息指针和消息状态
    CurrentMsgPtr =&I2cMsgIn1;
    I2cMsgIn1.MsgStatus = I2C_MSGSTAT_SEND_NOSTOP_BUSY;
    } 

    因为"I2cMsgOut1.MsgStatus"是"17"、即"I2C_MSGSTAT_WRITE_BUSY"。

    经过一段时间或"F7 Step Return"之后、 I2cMsgOut1.MsgStatus 变为0、 I2C_MSGSTAT_INACTIVE。

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

    Troodoon、

    假设自以下回复(https://e2e.ti.com/support/microcontrollers/c2000/f/171/p/684501/2523457#2523457 )以来配置代码没有变化,则表示 I2C 尝试以514.285 KHz 运行,这与 I2C 规范不兼容。 I2C 模块时钟也高于数据表中指定的12MHz 最大值。 调整 I2CPS 以使 I2C 模块时钟介于7和12 MHz 之间:I2CPS = 8应该正常、因为 I2C 模块时钟将为10 MHz、恰好在所需的范围内。

    您还需要确保 I2CCLKCL 和 I2CCLKH 寄存器获得400KHz 或以下的主时钟速率。 当您的电流设置为10和5时、您将得到精确的400KHz。

    您在最新帖子中提到的循环显示 EEPROM 尚未完成其写入周期。 对于我的 EEPROM、这可能需要几毫秒的时间。 在标记任何错误之前、您是否等待足够长的时间来允许 EEPROM 写入周期发生?

    使用示波器将有助于我们对其进行调试。 请显示示波器或逻辑分析仪的一些捕获结果。 这是每次写入和读取4个字时 i2c-EEPROM 示例的序列。 随附了 I2C 总线分析仪的日志文件、其中显示了每个事务。

    1. 主机写入起始地址
    2. 主器件写入4字节数据、
    3. 主机写入起始地址
    4. 写入周期内的从器件 NAK (重复2.5ms)、
    5. 从机应答从主机写入的地址
    6. 主机写入起始地址
    7. 主器件读取4个数据字节
    8. 如果匹配则数据通过。

    我希望这有助澄清一些混乱情况。 请告诉我。

    -Mark

    /cfs-file/__key/communityserver-discussions-components-files/171/i2c_5F00_eeprom_2D00_4byte_2D00_example.csv

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

    Labbato 先生、您好!

    感谢您的回答。  

    我已将 I2CPS 更改为"8"。   您知道 I2CCLKCL 和 I2CCLKH 为10和5。

    "在标记任何错误之前、您是否等待足够长的时间以允许 EEPROM 写入周期发生?"  

    我只使用"C:\ti\controlSUITE\device_support\f2806x\v151\F2806x_examples_ccsv5\i2c_EEPROM"示例。 我没有改变任何东西、至少是有意的。 我只想了解示例和 EEPROM i2c 通信的工作原理。  

    我的电路如下。 很抱歉耽误你的时间。 )

    即:  

    示例的文件分别位于附件上。

    当我选中"GpioDataRegs.GPADD.bit.GPIO28和29时、这些值会连续变为0或1、这很酷。

    但在示波器上、(Autoset) GPIO28和29如下所示:

    并检查:

    我不知道圆圈内的 LED 是否与 I2C 相关、但这让我知道有通信。 此外 、I2caRegs.I2CSTR 的 BB (总线忙)位通常为1。

    但是、正如我提到的、我无法读取、我无法写入。  

    当我在工作区内处理不同的项目时、我认为我更改了一些文件、例如"F2806x_SYSCTRL。 C"。 如果默认示例和我的示例项目之间存在重要差异、我将这些文件逐个添加为 txt 文件。  

    e2e.ti.com/.../Example_5F00_2806xI2C_5F00_eeprom.txt

    e2e.ti.com/.../F2806x_5F00_CodeStartBranch.txt

    e2e.ti.com/.../F2806x_5F00_CpuTimers.txt

    e2e.ti.com/.../F2806x_5F00_DefaultIsr.txt

    e2e.ti.com/.../F2806x_5F00_GlobalVariableDefs.txt

    e2e.ti.com/.../F2806x_5F00_Headers_5F00_nonBIOS.txt

    e2e.ti.com/.../F2806x_5F00_I2C.txt

    e2e.ti.com/.../F2806x_5F00_PieCtrl.txt

    e2e.ti.com/.../F2806x_5F00_PieVect.txt

    e2e.ti.com/.../F2806x_5F00_SysCtrl.txt

    e2e.ti.com/.../F2806x_5F00_usDelay.txt

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

    您没有看到示波器上的引脚切换、并且看到蓝色 LED 圈出、这是有道理的。 请再次查看您的原理图。

    默认情况下、配置示例代码、以便 I2C 使用 GPIO28和 GPIO29。 LaunchPad 将 GPIO28和 GPIO29用于 XDS100的反向通道 UART、这些引脚上的活动将触发蓝色 LED 切换。

    LaunchPad 的原理图显示、您选择的站点和连接到 EEPROM 的引脚为 GPIO32和 GPIO33。 您需要更改软件、以便为连接到 EEPROM 的引脚选择合适的 GPIO 引脚和多路复用器。

    在这种情况下(引脚应切换但不应切换)、比较原理图、代码和硬件连接通常是一个好做法、以确保所有引脚都对齐。

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

    解决了。 )

    这是一个非常好的细节,我对此表示尊重。 我有时会忘记 LaunchPad 的硬件功能。 我将始终检查原理图。

    MsgBuffer[1]和 MsgBuffer[2]是被写入/读取的、[3]和[4]是我的另一个故事。

    I2cMsgOut1的 MsgBuffer [3]、[4]是 EEPROM 地址、I2cMsgIn1的 MsgBuffer [3]、[4]根据我猜测的示例、我不知道什么、但0读取值是正常的。

    无论如何、至少有一个要修改的通信。

    谢谢你。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您的最新共享代码中的 I2C_NUMBYTES 看起来仍然设置为2。 如果您将其调整为4、您将看到传输了4个字节。

    很高兴沟通现在开始了! 如果您遇到新问题、请创建一个新主题、我们将帮助您解决问题。

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

    如果我将 I2C_NUMBYTES 设置为4、则所有4个 MsgBuffers 都变为0。 原因可能是 FIFO 溢出填充(可以发送2个数据字节+ 2个地址字节)。
    我已阅读以下主题。

    e2e.ti.com/.../669215

    要发送浮点值、我可以使用字符-十六进制值或字节序方法。 我不确定。 但是、正如您提到的、这是另一个要创建的主题。 在此之前,还需要进行一些研究。 )

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    来思考一下、您是正确的。 由于 F28069M 只有4字节 FIFO、要发送的地址占用2个字节、因此它只能发送额外的2个字节。
    简而言之、该示例只能发送2个数据字节。 您需要进行修改以扩展传输的数据。 可能会添加另一个传输阶段来发送其余数据。 此时、我只能提供指导、但您可以根据需要随意修改示例。

    此致、
    标记