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.

[参考译文] TMS320F28069:I2C CAN#39;t 使用 HDC1010获取正确的数据

Guru**** 2541900 points
Other Parts Discussed in Thread: HDC1010, C2000WARE

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

https://e2e.ti.com/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/623663/tms320f28069-i2c-can-t-get-correct-data-with-hdc1010

器件型号:TMS320F28069
主题中讨论的其他器件:HDC1010C2000WARE

大家好、我使用 F28069从传感器 HDC1010读取数据。

我可以读取  ManufacturerID 和 DeviceID 的正确数据。 但我无法获取传感器的正确数据。

读取 制造商 ID:确定

2.配置传感器:好的

从寄存器0x00读取温度:失败、但逻辑分析仪捕获了正确的数据、如下所示、但数据缓冲区读取错误。

再次从寄存器读取温度:获取最后一次的数据、我真的不知道原因。

5. I2C 初始化代码

void I2CA_Init (void)
{
//初始化 I2C
I2caRegs.I2CMDR.all = 0x0000;
I2caRegs.I2CSAR = 0; //从地址

I2caRegs.I2CPSC.all = 8; //预分频器-模块时需要7-12MHz 的时钟
I2caRegs.I2CCLKL = 10; //注:必须为非零
I2caRegs.I2CCLKH=5; //注:必须为非零

//I2caRegs.I2CIER。all = 0x24; //启用 SCD 和 ARDY 中断0010 0100
I2caRegs.I2CIER.bit.AAS = 0; //寻址为从器件中断使能位
I2caRegs.I2CIER.bit.SCD = 1; //检测到停止条件中断使能位
I2caRegs.I2CIER.bit.XRDY = 0; //发送数据就绪中断使能位
I2caRegs.I2CIER.bit.XRDY = 0; //接收数据就绪中断使能位
I2caRegs.I2CIER.bit.ARDY = 1; //寄存器访问就绪中断使能位
I2caRegs.I2CIER.bit.nack = 0; //无确认中断使能位
I2caRegs.I2CIER.bit.ARBL = 0; //仲裁丢失中断使能位

//I2caRegs.I2CMDR.ALL = 0x0020; //使 I2C 退出复位状态,挂起
I2caRegs.I2CMDR.bit.NACKMOD = 0时停止 I2C; // NACK 模式位
I2caRegs.I2CMDR.bit.FREE = 0; //挂起
I2caRegs.I2CMDR.bit.STT = 0时停止 I2C; //起始条件位
I2caRegs.I2CMDR.bit.STP= 0; //停止条件位
I2caRegs.I2CMDR.bit.MST = 0; //从机模式
I2caRegs.I2CMDR.bit.TRX = 0; //接收器模式
I2caRegs.I2CMDR.bit.XA = 0; // 7位寻址模式
I2caRegs.I2CMDR.bit.RM = 0; //非重复模式
I2caRegs.I2CMDR.bit.DLB = 0; //数字回送模式被禁用
I2caRegs.I2CMDR.bit.IRS = 1; // I2C 模块被使能
I2caRegs.I2CMDR.bit.STB=0; // I2C 模块不在起始字节模式
I2caRegs.I2CMDR.bit.FDF = 0; //自由数据格式模式被禁用
I2caRegs.I2CMDR.bit.BC = 0; //每个数据字节8位

// I2caRegs.I2CFFTX.all = 0x6000; //启用 FIFO 模式和 TXFIFO
I2caRegs.I2CFFTX.bit.I2CFFEN = 1; //启用 I2C FIFO 模式
I2caRegs.I2CFFTX.bit.TXFFRST=1; //启用发送 FIFO 操作
I2caRegs.I2CFFTX.bit.TXFFINTCLR = 0; //清除 TXFFINT 标志
I2caRegs.I2CFFTX.bit.TXFFIENA=0; 当 I2caRegs.I2CFFTX.bit.TXFFIL
= 0时、// TXFFINT 标志不会生成中断; //发送 FIFO 中断级别

// I2caRegs.I2CFFRX.ALL = 0x2040; //启用 RXFIFO、清除 RXFFINT
I2caRegs.I2CFFRX.bit.RXFFRST = 1; //启用接收 FIFO 操作
I2caRegs.I2CFFRX.bit.RXFFINTCLR = 1; //清除 RXFFINT 标志
I2caRegs.I2CFFRX.bit.RXFFIENA=0; 当 I2caRegs.I2CFFRX.bit.RXFFIL
= 0时、// RXFFINT 标志会生成一个中断; //接收 FIFO 中断级别

返回;
} 

读取传感器的功能

void HDC_GetSensor (uint16 addr、uint16 reg、uint16 ReadCount、uint8 *缓冲区)
{
uint16 i;

I2caRegs.I2CMDR.bit.IRS = 1; //复位 I2C

//确保 I2C 不忙且已停止
while (I2cRegs.I2CSTR.bit.BB = 1); //忙循环
I2caRegs.I2CSTR.bit.SCD = 1; //清除 SCD 位(停止条件位)
while (I2caRegs.I2CMDR.bit.STP==1); //停止位循环

I2caRegs.I2CSAR = addr; // I2C 从地址

I2caRegs.I2CMDR.ALL = 0x2E20; //开始、无停止位、主器件、TX、复位 I2C 00100110

I2caRegs.I2CCNT = 1; //假设寄存器地址为一个字节
I2caRegs.I2CDXR =寄存器; //传感器的寄存器地址(1个字节)


//while (!I2caRegs.I2CSTR.bit.ARDY); //准备好了吗?
while (HDC_DRDY_READ ()!= HDC_Ready);


I2caRegs.I2CMDR.ALL = 0x2C20; //开始、CNT = 0时的停止位、主器件、Rx、复位 I2C 00101100
I2caRegs.I2CCNT = ReadCount; //只读取一个字节数据

if (I2caRegs.I2CSTR.bit.nack = 1)
{
I2caRegs.I2CSTR.All = I2C_CLR_Nack_bit;// 0x0002
}
I2caRegs.I2CMDR.bit.STP= 1; // CNT=0时停止位

while (!I2cRegs.I2CSTR.bit.SCD); //是否检测到停止位?

对于(I = 0;I < ReadCount;I++)
{
Buffer[i]= I2caRegs.I2CDRR; //读取一个字节数据
}
} 

e2e.ti.com/.../F28069_5F00_HDC1010_5F00_2.rar

e2e.ti.com/.../hdc1010.pdf

感谢您的帮助!

)

-Di

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

    尊敬的 Di:

    在第一个读取温度中、缓冲器阵列被两个元件的字节0xF1填充。 您是否知道这些字节的来源? 它们可能之前就一直处于 I2CDRR 中。

    当您尝试接收两个新的数据字节时、可能发生的情况(但会很奇怪)会溢出。 在读取任何数据字节之前、以下寄存器应该等于0、"I2cRegs.I2CSTR.bit.RSFULL"、如果它等于1、那么在载入新数据之前、将需要读取 I2CDRR。 在以下用户指南的第29页上阅读有关该寄存器的更多信息:

    您可能还需要在代码中观察 I2cRegs.I2CSTR.bit.RRDY 寄存器、如下所示:

    对于(I = 0;I < ReadCount;I++)
    {
    while (!I2caRegs.I2CSTR.bit.RRDY);//检查数据是否就绪
    Buffer[i]= I2caRegs.I2CDRR; //读取一个字节数据
    //buffer[i]= reg;
    } 

    我认为、查看这两个寄存器是更好地了解问题的良好起点。 您可以尝试单步执行代码并在"Expressions"窗口中查看它们、以查看它们在程序中的特定点处是什么。

    希望这对您有所帮助、

    Kevin

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

    尊敬的 Kevin:

     感谢您的回复、您的回复很好、很有帮助。

     我逐步运行代码、发现初始化代码有问题。

     只需查看下面的图片即可。

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

    尊敬的 Kevin:

     如图所示、I2CDRR 在 I2caRegs.I2CFFTX.bit.I2CFFEN = 1后变为0x68。 我不知道为什么数据寄存器发生变化。

     在 I2caRegs.I2CFFRX.bit.RXFFRST = 1后、RXFFINT 变为1、这是合理的(如果 RXFFIENA 位被置位、该位将在置位时产生一个中断。) RXFFRST 表明 FIFO 包含1个字节。

     那么 I2cRegs.I2CFFTX.bit.I2CFFEN = 1意味着什么呢?

     是否可以在初始化代码后复位 FIFO?

     期待您的回复。

     DI

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    尊敬的 Kevin:
    是否有示例显示如何使用 I2C FIFO 读取/写入字节?

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

    我需要更深入地研究您之前的回答、可能直到明天某个时候才会有好的答案。

    同时、是的、C2000Ware 中的以下目录中有一个 I2C FIFO 模式示例:

    C:\ti\c2000Ware_1_00_01_00\device_support\f2806x\examples\c28\i2c_eeprom

    此示例是由中断驱动的、但具有读取/写入函数。

    我将很快向您回复您的其他问题。

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

    当您将 I2CARegs.I2CFFTX.BI2CFFEN 置1时、I2CDRR 寄存器将用作接收 FIFO 缓冲器、I2CDXR 寄存器将用作发送 FIFO 缓冲器。 话虽如此、当 FIFO 被启用时、I2CDRR 会立即开始接收 SDA 线上的任何内容、这就是您看到 FIFO 被填充的原因。

    至于复位 FIFO、您可以启用/禁用 FIFO 模式(I2CFFEN)或复位/启用 I2C TX 或 RX FIFO (TXFFRST 和 RXFFRST)、但我不确定这是否会清除缓冲区或任何内容。

    我之前提到过查看 I2caRegs.I2CSTR.bit.RRDY 寄存器、但这是错误的、实际上不是您在 FIFO 模式下想要查看的内容。 以下中断标志实际上是您想要查看的内容:

    I2caRegs.I2CFFRX.bit.RXFFINT => RX FIFO 中断标志

    I2caRegs.I2CFFTX.bit.TXFFRST=>TX FIFO 中断标志

    我认为、要解决这个问题、需要更多的调试。 您可以尝试在 init 函数期间观察 I2C 线路、以查看正在接收的数据。 此外、单步执行其余代码(I2C 读取)、观察不同的寄存器和 I2C 线路。

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

    尊敬的 Kevin:

     感谢您的帮助、我终于找到了 I2C 和 HDC1010的问题、并找到了解决方法。

     问题出在这里。 针对温度/湿度、通过写入0x00/0x01来触发 HDC1010。 请注意、SCL 应该被拉高。  

    但是、如果我在没有停止的情况下写入0x00/0x01、SCL 将保持低电平、然后 HDC 将永远不会准备好读取。

    如果我在写完后再加一个停止、那么就像我在上面所说的那样、事情会发生错误。

    那么、如何在写入后将 SCL 拉高。

    I2caRegs.I2CMDR.bit.IRS = 1; //复位 I2C
    
    //确保 I2C 不忙且已停止
    while (I2cRegs.I2CSTR.bit.BB = 1); //忙循环
    I2caRegs.I2CSTR.bit.SCD = 1; //清除 SCD 位(停止条件位)
    //while (I2caRegs.I2CMDR.bit.STP = 1); //停止位循环
    
    I2caRegs.I2CSAR = addr; // I2C 从地址
    
    while (I2cRegs.I2CSTR.bit.BB = 1); //仍然忙?
    
    I2caRegs.I2CMDR.ALL = 0x2620; //开始、无停止位、主器件、TX、复位 I2C 00100110
    // I2caRegs.I2CMDR.bit.NACKMOD = 0; // 15:NACK 模式位
    // I2caRegs.I2CMDR.bit.FREE = 0; // 14:挂起时停止 I2C
    // I2caRegs.I2CMDR.bit.STT = 1; // 13:起始条件位
    // I2caRegs.I2CMDR.bit.STP=0; // 11:停止条件位
    // I2caRegs.I2CMDR.bit.MST = 1; // 10:主控模式
    // I2caRegs.I2CMDR.bit.TRX = 1; // 9:发送器模式
    // I2caRegs.I2CMDR.bit.XA = 0; // 8:7位寻址模式
    // I2caRegs.I2CMDR.bit.RM = 0; // 7:非重复模式
    // I2cRegs.I2CMDR.bit.DLB = 0; // 6:数字回送模式被禁用
    // I2caRegs.I2CMDR.bit.IRS = 1; // 5:使能 I2C 模块
    // I2caRegs.I2CMDR.bit.STB=0; // 4:I2C 模块不在起始字节模式
    // I2caRegs.I2CMDR.bit.FDF = 0; // 3:禁用自由数据格式模式
    // I2caRegs.I2CMDR.bit.BC = 0; //每个数据字节2-0:8位
    
    I2caRegs.I2CCNT = 1; //假设寄存器地址为一个字节
    I2caRegs.I2CDXR =寄存器; //传感器的寄存器地址(1个字节)
    
    
    while (!I2cRegs.I2CSTR.bit.ARDY); //准备好了吗?
    // while (HDC_DRDY_READ ()!= HDC_Ready); 

    2.解决问题的方法。

     为了将 SCL 拉低至少一次、我在触发测量后读取 HDC1010数据、即使我知道数据未就绪。 然后、我得到一个正常的 NACK。 但 HDC1010被成功触发、我等待 DRDY 引脚变为低电平、然后读取寄存器并获取正确的数据!

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

    尊敬的 Kevin:

     尽管我已经解决了这个问题、但我想知道如何在写入后将 SCL 拉高。  

     以下是我阅读 HDC1010的最后代码、我希望它能为他人提供帮助。

    void HDC_GetSensor (uint16 addr、uint16 reg、uint16 ReadCount、uint8 *缓冲区)
    {
    uint16 i;
    
    I2caRegs.I2CMDR.bit.IRS = 1; //复位 I2C
    
    //确保 I2C 不忙且已停止
    while (I2cRegs.I2CSTR.bit.BB = 1); //忙循环
    I2caRegs.I2CSTR.bit.SCD = 1; //清除 SCD 位(停止条件位)
    //while (I2caRegs.I2CMDR.bit.STP = 1); //停止位循环
    
    I2caRegs.I2CSAR = addr; // I2C 从地址
    
    while (I2cRegs.I2CSTR.bit.BB = 1); //仍然忙?
    
    I2caRegs.I2CMDR.ALL = 0x2620; //开始、无停止位、主器件、TX、复位 I2C 00100110
    // I2caRegs.I2CMDR.bit.NACKMOD = 0; // 15:NACK 模式位
    // I2caRegs.I2CMDR.bit.FREE = 0; // 14:挂起时停止 I2C
    // I2caRegs.I2CMDR.bit.STT = 1; // 13:起始条件位
    // I2caRegs.I2CMDR.bit.STP=0; // 11:停止条件位
    // I2caRegs.I2CMDR.bit.MST = 1; // 10:主控模式
    // I2caRegs.I2CMDR.bit.TRX = 1; // 9:发送器模式
    // I2caRegs.I2CMDR.bit.XA = 0; // 8:7位寻址模式
    // I2caRegs.I2CMDR.bit.RM = 0; // 7:非重复模式
    // I2cRegs.I2CMDR.bit.DLB = 0; // 6:数字回送模式被禁用
    // I2caRegs.I2CMDR.bit.IRS = 1; // 5:使能 I2C 模块
    // I2caRegs.I2CMDR.bit.STB=0; // 4:I2C 模块不在起始字节模式
    // I2caRegs.I2CMDR.bit.FDF = 0; // 3:禁用自由数据格式模式
    // I2caRegs.I2CMDR.bit.BC = 0; //每个数据字节2-0:8位
    
    I2caRegs.I2CCNT = 1; //假设寄存器地址为一个字节
    I2caRegs.I2CDXR =寄存器; //传感器的寄存器地址(1个字节)
    
    
    while (!I2cRegs.I2CSTR.bit.ARDY); //准备好了吗?
    // while (HDC_DRDY_READ ()!= HDC_Ready);
    
    
    I2caRegs.I2CMDR.ALL = 0x2C20; //开始、CNT = 0时的停止位、主器件、Rx、复位 I2C 00101100
    I2caRegs.I2CCNT = ReadCount; //只读取一个字节数据
    
    while (HDC_DRDY_READ ()!= HDC_Ready);
    
    I2caRegs.I2CMDR.ALL = 0x2C20; //开始、CNT = 0时的停止位、主器件、Rx、复位 I2C 00101100
    I2caRegs.I2CCNT = ReadCount; //只读取一个字节数据
    
    if (I2caRegs.I2CSTR.bit.nack = 1)
    {
    I2caRegs.I2CSTR.All = I2C_CLR_Nack_bit;// 0x0002
    }
    I2caRegs.I2CMDR.bit.STP= 1; // CNT=0时停止位
    
    while (!I2cRegs.I2CSTR.bit.SCD); //是否检测到停止位?
    
    对于(I = 0;I < ReadCount;I++)
    {
    Buffer[i]= I2caRegs.I2CDRR; //读取一个字节数据
    }
    } 

    此致、

    DI

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

    尊敬的 Di:

    我需要进一步研究这一点、但为了澄清、只有在您向 HDC1010写入一个字节之后、而不是在读取之后、您才会遇到问题? SCL 在写入1个字节后一直保持低电平? 编辑:如果是、从器件将 SCL 保持在低电平、则可能是这样。

    下面是代码部分:

    I2caRegs.I2CSAR = addr; // I2C 从地址
    
    while (I2cRegs.I2CSTR.bit.BB = 1); //仍然忙?
    
    I2caRegs.I2CMDR.ALL = 0x2620; //开始、无停止位、主器件、TX、复位 I2C 00100110
    
    
    I2caRegs.I2CCNT = 1; //假设寄存器地址为一个字节
    I2caRegs.I2CDXR =寄存器; //传感器的寄存器地址(1个字节)
    
    
    while (!I2cRegs.I2CSTR.bit.ARDY); //准备好了吗?
    // while (HDC_DRDY_READ ()!= HDC_Ready);
    

    最棒的

    Kevin