秦天qintian0303 发表于 2022-11-5 19:10

【英飞凌XENSIV™ PAS CO2传感器】传感器驱动设计

<p><strong>一、准备工作</strong></p>

<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;硬件方面是在进行N32G430测评时做的EVA板上直接预留了,正好用N32作为主控进行通信。</p>

<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;接下来就要进行软件驱动的设计,了解测量的基本结构。</p>

<p><strong>二、软件结构</strong></p>

<p><strong>1、XENSIVTM PAS CO2开始测量的基本操作</strong></p>

<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;检查初始化是否正确,可以通过检查传感器状态寄存器来完成。</p>

<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;在开始测量之前,建议检查和设置压力补偿,可以通过外部的压力传感器数据进行写入补偿,寄存器的默认压力设置是1015hpa。</p>

<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;使用连续测量模式时,可以预先在两个测量周期配置寄存器中定义测量周期,注意配置完测量模式后,都会触发测量序列。</p>

<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;通过读取测量状态寄存器,可以检查测量序列是否完成,从而在二氧化碳浓度结果寄存器中是否有新的二氧化碳浓度值可用。</p>

<p><strong>2、了解具体的寄存器参数</strong></p>

<p><strong>1)PROD_ID</strong></p>

<p>地址:0x00</p>

<p>默认值:0x4F</p>

<p>注释:该寄存器显示设备的产品和版本ID,对该寄存器的写访问被忽略,由于修订版本的不同,该数据有可能不同,所以慎用。</p>

<p><strong>2)SENS_STS</strong></p>

<p>地址:0x01</p>

<p>默认值:0xC0</p>

<p>注释:这个寄存器显示和控制传感器的状态,对该寄存器只读位的写访问被忽略。</p>

<table style="table-layout: auto">
        <tbody>
                <tr>
                        <td>
                        <p>Field</p>
                        </td>
                        <td>
                        <p>Bits</p>
                        </td>
                        <td>
                        <p>Description</p>
                        </td>
                </tr>
                <tr>
                        <td>
                        <p>SEN_RDY</p>
                        </td>
                        <td>
                        <p>7</p>
                        </td>
                        <td>
                        <p>Sensor ready bit 该位表示上电复位后传感器的初始化是否已正确执行。 0:传感器未正确初始化。 1b:传感器已正确初始化。</p>
                        </td>
                </tr>
                <tr>
                        <td>
                        <p>PWM_DIS_ST</p>
                        </td>
                        <td>
                        <p>6</p>
                        </td>
                        <td>
                        <p>PWM_DIS pin status 该位表示在引脚PWM_DIS上读取的级别。 0:在引脚PWM_DIS读取低电平。 1:在引脚PWM_DIS读取高电平。 注意:这个位在引脚PWM_DIS的每次转换时都会更新。</p>
                        </td>
                </tr>
                <tr>
                        <td>
                        <p>ORTMP</p>
                        </td>
                        <td>
                        <p>5</p>
                        </td>
                        <td>
                        <p>Out-of-range temperature error bit (sticky bit) 该位表示是否检测到温度超出指定有效范围的情况。 0:没有发生错误。 1:出现错误。 通过设置SENS_STS.ORTMP_CLR清除此位。</p>
                        </td>
                </tr>
                <tr>
                        <td>
                        <p>ORVS</p>
                        </td>
                        <td>
                        <p>4</p>
                        </td>
                        <td>
                        <p>Out-of-range VDD12V error bit (sticky bit) 该位表示是否检测到VDD12V超出指定有效范围的条件。 0:没有发生错误。 1:出现错误。 通过设置位SENS_STS.ORVS_CLR清除此位。</p>
                        </td>
                </tr>
                <tr>
                        <td>
                        <p>ICCER</p>
                        </td>
                        <td>
                        <p>3</p>
                        </td>
                        <td>
                        <p>Communication error notification bit (sticky bit) 该位表示串行通信接口是否收到了无效的命令。 0:没有收到无效的命令。 1:收到无效的命令。 通过设置SENS_STS.ICCER_CLR清除此位。</p>
                        </td>
                </tr>
                <tr>
                        <td>
                        <p>ORTMP_CLR</p>
                        </td>
                        <td>
                        <p>2</p>
                        </td>
                        <td>
                        <p>Out-of-range temperature error clear bit 写入1清除SENS_STS.ORTMP。 这个位被读回为0</p>
                        </td>
                </tr>
                <tr>
                        <td>
                        <p>ORVS_CLR</p>
                        </td>
                        <td>
                        <p>1</p>
                        </td>
                        <td>
                        <p>Out-of-range VDD12V error clear bit 写入1清除SENS_STS.ORVS。 这个位被读回为0</p>
                        </td>
                </tr>
                <tr>
                        <td>
                        <p>ICCER_CLR</p>
                        </td>
                        <td>
                        <p>0</p>
                        </td>
                        <td>
                        <p>Communication error clear bit 写入1清除SENS_STS.ICCER。 这个位被读回为0</p>
                        </td>
                </tr>
        </tbody>
</table>

<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;可以说这个状态寄存器是最重要的,在开机时就需要进行读取和设计。</p>

<p><strong>3)MEAS_RATE_H与MEAS_RATE_L</strong></p>

<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;寄存器MEAS_RATE_H和MEAS_RATE_L定义连续模式中使用的测量周期(1位= 1 s)。</p>

<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;例如:0FFFH以上的值被视为等于FFFH (4095 s), 0005H以下的值被视为等于0005 h (5 s),将一个无效的值写入此字段将产生一个通信错误(SENS_STS.ICCER)。</p>

<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;注意:当写入到MEAS_RATE_H和MEAS_RATE_L时,设备不会立即考虑新值。它在下一次从空闲模式到连续模式的转换时被内部锁存。</p>

<p>&nbsp;</p>

<p>寄存器名称:MEAS_RATE_H</p>

<p>地址:0x02</p>

<p>默认值:0x00</p>

<p>注释:这个寄存器显示和控制传感器的状态,对该寄存器只读位的写访问被忽略。</p>

<table style="table-layout: auto">
        <tbody>
                <tr>
                        <td>
                        <p>Field</p>
                        </td>
                        <td>
                        <p>Bits</p>
                        </td>
                        <td>
                        <p>Description</p>
                        </td>
                </tr>
                <tr>
                        <td>
                        <p>0</p>
                        </td>
                        <td>
                        <p>7:4</p>
                        </td>
                        <td>
                        <p>这个位域应该用0H来写</p>
                        </td>
                </tr>
                <tr>
                        <td>
                        <p>VAL</p>
                        </td>
                        <td>
                        <p>3:0</p>
                        </td>
                        <td>
                        <p>连续模式下测量周期的MSB 该值与位域MEAS_RATE_L的拼接定义了连续模式下的测量周期。</p>
                        </td>
                </tr>
        </tbody>
</table>

<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;注意:0x0f以上的值保留,将一个无效的值写入此字段将产生一个通信错误(SENS_STS.ICCER),并将位域设置为0x0f。</p>

<p>&nbsp;</p>

<p>寄存器名称:MEAS_RATE_L</p>

<p>地址:0x03</p>

<p>默认值:0x3C</p>

<p>注释:连续模式下测量周期的LSB。</p>

<p>备注:0x00 ~ 0x04为保留值,将一个无效的值写入此字段将产生一个通信错误(SENS_STS.ICCER),并将位域设置为0x05。</p>

<p><strong>4)MEAS_CFG</strong></p>

<p>地址:0x04</p>

<p>默认值:0x24</p>

<p>注释:测量模式配置寄存器,定义了设备的操作设置。</p>

<table style="table-layout: auto">
        <tbody>
                <tr>
                        <td>
                        <p>Field</p>
                        </td>
                        <td>
                        <p>Bits</p>
                        </td>
                        <td>
                        <p>Description</p>
                        </td>
                </tr>
                <tr>
                        <td>
                        <p>Res</p>
                        </td>
                        <td>
                        <p>7:6</p>
                        </td>
                        <td>
                        <p>这个位域应该写入00b。</p>
                        </td>
                </tr>
                <tr>
                        <td>
                        <p>PWM_OUTEN</p>
                        </td>
                        <td>
                        <p>5</p>
                        </td>
                        <td>
                        <p>PWM output software enable bit 0:软件关闭PWM输出。 1:软件开启PWM输出。 注1:引脚PWM的实际状态取决于两者 MEAS_CFG.PWM_OUTEN和引脚PWM_DIS。 注2:该位自动设置在PWM_DIS引脚的高到低。</p>
                        </td>
                </tr>
                <tr>
                        <td>
                        <p>PWM_MODE</p>
                        </td>
                        <td>
                        <p>4</p>
                        </td>
                        <td>
                        <p>PWM mode configuration 0: PWM单脉冲模式。 1: PWM连续脉冲模式。</p>
                        </td>
                </tr>
                <tr>
                        <td>
                        <p>BOC_CFG</p>
                        </td>
                        <td>
                        <p>3:2</p>
                        </td>
                        <td>
                        <p>Baseline offset compensation configuration 00b:禁用自动基线偏移补偿(ABOC)。没有抵消补偿发生。 01b: ABOC启用。偏移量在每次BOC计算时定期更新。 注意:在单发模式下,ABOC校正因子被应用,但ABOC方案未激活且未更新。 10b:强制补偿。 注意:强制补偿完成后,设备自动将自身重新配置为ABOC (MEAS_CFG.BOC_CFG = 01b)。 11b:保留。</p>
                        </td>
                </tr>
                <tr>
                        <td>
                        <p>OP_MODE</p>
                        </td>
                        <td>
                        <p>1:0</p>
                        </td>
                        <td>
                        <p>传感器操作模式 00b:空闲模式。 01b:启用单发模式。将01b写入此字段会触发单个测量序列。该字段由固件自动重置。 10b:开启连续模式。 11b:保留(作为00b)。</p>
                        </td>
                </tr>
        </tbody>
</table>

<p><strong>5)CO2PPM_H与CO2PPM_L</strong></p>

<p>寄存器CO2PPM_H和CO2PPM_L用于显示最后一次CO2浓度测量的结果(1 bit = 1 ppm)。</p>

<p>读取寄存器CO2PPM_L清除位MEAS_STS.DRDY。</p>

<p>在读取CO2浓度值时,用户应先读取CO2PPM_H寄存器,然后读取CO2PPM_L寄存器。</p>

<p>&nbsp;</p>

<p>寄存器名称:CO2PPM_H</p>

<p>地址:0x05</p>

<p>默认值:0x00</p>

<p>注释:CO2浓度值的MSB。</p>

<p>&nbsp;</p>

<p>寄存器名称:CO2PPM_L</p>

<p>地址:0x06</p>

<p>默认值:0x00</p>

<p>注释:CO2浓度值的LSB。</p>

<p><strong>6)MEAS_STS</strong></p>

<p>地址:0x07</p>

<p>默认值:0x00</p>

<p>注释:这个寄存器显示传感器的状态信息。对该寄存器只读位的写访问被忽略。</p>

<table style="table-layout: auto">
        <tbody>
                <tr>
                        <td>
                        <p>Field</p>
                        </td>
                        <td>
                        <p>Bits</p>
                        </td>
                        <td>
                        <p>Description</p>
                        </td>
                </tr>
                <tr>
                        <td>
                        <p>0</p>
                        </td>
                        <td>
                        <p>7:6</p>
                        </td>
                        <td>
                        <p>这个位域被读取为00b。</p>
                        </td>
                </tr>
                <tr>
                        <td>
                        <p>Res</p>
                        </td>
                        <td>
                        <p>5</p>
                        </td>
                        <td>
                        <p>保留</p>
                        </td>
                </tr>
                <tr>
                        <td>
                        <p>DRDY</p>
                        </td>
                        <td>
                        <p>4</p>
                        </td>
                        <td>
                        <p>Data ready bit (sticky bit) 该位表示寄存器中是否有新数据可用(CO2PPM_H和CO2PPM_L) 0:没有新的数据。 1:表示存在未读数据。这个位设置在每个测量序列的末尾。 通过读取CO2PPM_L清除该位。</p>
                        </td>
                </tr>
                <tr>
                        <td>
                        <p>INT_STS</p>
                        </td>
                        <td>
                        <p>3</p>
                        </td>
                        <td>
                        <p>INT pin status bit 这个位指示引脚INT是否已锁存到活动状态(在报警或数据准备好的情况下)。 0:引脚INT没有锁存到活动状态。 1:引脚INT已锁存到活动状态。该位设置在每个测量序列的末尾,以防出现锁存条件。 通过设置位MEAS_STS.INT_STS_CLR清除此位。</p>
                        </td>
                </tr>
                <tr>
                        <td>
                        <p>ALARM</p>
                        </td>
                        <td>
                        <p>2</p>
                        </td>
                        <td>
                        <p>Alarm notification (sticky bit) 这个位表示是否发生了阈值违反。 0:没有违规发生。 1:违反发生。该位设置在每个测量序列的末尾,以防违反。 通过设置位MEAS_STS.ALARM_CLR清除该位。</p>
                        </td>
                </tr>
                <tr>
                        <td>
                        <p>INT_STS_CLR</p>
                        </td>
                        <td>
                        <p>1</p>
                        </td>
                        <td>
                        <p>INT pin status clear bit 用1写入这个位可以清除位MEAS_STS.INT_STS和强制引脚INT到非活动级别。 这个位被读回为0b。</p>
                        </td>
                </tr>
                <tr>
                        <td>
                        <p>ALARM_CLR</p>
                        </td>
                        <td>
                        <p>0</p>
                        </td>
                        <td>
                        <p>Alarm notification clear bit 用1写入这个位可以清除位MEAS_STS.ALARM。 这个位被读回为0b。</p>
                        </td>
                </tr>
        </tbody>
</table>

<p><strong>7)INT_CFG</strong></p>

<p>地址:0x08</p>

<p>默认值:0x11</p>

<p>注释:这个寄存器定义了引脚INT的配置。</p>

<table style="table-layout: auto">
        <tbody>
                <tr>
                        <td>
                        <p>Field</p>
                        </td>
                        <td>
                        <p>Bits</p>
                        </td>
                        <td>
                        <p>Description</p>
                        </td>
                </tr>
                <tr>
                        <td>
                        <p>0</p>
                        </td>
                        <td>
                        <p>7:5</p>
                        </td>
                        <td>
                        <p>这个位域应该用00b写。</p>
                        </td>
                </tr>
                <tr>
                        <td>
                        <p>INT_TYP</p>
                        </td>
                        <td>
                        <p>4</p>
                        </td>
                        <td>
                        <p>Pin INT electrical configuration 0b:引脚INT配置为推挽和非活动状态。 1b:引脚INT配置为推挽和活动状态。 注意: 写入此位域将使引脚INT处于非活动状态。</p>
                        </td>
                </tr>
                <tr>
                        <td>
                        <p>INT_FUNC</p>
                        </td>
                        <td>
                        <p>3:1</p>
                        </td>
                        <td>
                        <p>Pin INT function configuration 000b:引脚INT未激活。 001b:配置引脚INT为告警阈值违规通知引脚。 010b:引脚INT配置为数据就绪通知引脚。 011b:引脚INT配置为传感器繁忙通知引脚。 100b:引脚INT配置为早期测量开始通知引脚(此功能仅在连续模式下可用 MEAS_CFG.OP_MODE = 10b,否则引脚不活动)。 101 b:保留 ... 111 b:保留</p>
                        </td>
                </tr>
                <tr>
                        <td>
                        <p>ALARM_TYP</p>
                        </td>
                        <td>
                        <p>0</p>
                        </td>
                        <td>
                        <p>Alarm type configuration bit 该位域定义在违反较低或较高阈值的情况下是否发出警报。 0b:向下交叉&mdash;&mdash;将寄存器ALARM_TH_H和ALARM_TH_L的连接值定义为低阈值寄存器。 1b:向上交叉&mdash;&mdash;将寄存器ALARM_TH_H和ALARM_TH_L的连接值定义为较高阈值寄存器。</p>
                        </td>
                </tr>
        </tbody>
</table>

<p><strong>8)ALARM_TH_H与ALARM_TH_L</strong></p>

<p>地址:0x09~0x0A</p>

<p>默认值:0x00</p>

<p>注释:寄存器ALARM_TH_H和ALARM_TH_L定义用于告警违规阈值的值(1位= 1 ppm)。</p>

<p><strong>9)PRES_REF_H与PRES_REF_L</strong></p>

<p>地址:0x0B/0x0C</p>

<p>默认值:0x03/0xF7</p>

<p>注释:寄存器PRES_REF_L和PRES_REF_H用于捕获要补偿的大气压力(1位= 1 hPa),用户必须先写入PRES_REF_H,然后写入PRES_REF_L,如果不更新默认值,压力补偿实际上是无效的,为了正确操作,用户应确保所编程的压力值在设备规定的压力工作范围内,有效的工作范围是750 hPa到1150 hPa。低于750 hPa的值将被视为750 hPa,1150 hPa以上的值将被处理为1150 hPa,如果写入此范围以外的值,则位SENS_STS.ICCER被置位。</p>

<p><strong>10)CALIB_REF_H与CALIB_REF_L</strong></p>

<p>地址:0x0D/0x0E</p>

<p>默认值:0x01/0x90</p>

<p>注释:自动基线偏移补偿参考,寄存器CALIB_REF_H和CALIB_REF_L定义了用于ABOC和力校准的参考值(1bit = 1 ppm),数值必须包含在350ppm和900ppm之间。低于350 ppm的数值将被视为350 ppm,900ppm以上的值将被处理为900ppm。如果写入超出此范围的值,则位SENS_STS.ICCER被置位。</p>

<p><strong>11)SCRATCH_PAD</strong></p>

<p>地址:0x0F</p>

<p>默认值:0x00</p>

<p>注释:该寄存器为运行时的数据完整性测试提供了可读可写的地址空间。该寄存器与特定的硬件功能无关。</p>

<p><strong>12)SENS_RST</strong></p>

<p>地址:0x10</p>

<p>默认值:0x00</p>

<p>注释:该寄存器用于触发软复位。如果接收到无效的命令,位SENS_STS.ICCER被置位。</p>

<table style="table-layout: auto">
        <tbody>
                <tr>
                        <td>
                        <p>Field</p>
                        </td>
                        <td>
                        <p>Bits</p>
                        </td>
                        <td>
                        <p>Description</p>
                        </td>
                </tr>
                <tr>
                        <td>
                        <p>SRTRG</p>
                        </td>
                        <td>
                        <p>7:0</p>
                        </td>
                        <td>
                        <p>Soft reset trigger 向该字段写入A3H会触发软复位事件。 将BCH写入此字段将重置ABOC上下文。 将CFH写入此字段将立即将压力校准偏移量保存在内部非易失性存储器中。 将DFH写入此字段禁用IIR滤波器。 将FCH写入此字段将重置强制校准校正因子。 将FEH写入此字段启用IIR滤波器(默认启用)。 此位被读取为00H。</p>
                        </td>
                </tr>
        </tbody>
</table>

<p><strong>3、测试基本配置</strong></p>

<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;初始配置为连续采集,周期20s,不产生中断。</p>

<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;出现过读取的数据是65535的情况,读取数据是通过定时2s扫描MEAS_STS寄存器的Data ready bit ,如果为1则读取CO2浓度结果。目前还不太清楚为什么会出现读取结果为0xffff的情况。初步怀疑是连续测量以固定时间进行测量序列,开始进行测量序列时1s内应该是最好不要有任何操作,包括读写,有可能异常,循环扫描有可能与这块存在重叠导致异常。</p>

<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;由于口罩原因,目前还无法获取标气,头一天晚上在家测得的CO2浓度为1900ppm左右,可能是电脑房密闭的原因,且长时间在这个房间里,空气相对浑浊。无人一晚后,早上的水平在800ppm左右,不过我进来后水平基本就在1600ppm左右,这个传感器放置的位置还是有一定讲究的。</p>

<p><strong>4、驱动代码</strong></p>

<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;通过对上述寄存器的解读基本可以确定,读写寄存器基本围绕一个寄存器或者相邻两个寄存器组成的16位。</p>

<pre>
<code>/************************************宏定义************************************/
#define PasCO2_SlaveAddress               0x28
#define PasCO2_RegAddr_ID                   0x00
#define PasCO2_RegAddr_SENS_STS             0x01//状态寄存器
#define PasCO2_RegAddr_RATE_H               0x02//测量周期寄存器_高
#define PasCO2_RegAddr_RATE_L               0x03//测量周期寄存器_低
#define PasCO2_RegAddr_MEASCFG            0x04//测量配置寄存器
#define PasCO2_RegAddr_PPM_H                0x05//测量结果寄存器_高
#define PasCO2_RegAddr_PPM_L                0x06//测量结果寄存器_低
#define PasCO2_RegAddr_MEAS_STS             0x07//传感器状态寄存器
#define PasCO2_RegAddr_INTCFG               0x08//中断配置寄存器
#define PasCO2_RegAddr_ALARM_H            0x09//报警阈值寄存器_高
#define PasCO2_RegAddr_ALARM_L            0x0A//报警阈值寄存器_低
#define PasCO2_RegAddr_PRES_H               0x0B//压力补偿寄存器_高
#define PasCO2_RegAddr_PRES_L               0x0C//压力补偿寄存器_低
#define PasCO2_RegAddr_CALIB_H            0x0D//基线偏移寄存器_高
#define PasCO2_RegAddr_CALIB_L            0x0E//基线偏移寄存器_低
#define PasCO2_RegAddr_SCRATCH_PAD          0x0F//传感器状态寄存器
#define PasCO2_RegAddr_SENS_RST             0x10//复位寄存器

#define REG_SENS_STS_ICCER_CLR_POS      (0U)                                 
#define REG_SENS_STS_ICCER_CLR_MSK      (0x01U &lt;&lt; REG_SENS_STS_ICCER_CLR_POS)
#define REG_SENS_STS_ORVS_CLR_POS         (1U)                                 
#define REG_SENS_STS_ORVS_CLR_MSK         (0x01U &lt;&lt; REG_SENS_STS_ORVS_CLR_POS)
#define REG_SENS_STS_ORTMP_CLR_POS      (2U)                                 
#define REG_SENS_STS_ORTMP_CLR_MSK      (0x01U &lt;&lt; REG_SENS_STS_ORTMP_CLR_POS)
#define REG_SENS_STS_ICCER_POS            (3U)                                 
#define REG_SENS_STS_ICCER_MSK            (0x01U &lt;&lt; REG_SENS_STS_ICCER_POS)   
#define REG_SENS_STS_ORVS_POS             (4U)                                 
#define REG_SENS_STS_ORVS_MSK             (0x01U &lt;&lt; REG_SENS_STS_ORVS_POS)      
#define REG_SENS_STS_ORTMP_POS            (5U)                                 
#define REG_SENS_STS_ORTMP_MSK            (0x01U &lt;&lt; REG_SENS_STS_ORTMP_POS)   
#define REG_SENS_STS_PWM_DIS_ST_POS       (6U)                                 
#define REG_SENS_STS_PWM_DIS_ST_MSK       (0x01U &lt;&lt; REG_SENS_STS_PWM_DIS_ST_POS)
#define REG_SENS_STS_SEN_RDY_POS          (7U)                                 
#define REG_SENS_STS_SEN_RDY_MSK          (0x01U &lt;&lt; REG_SENS_STS_SEN_RDY_POS)   

/*******************************全局变量********************************/   
typedef enum
{
ERROR_NONE            = 0x00, // no error
ERROR_COM               = 0x01, // IIC通信异常
ERROR_ICC               = 0x02, // 无效指令
ERROR_ORVS            = 0x03, // 12V电压超限
ERROR_ORTMP             = 0x04, // 温度超限
ERROR_NOT_READY         = 0x05, // 未正确初始化

} Error_PasCO2;
Error_PasCO2 error_PasCO2;

typedef struct
{
uint8_t       Mode;//测量模式
uint16_t      MeasRate;//测量周期
uint16_t      AlarmTh;//报警阈值
uint16_t      PresRef;//压力补偿
uint16_t      CalibRef;//偏移补偿
}PasCO2_Config;
PasCO2_Config PasCO2Config;

typedef struct
{
uint8_t Error; //错误码
uint8_t ID;
uint16_t PPM;
}PasCO2States;//传感器状态
PasCO2States PasCO2,PasCO2Show;

/*******************************函数********************************/
void PasCO2_Init(void);
void PasCO2_GetPPM(void);
static Error_PasCO2 PasCO2_CheckCom(void);

static uint8_t PasCO2_GetOneWord(uint8_t reg);
static void PasCO2_SetOneWord(uint8_t reg,uint8_t data);
static uint16_t PasCO2_GetTwoWord(uint8_t reg);
static void PasCO2_SetTwoWord(uint8_t reg,uint16_t data);

//******************************************************************************
//* 函数名称: void PasCO2_Init(void)
//* 函数描述:
//* 输入参数:
//* 参数描述:
//* 输出参数: 无
//* 返回值    :
//******************************************************************************   
void PasCO2_Init(void)
{
uint8_t SysData;
if(PasCO2_CheckCom() == ERROR_NONE)
{
    PasCO2.ID = PasCO2_GetOneWord(PasCO2_RegAddr_ID);
    SysData = PasCO2_GetOneWord(PasCO2_RegAddr_SENS_STS);
    if ((SysData &amp; REG_SENS_STS_ICCER_MSK) != 0U)
      PasCO2.Error = ERROR_ICC;
    else if ((SysData &amp; REG_SENS_STS_ORVS_MSK) != 0U)
      PasCO2.Error = ERROR_ORVS;
    else if ((SysData &amp; REG_SENS_STS_ORTMP_MSK) != 0U)
      PasCO2.Error = ERROR_ORTMP;
    else if ((SysData &amp; REG_SENS_STS_SEN_RDY_MSK) == 0U)
      PasCO2.Error = ERROR_NOT_READY;
    else
      PasCO2.Error = ERROR_NONE;
   
}
else
{
    PasCO2.Error = ERROR_COM;
}

if(PasCO2.Error == ERROR_NONE)
{
   
    PasCO2_SetOneWord(PasCO2_RegAddr_MEASCFG,0x04);//切换到空闲模式
   
    PasCO2_SetTwoWord(PasCO2_RegAddr_RATE_H,0x0006);//测量周期20s
    PasCO2_SetTwoWord(PasCO2_RegAddr_PRES_H,0x03f6);//设置压力
    PasCO2_SetOneWord(PasCO2_RegAddr_INTCFG,0x01);//关闭外部中断
   
   
    PasCO2Config.MeasRate = PasCO2_GetTwoWord(PasCO2_RegAddr_RATE_H);
    PasCO2Config.PresRef = PasCO2_GetTwoWord(PasCO2_RegAddr_PRES_H);
    PasCO2Config.CalibRef = PasCO2_GetTwoWord(PasCO2_RegAddr_CALIB_H);
   
    PasCO2_SetOneWord(PasCO2_RegAddr_MEASCFG,0x06);//切换到连续采集模式

}
}

//******************************************************************************
//* 函数名称: PasCO2_GetPPM(void)
//* 函数描述: 获取CO2浓度值
//* 输入参数:
//* 参数描述:
//* 输出参数: 无
//* 返回值    :
//******************************************************************************
void PasCO2_GetPPM(void)
{
uint8_t MEAS_STS = 0;
MEAS_STS = PasCO2_GetOneWord(PasCO2_RegAddr_MEAS_STS);
if((MEAS_STS&amp;0x10) == 0x10)
{
    delay_ms(30);
    PasCO2.PPM = PasCO2_GetTwoWord(PasCO2_RegAddr_PPM_H);
    MEAS_STS = 0;
}
}

//******************************************************************************
//* 函数名称: PasCO2_CheckCom(void)
//* 函数描述:
//* 输入参数:
//* 参数描述:
//* 输出参数: 无
//* 返回值    :
//******************************************************************************
static Error_PasCO2 PasCO2_CheckCom(void)
{
uint8_t CheckData = 0;

PasCO2_SetOneWord(PasCO2_RegAddr_SCRATCH_PAD,0xA5);
CheckData = PasCO2_GetOneWord(PasCO2_RegAddr_SCRATCH_PAD);

return (CheckData == 0xA5) ? ERROR_NONE : ERROR_COM;
}

//******************************************************************************
//* 函数名称: PasCO2_GetOneWord
//* 函数描述: 获取一个8位数
//* 输入参数:
//* 参数描述:
//* 输出参数: 无
//* 返回值    :
//******************************************************************************   
static uint8_t PasCO2_GetOneWord(uint8_t reg)
{
uint8_t getData = 0;
IIC2_MasterUS_RecvBytes(1,&amp;getData,PasCO2_SlaveAddress,reg);
return getData;
}

//******************************************************************************
//* 函数名称: PasCO2_GetOneWord
//* 函数描述: 设置一个8位数
//* 输入参数:
//* 参数描述:
//* 输出参数: 无
//* 返回值    :
//******************************************************************************   
static void PasCO2_SetOneWord(uint8_t reg,uint8_t data)
{
IIC2_MasterUS_SendBytes(1,&amp;data,PasCO2_SlaveAddress,reg);
}

//******************************************************************************
//* 函数名称: PasCO2_GetTwoWord(uint8_t rate)
//* 函数描述: 获取16位数据
//* 输入参数:
//* 参数描述:
//* 输出参数: 无
//* 返回值    :
//******************************************************************************   
static uint16_t PasCO2_GetTwoWord(uint8_t reg)
{
uint8_t Data={0};
uint16_t data = 0;

IIC2_MasterUS_RecvBytes(2,Data,PasCO2_SlaveAddress,reg);

data = Data;
data = data &lt;&lt; 8;
data |= Data;

return data;
}

//******************************************************************************
//* 函数名称: PasCO2_SetTwoWord
//* 函数描述: 设置16位数据
//* 输入参数: rate:5~4095s
//* 参数描述:
//* 输出参数: 无
//* 返回值    :
//******************************************************************************   
static void PasCO2_SetTwoWord(uint8_t reg,uint16_t data)
{
uint8_t Data;
Data = (uint8_t)(data&gt;&gt;8);
Data = (uint8_t)data;

IIC2_MasterUS_SendBytes(2,Data,PasCO2_SlaveAddress,reg);
}
</code></pre>

<p><strong>5、效果视频</strong></p>

<p>5bcf0055dcaa60f6ebdb39ff4cae7d1d<br />
&nbsp;</p>

<p>&nbsp;</p>

<p>&nbsp;</p>

<p>&nbsp;</p>

<p>&nbsp;</p>

<p>&nbsp;</p>

<p>&nbsp;</p>

<p>&nbsp;</p>

火辣西米秀 发表于 2022-11-6 09:24

<p> &nbsp;</p>

<p>效果很好</p>

秦天qintian0303 发表于 2022-11-6 11:19

火辣西米秀 发表于 2022-11-6 09:24
&nbsp;

效果很好

<p>不知道这个数对不对,居家都是这样吗?我家基本不开窗</p>

秦天qintian0303 发表于 2022-11-6 17:10

<p>通过修改获取数据的方式测试发现,通过修改读取后的延时方式没有彻底解决异常数据的问题,还是通过中断引脚的方式比较靠谱</p>

qzc飘曳 发表于 2022-11-6 19:42

<p>这个CO2划分有标准吗?&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;</p>

Bymyself 发表于 2022-11-6 19:58

<p>非常详细,感谢楼主,异常数据有进展了</p>

秦天qintian0303 发表于 2022-11-6 20:23

qzc飘曳 发表于 2022-11-6 19:42
这个CO2划分有标准吗?&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &n ...

<p>就是通过百度搜的,大气基本是300到500,1000以上就算是浑浊了,不过也没有他说的那样嗜睡</p>

秦天qintian0303 发表于 2022-11-6 20:24

Bymyself 发表于 2022-11-6 19:58
非常详细,感谢楼主,异常数据有进展了

<p>今天换了一种检测方法,确实测量时序上同步的比较好&nbsp;</p>

dql2016 发表于 2022-11-6 20:30

<p>学习了</p>

nmg 发表于 2022-11-7 10:38

<p>看了你的数据,感觉人是个巨大的CO2发生器啊</p>

<p>你说的放置的位置,是不是跟高度有关系,CO2比较沉,离地的位置浓度比较高?</p>

秦天qintian0303 发表于 2022-11-7 19:07

nmg 发表于 2022-11-7 10:38
看了你的数据,感觉人是个巨大的CO2发生器啊

你说的放置的位置,是不是跟高度有关系,CO2比较沉,离地的 ...

<p>我平坐的,传感器就放在桌子上,也不能端直接对着,主要是采集的点应该离人要远一点,要不然人的呼吸会有较大影响</p>

Bymyself 发表于 2022-11-18 13:56

Bymyself 发表于 2022-11-6 19:58
非常详细,感谢楼主,异常数据有进展了

<p>65535依然是传感器本省的假数据?</p>

戈壁滩上的辉煌 发表于 2022-11-18 14:42

<p>这个传感器真不错</p>

金玉其中 发表于 2022-11-18 16:07

<p>IIC的速度如何?</p>

秦天qintian0303 发表于 2022-11-18 16:48

金玉其中 发表于 2022-11-18 16:07
IIC的速度如何?

<p>使用的硬件模拟的,不太清楚具体速度,不过传感器支持400K的速度</p>

秦天qintian0303 发表于 2022-11-18 16:50

戈壁滩上的辉煌 发表于 2022-11-18 14:42
这个传感器真不错

<p>新的黑科技你值得拥有          </p>

秦天qintian0303 发表于 2022-11-18 16:51

Bymyself 发表于 2022-11-18 13:56
65535依然是传感器本省的假数据?

<p>应该是在特定的时间段无法通信导致的,这个就没法具体测试的,需要规避那个特定时间,还是用中断通知比较好</p>

lugl4313820 发表于 2023-6-13 21:51

大佬这是整体的评估板,还是自己打样的?

秦天qintian0303 发表于 2023-6-14 10:53

lugl4313820 发表于 2023-6-13 21:51
大佬这是整体的评估板,还是自己打样的?

<p>就一个传感器,设计的一个基板,这个传感器需要12V供电,正好那时候在测试N32G430就直接一块进行了</p>
页: [1]
查看完整版本: 【英飞凌XENSIV™ PAS CO2传感器】传感器驱动设计