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.

[参考译文] CC2640R2F:无法从 SCD30 I2C 传感器读取数据

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

https://e2e.ti.com/support/wireless-connectivity/bluetooth-group/bluetooth/f/bluetooth-forum/1040067/cc2640r2f-cannot-read-data-from-scd30-i2c-sensor

器件型号:CC2640R2F
Thread 中讨论的其他器件:CC2640SYSBIOS

你好。 从 Sensirion SCD30 I2C 传感器读取任何数据时遇到问题。  使用 i2ctmp 示例和 I2C.h 文件参考中的示例、 我已经成功连接 了一个 SHT30传感器和 CCS811传感器。  但是、我很难对 SCD30传感器执行相同的操作。

例如、 要读取 固件版本、我首先在  第一个 I2C 事务中发送"读取固件"命令0xD100、然后在第二个事务中读取2个字节(因为 SCD30不支持重复启动条件)。  
但是、我 每次都会得到不正确的数据:  

我已经使用 Arduino 测试了相同的传感器、它在那里工作正常。

我的问题:

 Sensirion SCD30接口说明中指出:

最大 I2C 速度为100kHz、主器件必须支持时钟扩展。 Sensirion 建议以50kHz 或更低的波特率运行 SCD30。 写入帧和读取帧的时钟拉伸周期为30ms、但是、由于内部校准过程、最大时钟拉伸可达150ms、每天一次。 有关 I2C 协议的详细信息,请参阅 NXP I2C-bus 说明1。 SCD30不支持重复起始条件。 时钟拉伸是启动微控制器所必需的、并且可能在每次 ACK 前发生。 需要根据 NXP 规范实现 I2C 主时钟扩展。 启动时间< 2s

在时钟拉伸方面、我是否需要更改代码中的任何内容、例如更改任何时钟拉伸限制? 对于 CC2640的时钟扩展、我找不到任何东西。

否则、您还有其他建议吗?

我的代码以蓝色显示(仅用于读取固件版本):

/*

*版权所有(c) 2016-2017、德州仪器(TI)公司
*保留所有权利。
*
*以源代码和二进制形式重新分发和使用、有无
*如果满足以下条件、则允许进行修改
符合*:
*
**源代码的重新分发必须保留上述版权
*注意、此条件列表和以下免责声明。
*
**二进制形式的再发行必须复制上述版权
*请注意、中的此条件列表和以下免责声明
*随分发提供的文档和/或其他材料。
*
**德州仪器公司的名称和名称均不相同
*其贡献者可用于认可或推广衍生产品
*未经特定的事先书面许可。
*
*本软件由版权所有者和贡献者"按原样"提供
*以及任何明示或暗示的保证、包括但不限于:
*特定适销性和适用性的隐含保证
*不承认目的。 在任何情况下、版权所有者不得或
*派遣国应对任何直接、间接、偶然、特殊、
*典型或必然的损害(包括但不限于
*采购替代货物或服务;丧失使用、数据或利润;
*或业务中断)、无论原因是什么以及任何责任理论、
*无论是合同、严格责任还是侵权行为(包括疏忽或)
*否则)因使用本软件而以任何方式产生、
*即使被告知可能会发生此类损坏。
*

/*
*==== i2ctmp007.c ===
*
#include
#include
#include

/*驱动程序头文件*/
#include
#include
#include

/* BIOS 模块标题*/
#include
#include
#include
#include
#include
#include

/*示例/板头文件*/
#include "Board.h"

#define TASKSTACKSIZE 640

#define TMP007_DIE_TEMP 0x0001 /*裸片温度结果寄存器*
#define TMP007_obj_TEMP 0x0003 //对象温度结果寄存器*/

静态 Display_Handle 显示;

uint8_t crc8scd30 (void const*输入、size_t len);

/*
*==== mainThread ====
*
void * mainThread (void * arg0)

unsigned int i;
//uint16_t 温度;
uint8_t txBuffer[5];
uint8_t rxBuffer[18];
I2C_Handle i2c;
I2C_Params i2cParams;
I2C_Transaction i2cTransaction;

bool status = true;

//SCD30
静态常量 uint8_t SCD30_I2C_address = 0x61;
//浮点 SCD30_CO2_ppm、SCD30_temperature、SCD30_hum湿度;
unsigned int tempU32;

// int16_t err;
// uint16_t interval_in_seconds = 2;
// uint8_t crc_input[2]= 0;
// uint8_t crc_result[2]= 0;

/*调用驱动程序初始化函数*/
display_init();
GPIO_init();
I2C_init();

/*配置 LED 引脚*/
GPIO_setConfig (Board_GPIO_LED0、GPIO_CFG_OUT_STD | GPIO_CFG_OUT_LOW);

/*打开主机显示屏以输出*/
Display = Display_open (Display_Type_UART、NULL);
if (display =NULL){
while (1);

/*打开用户 LED */
GPIO_WRITE (Board_GPIO_LED0、Board_GPIO_LED_ON);
display_printf (display、0、0、"开始 i2c SCD30测试\n");

/*创建 I2C 以供使用*/
I2C_Params_init (&i2cParams);
i2cParams.bitrate = I2C_100kHz;// SCD30的最大 I2C 速度为100kHz;
I2C = I2C_open (Board_I2C_TMP、&i2cParams);
if (i2c == NULL){
Display_printf (display、0、0、"Error Initializing I2C\n");
while (1);

否则{
display_printf (display、0、0、"I2C initialized!\n"\});

//SCD30
/*重置传感器*/
Task_sleep (2000 *(1000 / Clock_tickPeriod));//暂停5000ms

Display_printf (display、0、0、"Reset sensor \n");
TxBuffer[0]= 0xD3;//开始命令= 0xD304
TxBuffer[1]= 0x04;
i2cTransaction.slaveAddress = SCD30_I2C_address;//默认从地址
i2cTransaction.writeBuf = txBuffer;
i2cTransaction.writeCount = 2;
i2cTransaction.readBuf =空;
i2cTransaction.ReadCount = 0;
STATUS = I2C_TRANSF传输(i2c、&i2cTransaction);
如果(status == false){
// I2C 传输失败

/*读取固件版本*/
display_printf (display、0、0、"读取固件版本\n");

//写入命令
TxBuffer[0]= 0xD1;//开始命令= 0xD100
TxBuffer[1]= 0x00;
i2cTransaction.slaveAddress = SCD30_I2C_address;//默认从地址
i2cTransaction.writeBuf = txBuffer;
i2cTransaction.writeCount = 2;
i2cTransaction.readBuf =空;
i2cTransaction.ReadCount = 0;
I2C_transfer (i2c、&i2cTransaction);

//读取固件版本
i2cTransaction.slaveAddress = SCD30_I2C_address;//默认从地址
i2cTransaction.writeBuf =空;
i2cTransaction.writeCount = 0;
i2cTransaction.readBuf = rxBuffer;
i2cTransaction.ReadCount = 2;
I2C_transfer (i2c、&i2cTransaction);
Display_printf (display、0、0、"固件版本:%x、%x \n"、rxBuffer[0]、rxBuffer[1]);

/*已取消初始化 I2C */
I2C_Close (i2c);
display_printf (display、0、0、"I2C closed!\n"\});

返回(空);

//SCD30功能
uint8_t const table []={
0x00、0x31、0x62、0x53、0xc4、 0xf5、0xa6、0x97、0xb9、0x88、 0xdb、0xEA、0x7d、
0x4c、0x1f、0x2e、0x43、0x72、 0x21、0x10、0x87、0xb6、0xe5、 0xd4、0xfa、0xcb、
0x98、0xa9、0x3E、0x0F、0x5c、 0x6d、0x86、0xb7、0xe4、0xd5、 0x42、0x73、0x20、
0x11、0x3f、0x0E、0x5d、0x6c、 0xfb、0xca、0x99、0xa8、0xc5、 0xf4、0xa7、0x96、
0x01、0x30、0x63、0x52、0x7c、 0x4d、0x1E、0x2F、0xb8、0x89、 0xda、0xeb、0x3D、
0x0C、0x5f、0x6e、0xf9、0xc8、 0x9b、0xAA、0x84、0xb5、0xe6、 0xd7、0x40、0x71、
0x22、0x13、0x7E、0x4f、0x1c、 0x2D、0xBA、0x8b、0xd8、0xe9、 0xc7、0xf6、0xA5、
0x94、0x03、0x32、0x61、0x50、 0xbb、0x8a、0xd9、0xe8、0x7f、 0x4e、0x1d、0x2C、
0x02、0x33、0x60、0x51、0xc6、 0xf7、0xa4、0x95、0xf8、0xc9、 0x9a、0xab、0x3c、
0x0D、0x5e、0x6f、0x41、0x70、 0x23、0x12、0x85、0xb4、0xe7、 0xd6、0x7a、0x4b、
0x18、0x29、0xbe、0x8F、0xdc、 0xED、0xc3、0xF2、0xa1、0x90、 0x07、0x36、0x65、
0x54、0x39、0x08、0x5b、0x6A、 0xFD、0xcc、0x9f、0xae、0x80、 0xb1、0xe2、0xd3、
0x44、0x75、0x26、0x17、0xFC、 0xcd、0x9e、0xaf、0x38、0x09、 0x5a、0x6b、0x45、
0x74、0x27、0x16、0x81、0xb0、 0xe3、0xd2、0xbf、0x8e、0xdd、 0xEC、0x7B、0x4a、
0x19、0x28、0x06、0x37、0x64、 0x55、0xC2、0xf3、0xa0、0x91、 0x47、0x76、0x25、
0x14、0x83、0xb2、0xe1、0xd0、 0xFE、0xCF、0x9C、0xAD、0x3a、 0x0B、0x58、0x69、
0x04、0x35、0x66、0x57、0xc0、 0xF1、0xa2、0x93、0xbd、0x8c、 0xdf、0xee、0x79、
0x48、0x1b、0x2a、0xc1、0xf0、 0xa3、0x92、0x05、0x34、0x67、 0x56、0x78、0x49、
0x1a、0x2b、0xbc、0x8d、0xde、 0xef、0x82、0xb3、0xe0、0xD1、 0x46、0x77、0x24、
0x15、0x3b、0x0a、0x59、0x68、 0xFF、0xce、0x9d、0xac
};

uint8_t crc8scd30 (void const*输入、size_t len){
uint8_t CRC = 0xff;
uint8_t const* data =输入;
if (数据==空)
返回 CRC;
CRC &= 0xff;
while (len-)
CRC = table[CRC ^*数据++];
返回 CRC;

 

感谢你的帮助。

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

    您好!

    由于您在 I2C 上收到响应、因此似乎您已正确设置 I2C 外设。 您是否检查了响应的字节序? 预期响应与您正在阅读的响应之间有何差异?

    此致、

    Daniel

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

    感谢您的回复。  

    预期响应为 :0xD100

    收到的响应为:0xBEBE

    我不确定我还应该如何检查响应的字节序。

    我是否需要考虑有关时钟的任何注意事项?

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

    对于时钟、我没有其他考虑因素可以考虑。 软件中无需任何器件即可支持时钟扩展。

    您是否使用示波器或逻辑分析仪查看了信号、以确保发送的信号与传感器的预期相符? 您是否曾尝试使用调试器查看 I2C 寄存器、以确保按照您的意愿传输和打印这些值?

    此致、

    Daniel

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    [引用 userid="13116" URL"~/support/wireless-connectivity/bluetooth-group/bluetooth/f/bluetooth-forum/1040067/cc2640r2f-cannot-read-data-from-scd30-i2c-sensor/3860580 #3860580"]您是否使用示波器或逻辑分析仪查看了该信号、以确保发送的信号与传感器期望的信号相匹配?

    现在还不是、我明天可以回到实验室时就会这样做。

    [引用 userid="13116" URL"~/support/wireless-connectivity/bluetooth-group/bluetooth/f/bluetooth-forum/1040067/cc2640r2f-cannot-read-data-from-scd30-i2c-sensor/3860580 #3860580"]是否尝试使用调试器查看 I2C 寄存器以确保按您的意愿传输和打印值?

    我已经尝试过。  下面是当我尝试向器件写入 START 命令"0xD100"时 I2C0寄存器的屏幕截图。  

    从地址0x61似乎已更新、因为 MSA 显示 0x000000C2。

    但是、主数据寄存器 MDR 显示 为0x00000000、因此看起来实际上没有发送任何内容。

    我是否看到了错误的寄存器?


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

    显示0x61的 MSA 正确、因为位0是接收或发送位。 由于它为0、因此处于"向从器件发送数据"模式。 向左移动一位的0x61位为0xC2。 在 I2C_TRANSFCTION 函数之后、MDR 可能不会更新。

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

    在 I2C_transfer 函数之后添加了另一个断点、MDR 仍然未更新。

    但是、当我执行另一个事务从从从器件读取时、MDR 会更新:

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

    感谢您的更新。 我认为调试的最佳下一步是使用逻辑分析仪来查看 I2C 输出是否是您的传感器所期望的。

    此致、

    Daniel

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

    我将尽快更新、 感谢您迄今提供的帮助。

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

    在检查示波器后 、我意识到在调用软复位函数后需要大于2秒的延迟、否则 I2C 传输将不会发生。 似乎软复位也被视为启动、数据表中指出、需要大于2秒的延迟。

    一切都在进行中、谢谢 Daniel!