盛思瑞CO2传感器STC31-C-R3读数据错误,百思不解。

[复制链接]
1681|14
Aist2018 发表于 2025-9-17 13:18 | 显示全部楼层 |阅读模式
本帖最后由 Aist2018 于 2025-9-17 14:23 编辑

这是CRC函数:uint8_t sensirion_i2c_generate_crc(const uint8_t* in, uint16_t count) {
    uint16_t current_byte;
    uint8_t crc = CRC8_INIT;
    uint8_t crc_bit;

    /* calculates 8-Bit checksum with given polynomial */
    for (current_byte = 0; current_byte < count; ++current_byte) {
        crc ^= (in[current_byte]);
        for (crc_bit = 8; crc_bit > 0; --crc_bit) {
            if (crc & 0x80)
                crc = (crc << 1) ^ CRC8_POLYNOMIAL;
            else
                crc = (crc << 1);
        }
    }
    return crc;
}     uint8_t buf[2] = {0x00, 0x11};   #define CRC8_POLYNOMIAL 0x31
#define CRC8_INIT 0xFF
#define CRC8_LEN 1  crc_test = sensirion_i2c_generate_crc((uint8_t*)&buf[0],2);                                                                                                                                                                                                                                                               下面是发指令代码:              iic_Start();
                // 1. Write command phase (use write address 0x28)
                iic_SendData(0x52); // Slave write address (0x29 >> 1 = 0x14? Or check datasheet for correct write address)
                iic_Wait_Ack();
                iic_SendData(0x36); // Command byte 3
                iic_Wait_Ack();
                iic_SendData(0x15); // Argument byte 1
                iic_Wait_Ack();
                iic_SendData(0x00); // Argument byte 2
                iic_Wait_Ack();
                iic_SendData(0x11); // Argument byte 3
                                                          iic_Wait_Ack();
                                                          iic_SendData(0xf3); // Argument byte 3
                                                                iic_Wait_Ack();
                                                                iic_Stop();
                                                                delay_100us(100);   出现的错误现象是:iic_SendData(0xf3);就会通讯失败,注意0xF3是CRC计算值, 但是如果任意发一个CRC字节,不是计算的0xf3结果, 任意一个。比如:0xfd, 或者0x31,这时虽然下面的读数据失败,但是通讯并没有死亡。再后面的读product id指令还能读到结果。 但是如果发的是函数计算的0xf3作为CRC字节发送,通讯就死亡。后面读product id也失败了。为什么发的是正确的CRC反而导致通讯死亡呢?

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

×
 楼主| Aist2018 发表于 2025-9-17 13:26 | 显示全部楼层
有人用过盛思瑞CO2传感器STC31-C-R3吗?它的36 15 00 11指令CRC不就是0xf3吗?
 楼主| Aist2018 发表于 2025-9-17 14:05 | 显示全部楼层
好像不是CRC的问题,这是禁用CRC的代码,下面设置气体模式一段加上读product id都失败,通讯彻底失败,注释设置气体模式那一段下面读product id还可以读                


iic_Init();
                delay_100us(140);


                iic_Start();
                // 软复位
                iic_SendData(0x52); // Slave write address (0x29 >> 1 = 0x14? Or check datasheet for correct write address)
                iic_Wait_Ack();
                iic_SendData(0x06); // Command byte 1
                iic_Wait_Ack();
                delay_100us(150);   


                iic_Start();
                // 这是禁用CRC
                iic_SendData(0x52); // Slave write address (0x29 >> 1 = 0x14? Or check datasheet for correct write address)
                iic_Wait_Ack();
                iic_SendData(0x37); // Command byte 1
                iic_Wait_Ack();
                iic_SendData(0x68); // Command byte 2
                iic_Wait_Ack();
       
               
                iic_Start();
                // 自检
                iic_SendData(0x52); // Slave write address (0x29 >> 1 = 0x14? Or check datasheet for correct write address)
                iic_Wait_Ack();
                iic_SendData(0x36); // Command byte 3
                iic_Wait_Ack();
                iic_SendData(0x5B); // Argument byte 1
                iic_Wait_Ack();
                delay_100us(220);
                iic_Start(); // Repeated start if required by sensor
                iic_SendData(0x53); // Read address again
                iic_Wait_Ack();
                GasConcentrationByte1 = iic_ReadData();
                iic_Ack(); // ACK after first byte
                GasConcentrationByte2 = iic_ReadData();
                iic_NAck();
                iic_Stop(); // Stop condition after all reads


                //----------------------------  这一段加上下面读product id都失败,通讯彻底失败,注释这一段气体模式下面读product id还可以读
                      iic_Start();
                // 这是设置气体模式
                iic_SendData(0x52); // Slave write address (0x29 >> 1 = 0x14
                iic_Wait_Ack();
                iic_SendData(0x36); // Command byte 3
                iic_Wait_Ack();
                iic_SendData(0x15); // Argument byte 1
                iic_Wait_Ack();
                iic_SendData(0x00); // Argument byte 2
                iic_Wait_Ack();
                iic_SendData(0x11); // Argument byte 3
                  iic_Wait_Ack();
                delay_100us(200);   //----------------  这个气体模式按手册写的, 不能加再这里吗?
                                                               
               
while (1)         
{  
                // 1. Write command phase (use write address 0x28)
               iic_Start();
                iic_SendData(0x52); // Slave write address (0x29 >> 1 = 0x14? Or check datasheet for correct write address)
                iic_Wait_Ack();
                iic_SendData(0x36); // Command byte 4
                iic_Wait_Ack();
                iic_SendData(0x39); // Argument byte 4
                iic_Wait_Ack();
         
                delay_100us(1200);               
                // 2. Read da phase (restart with read address)
                iic_Start(); // Repeated start
                iic_SendData(0x53); // Slave read address (0x28 | 0x01 = 0x29 if 0x28 is write address)
                iic_Wait_Ack();
                // Read Gas Concentration (2 bytes)
                GasConcentrationByte1 = iic_ReadData();
                iic_Ack(); // ACK after first byte
                GasConcentrationByte2 = iic_ReadData();
                  iic_Ack();
                ReservedByte1 = iic_ReadData();
                iic_Ack();
                ReservedByte1 = iic_ReadData();
                iic_NAck();
                iic_Stop(); // Stop condition after all reads


                delay_100us(10);       

               
                iic_Start();
                // 读取product id
                iic_SendData(0x52); // Slave write address (0x29 >> 1 = 0x14? Or check datasheet for correct write address)
                iic_Wait_Ack();
                iic_SendData(0x36); // Command byte 3
                iic_Wait_Ack();
                iic_SendData(0x7C); // Argument byte 1
                iic_Wait_Ack();
                                                               
                iic_Start();
                iic_SendData(0x52); // Slave write address (0x29 >> 1 = 0x14? Or check datasheet for correct write address)
                iic_Wait_Ack();
                iic_SendData(0xE1); // Argument byte 2
                iic_Wait_Ack();
                iic_SendData(0x02); // Argument byte 3
                iic_Wait_Ack();
                delay_100us(1000);
                iic_Start(); // Repeated start
                iic_SendData(0x53);
                iic_Wait_Ack();
                product1 = iic_ReadData();
                iic_Ack(); // ACK after first byte
                product2 = iic_ReadData();
                iic_Ack(); //
                ReservedByte1 = iic_ReadData();
                iic_Ack();
                ReservedByte1 = iic_ReadData();
                iic_NAck();
                iic_Stop();               
               


 楼主| Aist2018 发表于 2025-9-17 14:16 | 显示全部楼层
就是这段气体设置:                      iic_Start();
                // 1. Write command phase (use write address 0x28)
                iic_SendData(0x52); // Slave write address (0x29 >> 1 = 0x14? Or check datasheet for correct write address)
                iic_Wait_Ack();
                iic_SendData(0x36); // Command byte 3
                iic_Wait_Ack();
                iic_SendData(0x15); // Argument byte 1
                iic_Wait_Ack();
                iic_SendData(0x00); // Argument byte 2
                iic_Wait_Ack();
                iic_SendData(0x11); // Argument byte 3
                                                          iic_Wait_Ack();     一运行通讯死机,注释掉下面的读product id还能读出来。
 楼主| Aist2018 发表于 2025-9-17 14:22 | 显示全部楼层
dffzh 发表于 2025-9-17 14:25 | 显示全部楼层
Aist2018 发表于 2025-9-17 14:16
就是这段气体设置:                      iic_Start();
                // 1. Write command phase (use write a ...

MCU和CO2通过I2C通信?CO2传感器的驱动代码直接问厂家要一下参考看看,这样效率比较快吧。
 楼主| Aist2018 发表于 2025-9-17 14:27 | 显示全部楼层
本帖最后由 Aist2018 于 2025-9-17 14:32 编辑

但是如果使用CRC,  iic_Start();
                // 1. Write command phase (use write address 0x28)
                iic_SendData(0x52); // Slave write address (0x29 >> 1 = 0x14? Or check datasheet for correct write address)
                iic_Wait_Ack();
                iic_SendData(0x36); // Command byte 3
                iic_Wait_Ack();
                iic_SendData(0x15); // Argument byte 1
                iic_Wait_Ack();
                iic_SendData(0x00); // Argument byte 2
                iic_Wait_Ack();
                iic_SendData(0x11); // Argument byte 3
                                                          iic_Wait_Ack();     iic_SendData(0xfd); // 注意这里不发0xf3,CRC字段随便发个数据,后面的读product id也不会死掉,还能读出来
                                                          iic_Wait_Ack();   
 楼主| Aist2018 发表于 2025-9-17 14:29 | 显示全部楼层
就是参考厂家的STM32的例程时序写的软件I2C。我的是stc32g单片机

评论

按我经验,驱动代码里使用的delay_100us尝试改大一点试试。  发表于 2025-9-17 14:40
用的是软件模拟I2C吧?那估计是因为两种单片机所用的主频不一样导致模拟I2C驱动里的延时时间不一样引起的,可以看下。  发表于 2025-9-17 14:39
 楼主| Aist2018 发表于 2025-9-17 14:30 | 显示全部楼层
盛思瑞CO2传感器STC31-C-R3的指令全是I2C下发。没人用过盛思瑞CO2传感器STC31-C-R3吗?
 楼主| Aist2018 发表于 2025-9-17 15:40 | 显示全部楼层
是否还需要apply state的指令呢?在设置模式后面?
 楼主| Aist2018 发表于 2025-9-17 15:54 | 显示全部楼层
不过看传感器例程里那个STM32例程就没有apply state。我按着那个例程和手册写的代码。没人用过盛思瑞CO2传感器STC31-C-R3吗?
玄德 发表于 2025-9-18 12:00 | 显示全部楼层

1、看波形,确定你的Start、send、wait ACK 、stop 时序是正确的。
2、把手册发出来,别人不知道命令序列究竟是咋样规定的。

yueguang3048 发表于 2025-9-18 13:31 | 显示全部楼层
本帖最后由 yueguang3048 于 2025-9-18 13:37 编辑

看了下原厂的资料,其中一个例程主要就下面几个操作

主函数
{
  • 读ID    0x367c
  • 设置量程和精度    0x3615
  • 设置滤波       0x3fc8
  • 获取数据     0x3639
}
=============解决手段==================
1.先禁止CRC进行调试,调试成功后再加上CRC
2.逻辑分析仪看下你发送的数据是否是对的
3.降低你的IIC速率
3.打印一下自检后的数值,看看是什么在报错
4.可以尝试关闭自检,你的软复位少了0x00  只写了个0x06


CHIP  id 可以读出来说明IIC读写是没大问题的,猜测是这个“自检老小子”在捣鬼。




编不下去了...








本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

×
您需要登录后才可以回帖 登录 | 注册

本版积分规则

17

主题

90

帖子

0

粉丝
快速回复 在线客服 返回列表 返回顶部