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.

[参考译文] HDC3020:无法正确读取第一个数据。

Guru**** 2457910 points
Other Parts Discussed in Thread: HDC3020

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

https://e2e.ti.com/support/sensors-group/sensors/f/sensors-forum/1493457/hdc3020-the-first-data-cannot-be-read-correctly

器件型号:HDC3020

工具与软件:

打开 HDC3020后、无法正确读取第一个数据。
第一个数据始终为零。
如果我读取一次数据、等待6ms、然后再次读取数据、将读取正确的数据。
为什么会这样呢?

void Test1()
{
	PowerOn();
	Wait1s();

	I2C_RepeatedStartSequence_MultiDataResult();	// Result is Zero
	Wait6ms();
	I2C_RepeatedStartSequence_MultiDataResult();	// Result is Correct Value
	I2C_RepeatedStartSequence_MultiDataResult();	// Result is Correct Value
	I2C_RepeatedStartSequence_MultiDataResult();	// Result is Correct Value
}

void Test2()
{
	PowerOn();
	Wait1s();

	I2C_RepeatedStartSequence_MultiDataResult();	// Result is Zero
	I2C_RepeatedStartSequence_MultiDataResult();	// Result is Zero
	I2C_RepeatedStartSequence_MultiDataResult();	// Result is Zero
	I2C_RepeatedStartSequence_MultiDataResult();	// Result is Zero
}

void Test3()
{
	PowerOn();
	Wait1s();

	I2C_RepeatedStartSequence_MultiDataResult();	// Result is Zero
	Wait4ms();
	I2C_RepeatedStartSequence_MultiDataResult();	// Result is Zero
	Wait4ms();
	I2C_RepeatedStartSequence_MultiDataResult();	// Result is Zero
	Wait4ms();
	I2C_RepeatedStartSequence_MultiDataResult();	// Result is Zero
}

* I2C_Repeatedsnap (Sequence_Multi) IS
www.ti.com/.../hdc3020.pdf
图7-6. I2C 重复 START 序列、多个数据结果

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

    其他说明:
    HDC3020的命令是0x2C06 (按需触发模式)。

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

    Manabu-San,

    您是否在任何时候看到 HDC3020的 NACK、温度和湿度结果是否为0? 结果是否为0x0000、或读数为0°C 和0% RH (0°C 不会读取十六进制代码0x0000)? 分享示波器屏幕截图可能会有所帮助。 无论初始等待时间是多少、您是否收到此不良的初始结果?

    谢谢

    - Alex Thompson

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

    感谢您发送编修。

    首先、我要更正一个错误。
    读取方法不是
    "图7-6. I2C 重复启动序列、多个数据结果"、
    而是作为组合
    "图7-1. I2C 写入命令、无需配置数据"

    "图7-4. I2C 读取多个数据结果"。
    抱歉。

    通过插入一个15ms 等待时间(初始等待时间?) "写入"命令和"读取"命令
    可以读取正确的值。

    我以前使用的产品(Senserion SHT3x 系列)具有时钟拉伸功能、
    因此、无需等待15ms。

    HDC3020是否具有类似的功能?

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

    Manabu-San,

    感谢您提供最新信息。 我建议遵循图7-6中列出的顺序、这是从 HDC3020获取数据的最佳方法。 您只需等待~15ms、然后才会重复启动以允许传感器进行转换。 HDC3020不支持时钟延展。

    所谓的"初始等待时间"、并不是指转换期间的等待时间、而是指您在 HDC3020上电之后和首次通信之前等待的时间。 在启动后、传感器至少需要5ms 的等待时间才能开始通信。 是否满足这个等待时间?

    此致

    - Alex Thompson

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

    感谢您的答复。

    我按照图7-6读出数据、但第一个数据仍然为零。
    打开电源后我等待了15毫秒、然后才读取数据。

    如图7-10所示、如果测量值​​尚未准备就绪、则应返回 NAK、但返回 ACK。

    为什么会这样?

    即使在上电后等待15ms、执行软复位(0x30A2)并等待3ms 后、也会出现相同的结果。

    // for MICROCHIP PIC24FJ128GC010
    void i2cStart()
    {
    	I2C1CONbits.SEN = 1;
    	while (I2C1CONbits.SEN == 1) {}
    }
    void i2cRepeatedStart()
    {
    	I2C1CONbits.RSEN = 1;
    	while (I2C1CONbits.RSEN) {}
    }
    void i2cStop()
    {
    	I2C1CONbits.PEN = 1;
    	while (I2C1CONbits.PEN == 1) {}
    }
    void i2cAck()
    {
    	I2C1CONbits.ACKDT = 0;
    	I2C1CONbits.ACKEN = 1;
    	while (I2C1CONbits.ACKEN) {}
    }
    void i2cNak()
    {
    	I2C1CONbits.ACKDT = 1;
    	I2C1CONbits.ACKEN = 1;
    	while (I2C1CONbits.ACKEN) {}
    }
    unsigned char i2cWrite(unsigned char data)
    {
    	I2C1TRN = data;
    	while (I2C1STATbits.TRSTAT | I2C1STATbits.TBF) {}
    	return I2C1STATbits.ACKSTAT;
    }
    unsigned char i2cRead()
    {
    	I2C1CONbits.RCEN = 1;
    	while (I2C1STATbits.RBF == 0) {}
    	return (unsigned char)I2C1RCV;
    }
    void i2cTest(unsigned char *p)
    {
    	int i;
    	unsigned char ret;
    
    	// wait 15ms
    	for (i = 0; i < 15; i++)
    	{
    		Delay_1ms();
    	}
    
    /*
    	// Soft Reset
    	i2cStart();							// Start Condition
    	ret = i2cWrite(0x88);				// Address(W)
    	ret = i2cWrite(0x30);				// Command(H)
    	ret = i2cWrite(0xA2);				// Command(L)
    	i2cStop();							// Stop Condition
    
    	// wait 3ms
    	for (i = 0; i < 3; i++)
    	{
    		Delay_1ms();
    	}
    */
    
    	i2cStart();							// Start Condition
    	ret = i2cWrite(0x88);				// Address(W)
    	ret = i2cWrite(0x2C);				// Command(H)
    	ret = i2cWrite(0x06);				// Command(L)
    	i2cRepeatedStart();					// Repeated Start Condition
    	ret = i2cWrite(0x88 | 0x01);		// Address(R)
    	while (ret)
    	{
    		i2cStop();						// Stop Condition
    
    		// wait 3ms
    		for (i = 0; i < 3; i++)
    		{
    			Delay_1ms();
    		}
    
    		i2cStart();						// Start Condition
    		ret = i2cWrite(0x88 | 0x01);	// Read Address
    	}
    	for (i = 0; i < 5; i++)
    	{
    		*p++ = i2cRead();				// Data
    		i2cAck();						// ACK
    	}
    	*p++ = i2cRead();					// Data
    	i2cNak();							// NACK
    	i2cStop();							// Stop Condition
    }

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

    Manabu-San,

    我建议查看 ASC Studio 中的 HDC3020代码示例:

     https://dev.ti.com/sysconfig/index.html#/config/?args=--product%20%2Fmnt%2Ftirex-content%2Fascstudio_1_17_0%2F.metadata%2Fproduct.json%20--device%20Other&module=%2Fti%2Fsensors%2Fhumiditysensor%2FHDC3020

    这里有 HDC3020的 C 代码示例、请尝试并查看第一次读取问题是否仍然存在。

    谢谢

    - Alex Thompson

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

    感谢您提供示例代码。

    但是、在检查这些内容之后、似乎这不是图7-6 (I2C 重复开始序列、多个数据结果)的示例代码。

    这是使用图7-1 (I2C 写入命令、无需配置数据)和图7-4 (I2C 读取多数据结果)的示例代码。
    写入命令和读取命令之间固定等待12ms、通过使用此方法、我的代码能够读取正确的测量值。

    您是否知道图7-6中有用的示例代码?

    /*
     *  ======== HDC3020_read ========
     *  Read temperature and humidity registers
     */
    void HDC3020_read(HDC3020_Handle sensor, int32_t values[])
    {
        uint8_t txBuf[2];
        uint8_t rxBuf[6] = {0};
    
        /* If needed, trigger conversion */
        if (sensor->mode1 == HDC3020_MODE_TRIG_MSB) {
            txBuf[0] = sensor->mode1;
            txBuf[1] = sensor->mode2;
        } else {
        /* send read command */
            txBuf[0] = HDC3020_MODE_READ_MSB;
            txBuf[1] = HDC3020_MODE_READ;
        }
        mcu_i2cTransfer(sensor->busId, sensor->devAddr, txBuf, 2, NULL, 0);
    
        /* Wait for measurement */
        mcu_msWait(sensor->osWait);
    
        /* read temperature, humidity bytes */
        mcu_i2cTransfer(sensor->busId, sensor->devAddr, NULL, 0, rxBuf, 6);
    
        /* check temperature CRC */
        uint8_t tchk[3] = {rxBuf[0], rxBuf[1], rxBuf[2]};
        if (HDC3020_CRC_A(tchk, 3)) {
            /* report temperature CRC error!
            a non-zero return indicates bad CRC */
        }
    
        /* check humidity CRC */
        uint8_t hchk[3] = {rxBuf[3], rxBuf[4], rxBuf[5]};
        if (HDC3020_CRC_A(hchk, 3)) {
            /* report humidity CRC error!
            a non-zero return indicates bad CRC */
        }
    
        /* store temperature */
        values[0] = ((int32_t)rxBuf[0]) << 8 | rxBuf[1];
        /* store humidity */
        values[1] = ((int32_t)rxBuf[3]) << 8 | rxBuf[4];
    }

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

    冷静地思考一下、我认为问题不是代码、而是在第一次测量期间、出现"测量未就绪"时不会返回 NAK、如图7-10所示。
    从之前上传的 I2C 波形图像中可以看出、SCL 和 SDA 的控制似乎不正确。
    有什么想法、原因可能是什么?
    上电和读取之间需要等待足够长的时间。

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

    我按如下方式更改了代码、并使用 SHT31 (Sensirion)和 HDC3020 (TI)检查了运行情况。

    1、执行软复位(0x302A)。
    2、等待3ms。
    3、根据图7-6 (7-9、7-10)读取使用"按需触发-低功耗模式0 (0x2400)"的测量值。

    如图7-10所示、SHT31返回了 NAK、但 HDC3020未返回 NAK。
    这是 HDC3020中的错误吗?
    或者我是不是以某种方式使用它?

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

    Manabu-San,

    这很可能是一个错误、我将在结束时对此进行探讨 不过、我只想确认一下、使用示例代码中的方法(使用图7-1和图7-4、而不是7-6)每次都适用(即使是在首次读取时)、正确吗? 使用图7-6中的方法(通过重复启动)在上电或复位后的第一次读取不起作用、但对所有其他后续读取都有效、这种情况是否仍然正确?

    为了尝试因测量尚未就绪而从 HDC3020中获得 NACK、您是在写入命令完成后立即发送重复启动和后续数据读取、还是等待足够的时间来完成转换? 我想您是对的、当数据未就绪时、HDC3020不会返回 NACK、因此器件会输出无用结果。 我试图掌握的是你第一次阅读和其他阅读之间的不同之处。 因为如果您的单次触发等待时间不足、请求的数据尚未准备就绪、那么您的所有读取操作都将发生这种情况、而不仅仅是第一次。 请确认这是问题所在。

    最后、每次复位、硬复位(上电/断电)和软复位(软件复位)后、你是否看到"第一次读取错误"? 我只是想确保我了解问题的范围。

    谢谢

    - Alex Thompson

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

    感谢您的答复。
    我将回答您的问题。


    (Q1)不过、我只想确认使用示例代码中的方法(使用图7-1和图7-4、而不是7-6)每次都适用于您、即使是在首次读取时也是如此吗?

    是的、每次都能获得正确的读数。 但是、如果没有在写入命令和读取命令之间插入适当的等待、则不会生成 NAK、并且您将读取零。 从第二次开始、测量值似乎正确、但由于即使未插入等待、也不返回 NAK、因此我不确定测量值是否真的正确。 (如果测量值​​尚未准备就绪、我们希望您在图7-4中的"读取"之后在"ACK"部分中返回 NAK。)


    (Q2)。使用图7-6中的方法(具有重复启动)在上电或复位后的第一次读取不起作用、但对所有其他后续读取都有效、这种情况是否仍然正确?

    从第二次开始、​读取的测量值似乎是正确的。 但是、如图7-6所示、即使在写命令后立即执行读命令、也不返回 NAK、因此它是否真正正常工作是有疑问的。


    (Q3)为了尝试在测量尚未就绪时从 HDC3020中获取 NACK、您是在写入命令完成后立即发送重复启动和后续数据读取、还是等待足够的时间来完成转换?

    在图7-6中、写入命令完成后立即发送重复启动和后续数据读取。


    (四)我正在尝试掌握的是,你的第一次阅读和其他阅读之间的不同之处,这是有效的。 因为如果您的单次触发等待时间不足、请求的数据尚未准备就绪、那么您的所有读取操作都将发生这种情况、而不仅仅是第一次。 请确认这是问题所在。

    正如我在(Q1)和(Q2)中所写的、由于它从第二次开始不返回 NAK、因此我认为它不能正常进行所有读取。


    (Q5)最后、每次复位、硬(上电/断电)和软(软件复位)后、您是否看到"第一次读取错误"? 我只是想确保我了解问题的范围。

    有。 如果进行软复位、它每次都读取零。 我还没有经常执行硬复位、但是每次都读0。


    我猜测、如果您在读取测量值时未插入适当的等待、则会读取上一次测量的结果。 如果您以一秒的间隔进行测量、它将读取一秒前的测量值、如果您以一分钟的间隔进行测量、它将读取一分钟前的测量值。
    我还没有验证这一点。

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

    Manabu-San,

    谢谢您的澄清。 我想您在这里的见解是正确的、这并不是真正的"第一次读取就很糟糕"问题、而是该器件在没有足够的等待时间的情况下不是 NACK、从而返回之前转换过的数据(在第一次读取的情况下为0x0)。 因此、在写入命令和6字节读取之间必须等待适当的15ms (无论是通过重复启动还是两个单独的 I2C 事务完成)。

    我今天将尝试自行验证这一点、如果 HDC3020在数据表显示时确实不是 NACK、我们应该需要修改数据表。 我将向您介绍我发现的最新情况。

    谢谢你

    - Alex Thompson。

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

    Manabu-San,

    我想向您通报我对此问题的调查结果。 我能够验证您看到的行为、我确实认为这是 HDC3020的错误。 我需要更新 HDC3020数据表、以反映数据未就绪时器件不会 NACK。

    该范围屏幕截图展示了第一次读取、无需在0x2400命令和6字节读取之间进行适当等待。 如您所见、对于温度和 RH、该器件均读取为0x00。您也可以在此图中看到、尽管该器件报告了垃圾数据、但它仍然是 ACK。

    接下来、我使用相同的时序运行相同的命令并获得良好的数据。 我们知道转换时间不够、因此该数据很可能来自上一次转换尝试。

    最后、这是在下电上电后以适当的等待时间读取的6字节、证明只要等待时间足以完成转换、传感器就会正确读取。

    感谢您帮助识别此问题、这将使我们能够帮助遇到此问题的其他客户。

    此致

    - Alex Thompson