SCD40是瑞士SENSIRION公司推出的一款微型CO2传感器,它基于光声传感原理,并结合了温湿度传感器SHTW2实现片上信号补偿。以下是SCD40的详细介绍:
一、产品特点
- 高精度:SCD40在特定范围内(如400-2000ppm)具有高精度的CO2浓度测量能力,精度可达±(40ppm+5%)。
- 小尺寸:其尺寸仅为10 x 10 x 7 mm³(或根据其他资料为10.1 x 10.1 x 6.5 mm³),便于集成到各种设备中。
- 多功能:除了测量CO2浓度外,还能同时测量温度和湿度,提供全面的环境参数监测。
- 自动校准:SCD40具有自动校准功能(ASC),可以在使用过程中自动保持测量准确性。
- 低功耗:支持低功耗模式,适合长时间运行和电池供电的应用场景。
二、技术原理
SCD40采用光声传感原理进行CO2浓度测量。当红外光通过含有二氧化碳的气流时,二氧化碳分子会吸收部分光线并产生热量,进而产生声波。传感器通过检测这些声波信号的强度来判断二氧化碳的浓度。此外,内置的SHTW2温湿度传感器能够实时测量环境温度和湿度,并通过片上信号补偿技术提高CO2浓度的测量精度。
三、应用场景
SCD40广泛应用于需要精确监测CO2浓度的场合,如:
- 智能家居:用于智能通风系统、空气净化器等设备中,根据室内CO2浓度自动调节通风量或净化效率。
- 农业大棚:监测大棚内的CO2浓度,为植物提供适宜的生长环境。
- 工业检测:在工业生产过程中监测CO2排放情况,确保生产安全和环境合规。
- 医疗领域:用于手术室、病房等场所的空气质量监测,保障医疗环境的洁净度。
四、使用注意事项
- 上电稳定:传感器上电后需要等待约1000ms才能进入空闲状态并接收命令。
- 校准操作:虽然SCD40具有自动校准功能,但在特定情况下(如长时间未使用或环境变化较大时)可能需要进行手动校准。
- 焊接时间:拆包后应在168小时内完成焊接,以避免湿度增加影响传感器性能。
- 接口通信:SCD40使用IIC接口进行通信,从机地址为0x62。在读取数据时需注意遵循相应的通信协议和时序要求。
综上所述,SCD40是一款性能优越、功能全面的微型CO2传感器,广泛应用于智能家居、农业、工业和医疗等领域。在使用过程中需注意遵循相关操作规范和维护要求以确保其长期稳定运行和测量准确性。
五、驱动代码
STM32采用任意IO口即可驱动,因为本人采用的是模拟iic接口,分别罗列了.C文件和h文件。如下为.c文件:
#include "i2c.h"
#include "delay.h"
//初始化IIC
void IIC_Init(void)
{
GPIO_InitTypeDef GPIO_Initure;
__HAL_RCC_GPIOB_CLK_ENABLE(); //使能GPIOD时钟
/*
SCL - PD6 SDA-PC1
*/
GPIO_Initure.Pin = GPIO_PIN_6;
GPIO_Initure.Mode = GPIO_MODE_OUTPUT_PP; //推挽输出
GPIO_Initure.Pull = GPIO_PULLUP; //上拉
GPIO_Initure.Speed = GPIO_SPEED_FREQ_HIGH; //快速
HAL_GPIO_Init(GPIOB, &GPIO_Initure);
GPIO_Initure.Pin = GPIO_PIN_7;
GPIO_Initure.Mode = GPIO_MODE_OUTPUT_PP; //推挽输出
GPIO_Initure.Pull = GPIO_PULLUP; //上拉
GPIO_Initure.Speed = GPIO_SPEED_FREQ_HIGH; //快速
HAL_GPIO_Init(GPIOB, &GPIO_Initure);
}
//产生IIC起始信号
void IIC_Start(void)
{
SDA_OUT(); //sda线输出
IIC_SDA(1);
IIC_SCL(1);
delay_us(4);
IIC_SDA(0);//START:when CLK is high,DATA change form high to low
delay_us(4);
IIC_SCL(0);//钳住I2C总线,准备发送或接收数据
}
//产生IIC停止信号
void IIC_Stop(void)
{
SDA_OUT();//sda线输出
IIC_SCL(0);
IIC_SDA(0);//STOP:when CLK is high DATA change form low to high
delay_us(4);
IIC_SCL(1);
IIC_SDA(1);//发送I2C总线结束信号
delay_us(4);
}
//等待应答信号到来
//返回值:1,接收应答失败
// 0,接收应答成功
u8 IIC_Wait_Ack(void)
{
u8 ucErrTime=0;
SDA_IN(); //SDA设置为输入
IIC_SDA(1);delay_us(1);
IIC_SCL(1);delay_us(1);
while(READ_SDAA)
{
ucErrTime++;
if(ucErrTime>250)
{
IIC_Stop();
return 1;
}
}
IIC_SCL(0);//时钟输出0
return 0;
}
//产生ACK应答
void IIC_Ack(void)
{
IIC_SCL(0);
SDA_OUT() ;
IIC_SDA(0);
delay_us(2);
IIC_SCL(1);
delay_us(2);
IIC_SCL(0);
}
//不产生ACK应答
void IIC_NAck(void)
{
IIC_SCL(0);
SDA_OUT();
IIC_SDA(1);
delay_us(2);
IIC_SCL(1);
delay_us(2);
IIC_SCL(0);
}
//IIC发送一个字节
//返回从机有无应答
//1,有应答
//0,无应答
void IIC_Send_Byte(u8 txd)
{
u8 t;
SDA_OUT();
IIC_SCL(0);//拉低时钟开始数据传输
for(t=0;t<8;t++)
{
IIC_SDA((txd & 0x80) >> 7);
// IIC_SDA(txd&0x80)>>7;
txd<<=1;
delay_us(2); //对TEA5767这三个延时都是必须的
IIC_SCL(1);
delay_us(2);
IIC_SCL(0);
delay_us(2);
}
}
//读1个字节,ack=1时,发送ACK,ack=0,发送nACK
u8 IIC_Read_Byte(unsigned char ack)
{
unsigned char i,receive=0;
SDA_IN();//SDA设置为输入
for(i=0;i<8;i++ )
{
IIC_SCL(0);
delay_us(2);
IIC_SCL(1);
receive<<=1;
if(READ_SDAA)receive++;
delay_us(1);
}
if (!ack)
IIC_NAck();//发送nACK
else
IIC_Ack(); //发送ACK
return receive;
}
uint8_t periodic_Measurements_AreRunning = 0;
scd4x_SensorData_t SCD4x_SensorData;
//Start periodic measurements. See "SCD40_SCD41_Datasheet.pdf" 3.5.1
//signal update interval is 5 seconds.
bool SCD4x_StartPeriodicMeasurement(void)
{
bool success = 0;
if (periodic_Measurements_AreRunning)
{
#if SCD4x_ENABLE_DEBUGLOG
printf("SCD4x_StartPeriodicMeasurement: periodic measurements are already running");
#endif // if SCD4x_ENABLE_DEBUGLOG
return (true); //Maybe this should be false?
}
success = SCD4x_sendCommand(SCD4x_COMMAND_START_PERIODIC_MEASUREMENT);
if (success)
periodic_Measurements_AreRunning = true;
return (success);
}
// Stop periodic measurements. See "SCD40_SCD41_Datasheet.pdf" 3.5.3
// 传感器在发出 STOP_PERIONAL_MEASURATION 命令后等待500毫秒后才会对其他命令作出响应。
bool SCD4x_stopPeriodicMeasurement(uint16_t delayTime)
{
// if (periodic_Measurements_AreRunning == 0)
// {
// return (false);
// }
bool success = SCD4x_sendCommand(SCD4x_COMMAND_STOP_PERIODIC_MEASUREMENT);
if(success)
{
periodic_Measurements_AreRunning = false;
if (delayTime > 0)
delay_ms(delayTime);
return true;
}
if (delayTime > 0)
delay_ms(delayTime);
return (false);
}
// Get 9 bytes from SCD4x. See 3.5.2
// Read sensor output.
// 每个信号更新间隔只能读出一次测量数据,因为读数时缓冲区被清空
// 如果缓冲区中没有可用数据,传感器将返回 NACK。
bool SCD4x_readMeasurement(uint16_t *co2, float *temperature, float *humidity, uint8_t *Error)
{
uint8_t error = 0;
uint8_t buffer[10] = {0};
if (SCD4x_getDataReadyStatus() == false) // get_data_ready_status. see "SCD40_SCD41_Datasheet.pdf" 3.8.2
return (false);
SCD4x_SensorData.tempCO2.unsigned16 = 0;
SCD4x_SensorData.tempHumidity.unsigned16 = 0;
SCD4x_SensorData.tempTemperature.unsigned16 = 0;
IIC_Start();
IIC_Send_Byte( (SCD4x_ADDRESS<<1)&(~0x01)); //I2C Address + write
IIC_Wait_Ack();
IIC_Send_Byte(SCD4x_COMMAND_READ_MEASUREMENT >> 8); //MSB
IIC_Wait_Ack();
IIC_Send_Byte(SCD4x_COMMAND_READ_MEASUREMENT & 0xFF); //LSB
error = IIC_Wait_Ack();
if ( error )
return (false); //Sensor did not ACK
error = 0;
delay_ms(1); //Datasheet specifies this, command execution time
IIC_Start();
IIC_Send_Byte( (SCD4x_ADDRESS<<1)|(0x01)); //I2C Address + read
IIC_Wait_Ack();
buffer[0] = IIC_Read_Byte(1); //read data and ack
buffer[1] = IIC_Read_Byte(1);
buffer[2] = IIC_Read_Byte(1);
buffer[3] = IIC_Read_Byte(1);
buffer[4] = IIC_Read_Byte(1);
buffer[5] = IIC_Read_Byte(1);
buffer[6] = IIC_Read_Byte(1);
buffer[7] = IIC_Read_Byte(1);
buffer[8] = IIC_Read_Byte(0); //read data and no ack
IIC_Stop();
uint8_t foundCrc = 0;
uint8_t bytesToCrc[2]={0};
for (uint8_t x = 0; x < 9; x++)
{
switch (x)
{
case 0:
case 1:
SCD4x_SensorData.tempCO2.bytes[x == 0 ? 1 : 0] = buffer[x]; // Store the two CO2 bytes in little-endian format
bytesToCrc[x] = buffer[x]; // Calculate the CRC on the two CO2 bytes in the order they arrive
break;
case 3:
case 4:
SCD4x_SensorData.tempTemperature.bytes[x == 3 ? 1 : 0] = buffer[x]; // Store the two T bytes in little-endian format
bytesToCrc[x % 3] = buffer[x]; // Calculate the CRC on the two T bytes in the order they arrive
break;
case 6:
case 7:
SCD4x_SensorData.tempHumidity.bytes[x == 6 ? 1 : 0] = buffer[x]; // Store the two RH bytes in little-endian format
bytesToCrc[x % 3] = buffer[x]; // Calculate the CRC on the two RH bytes in the order they arrive
break;
default: // x == 2, 5, 8
//Validate CRC
foundCrc = SCD4x_computeCRC8(bytesToCrc, 2); // Calculate what the CRC should be for these two bytes
if (foundCrc != buffer[x]) // CRC check error
{
#if SCD4x_ENABLE_DEBUGLOG
#endif // if SCD4x_ENABLE_DEBUGLOG
if(x==2)
{error |= 0x01;} // CO2
if(x==5)
{error |= 0x02;} // Temperature
if(x==8)
{error |= 0x04;} // Humidity
}
break;
}
}
if (error)
{
*Error = error;
#if SCD4x_ENABLE_DEBUGLOG
printf("SCD4x_readMeasurement: encountered error reading SCD4x data.");
#endif // if SCD4x_ENABLE_DEBUGLOG
return (false);
}
// 返回解析后的数据
*co2 = (uint16_t)SCD4x_SensorData.tempCO2.unsigned16; //ppm
*temperature = -45 + (((float)SCD4x_SensorData.tempTemperature.unsigned16) * 175 / 65536);
*humidity = ((float)SCD4x_SensorData.tempHumidity.unsigned16) * 100 / 65536;
return (true); //Success!
}
//Get 9 bytes from SCD4x. Convert 48-bit serial number to ASCII chars. See 3.9.2
//Returns true if serial number is read successfully
//Reading out the serial number can be used to identify the chip and to verify the presence of the sensor.
bool SCD4x_getSerialNumber(char *serialNumber)
{
uint8_t error = 0;
uint8_t Crc = 0;
if (periodic_Measurements_AreRunning)
{
#if SCD4x_ENABLE_DEBUGLOG
printf("SCD4x_getSerialNumber: periodic measurements are running. Aborting");
#endif // if SCD4x_ENABLE_DEBUGLOG
return (false);
}
IIC_Start();
IIC_Send_Byte( (SCD4x_ADDRESS<<1)&(~0x01)); //I2C Address + write
IIC_Wait_Ack();
IIC_Send_Byte(SCD4x_COMMAND_GET_SERIAL_NUMBER >> 8); //MSB
IIC_Wait_Ack();
IIC_Send_Byte(SCD4x_COMMAND_GET_SERIAL_NUMBER & 0xFF); //LSB
error = IIC_Wait_Ack();
if ( error )
return (false); //Sensor did not ACK
delay_ms(1); //Datasheet specifies this
IIC_Start();
IIC_Send_Byte( (SCD4x_ADDRESS<<1)|(0x01)); //I2C Address + read
error = IIC_Wait_Ack();
if (error==0)
{
uint8_t bytesToCrc[2];
int digit = 0;
for (uint8_t x = 0; x < 9; x++)
{
uint8_t incoming = IIC_Read_Byte(1); //read data and ack
if(x==8)
{
incoming = IIC_Read_Byte(0); //read data and no ack
IIC_Stop();
}
switch (x)
{
case 0: // The serial number arrives as: two bytes, CRC, two bytes, CRC, two bytes, CRC
case 1:
case 3:
case 4:
case 6:
case 7:
serialNumber[digit++] = SCD4x_convertHexToASCII(incoming >> 4); // Convert each nibble to ASCII
serialNumber[digit++] = SCD4x_convertHexToASCII(incoming & 0x0F);
bytesToCrc[x % 3] = incoming;
break;
default: // x == 2, 5, 8
Crc = SCD4x_computeCRC8(bytesToCrc, 2); // Calculate what the CRC should be for these two bytes
if (Crc != incoming) // Does this match the CRC byte from the sensor?
{
#if SCD4x_ENABLE_DEBUGLOG
#endif // if SCD4x_ENABLE_DEBUGLOG
error = true;
}
break;
}
serialNumber[digit] = 0; // NULL-terminate the string
}
}
if (error)
{
#if SCD4x_ENABLE_DEBUGLOG
printf("SCD4x_readSerialNumber: encountered error reading SCD4x data.");
#endif // if SCD4x_ENABLE_DEBUGLOG
return (false);
}
return (true); //Success!
}
//Perform self test. Takes 10 seconds to complete. See 3.9.3
//The perform_self_test feature can be used as an end-of-line test to check sensor functionality
//and the customer power supply to the sensor.
bool SCD4x_performSelfTest(void)
{
if (periodic_Measurements_AreRunning)
{
#if SCD4x_ENABLE_DEBUGLOG
#endif // if SCD4x_ENABLE_DEBUGLOG
return (false);
}
uint16_t response;
#if SCD4x_ENABLE_DEBUGLOG
printf("SCD4x_performSelfTest: delaying for 10 seconds...");
#endif // if SCD4x_ENABLE_DEBUGLOG
bool success = SCD4x_readRegister(SCD4x_COMMAND_PERFORM_SELF_TEST, &response, 10000);
return (success && (response == 0x0000)); // word[0] = 0 → no malfunction detected
}
//Peform factory reset. See 3.9.4
//The perform_factory_reset command resets all configuration settings stored in the EEPROM
//and erases the FRC and ASC algorithm history.
bool SCD4x_performFactoryReset(uint16_t delayTime)
{
if (periodic_Measurements_AreRunning)
{
#if SCD4x_ENABLE_DEBUGLOG
#endif // if SCD4x_ENABLE_DEBUGLOG
return (false);
}
bool success = SCD4x_sendCommand(SCD4x_COMMAND_PERFORM_FACTORY_RESET);
if (delayTime > 0)
delay_ms(delayTime);
return (success);
}
//Reinit. See 3.9.5
//The reinit command reinitializes the sensor by reloading user settings from EEPROM.
//Before sending the reinit command, the stop measurement command must be issued.
//If the reinit command does not trigger the desired re-initialization,a power-cycle should be applied to the SCD4x.
bool SCD4x_reInit(uint16_t delayTime)
{
if (periodic_Measurements_AreRunning)
{
return (false); // 需停止周期测量
}
bool success = SCD4x_sendCommand(SCD4x_COMMAND_REINIT);
if (delayTime > 0)
delay_ms(delayTime);
return (success);
}
//Sends just a command, no arguments, no CRC
// see "SCD40_SCD41_Datasheet.pdf 3.3", "send command sequence"
bool SCD4x_sendCommand(uint16_t command)
{
uint8_t error = 0;
IIC_Start();
IIC_Send_Byte((SCD4x_ADDRESS<<1)&(~0x01));
IIC_Wait_Ack();
IIC_Send_Byte(command >> 8); //MSB
IIC_Wait_Ack();
IIC_Send_Byte(command & 0xFF); //LSB
error = IIC_Wait_Ack();
IIC_Stop();
if ( error )
return (false); //Sensor did not ACK
return (true);
}
// Sends a command along with arguments and CRC
// see "SCD40_SCD41_Datasheet.pdf 3.3", "write sequence"
bool SCD4x_sendCommand_CmdData_CRC(uint16_t command, uint16_t arguments)
{
uint8_t data[2];
uint8_t error = 0;
data[0] = arguments >> 8;
data[1] = arguments & 0xFF;
uint8_t crc = SCD4x_computeCRC8(data, 2); //Calc CRC on the arguments only, not the command
IIC_Start();
IIC_Send_Byte( (SCD4x_ADDRESS<<1)&(~0x01) );
IIC_Wait_Ack();
IIC_Send_Byte(command >> 8); //MSB
IIC_Wait_Ack();
IIC_Send_Byte(command & 0xFF); //LSB
IIC_Wait_Ack();
IIC_Send_Byte(arguments >> 8); //MSB
IIC_Wait_Ack();
IIC_Send_Byte(arguments & 0xFF); //LSB
IIC_Wait_Ack();
IIC_Send_Byte(crc); //CRC
error = IIC_Wait_Ack();
IIC_Stop();
if ( error )
return (false); //Sensor did not ACK
return (true);
}
// Read one uint16 data from SCD4x plus CRC. see "SCD40_SCD41_Datasheet.pdf 3.3", "read sequence"
// Returns true if IIC_Wait_Ack returns 0 _and_ the CRC check is valid
bool SCD4x_readRegister(uint16_t registerAddress, uint16_t *response, uint16_t delayTime)
{
uint8_t error = 0;
uint8_t crc = 0;
uint8_t data[2] = {0};
IIC_Start();
IIC_Send_Byte( (SCD4x_ADDRESS<<1)&(~0x01) ); //I2C Address + write
IIC_Wait_Ack();
IIC_Send_Byte(registerAddress >> 8); //MSB
IIC_Wait_Ack();
IIC_Send_Byte(registerAddress & 0xFF); //LSB
error = IIC_Wait_Ack();
IIC_Stop();
if ( error )
return (false); //Sensor did not ACK
delay_ms(delayTime);
IIC_Start();
IIC_Send_Byte( (SCD4x_ADDRESS<<1)|(0x01) ); //I2C Address + read
IIC_Wait_Ack();
data[0] = IIC_Read_Byte(1);
data[1] = IIC_Read_Byte(1);
crc = IIC_Read_Byte(0);
IIC_Stop();
*response = (uint16_t)data[0] << 8 | data[1];
uint8_t expectedCRC = SCD4x_computeCRC8(data, 2);
if (crc == expectedCRC) // Return true if CRC check is OK
return (true);
return (false);
}
//Returns true when data is available. See 3.8.2
bool SCD4x_getDataReadyStatus(void)
{
uint16_t response;
bool success = SCD4x_readRegister(SCD4x_COMMAND_GET_DATA_READY_STATUS, &response, 1);
if (success == false)
return (false);
// 0 至 11 bit 是 0 --> data not ready
//else → data ready for read-out
if ((response & 0x07ff) == 0x0000)
return (false);
return (true);
}
//PRIVATE: Convert serial number digit to ASCII
char SCD4x_convertHexToASCII(uint8_t digit)
{
if (digit <= 9)
return ( (char)(digit + 0x30) );
else
return ( (char)(digit + 0x41 - 10) ); // Use upper case for A-F
}
//Given an array and a number of bytes, this calculate CRC8 for those bytes
//From: http://www.sunshine2k.de/articles/coding/crc/understanding_crc.html
//Tested with: http://www.sunshine2k.de/coding/javascript/crc/crc_js.html
//x^8+x^5+x^4+1 = 0x31
uint8_t SCD4x_computeCRC8(uint8_t data[], uint8_t len)
{
uint8_t crc = 0xFF; //Init with 0xFF
for (uint8_t x = 0; x < len; x++)
{
crc ^= data[x]; // XOR-in the next input byte
for (uint8_t i = 0; i < 8; i++)
{
if ((crc & 0x80) != 0)
crc = (uint8_t)((crc << 1) ^ 0x31);
else
crc <<= 1;
}
}
return crc; //No output reflection
}
/*
end
*?
h文件如下:
#ifndef _I2C_H_
#define _I2C_H_
#include "stm32g0xx.h"
#include "stdbool.h"
//IO方向设置
#define SDA_IN() {GPIOB->MODER&=~(3<<(6*2));GPIOB->MODER|=0<<(6*2);} //PC1输入模式
#define SDA_OUT() {GPIOB->MODER&=~(3<<(6*2));GPIOB->MODER|=1<<(6*2);} //PC1输出模式
#define IIC_SCL(n) (n?HAL_GPIO_WritePin(GPIOB,GPIO_PIN_7,GPIO_PIN_SET):HAL_GPIO_WritePin(GPIOB,GPIO_PIN_7,GPIO_PIN_RESET))//SCL
#define IIC_SDA(n) (n?HAL_GPIO_WritePin(GPIOB,GPIO_PIN_6,GPIO_PIN_SET):HAL_GPIO_WritePin(GPIOB,GPIO_PIN_6,GPIO_PIN_RESET))//SDA
#define READ_SDAA HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_6)//输入SDA
//IIC所有操作函数
void IIC_Init(void); //初始化IIC的IO口
void IIC_Start(void); //发送IIC开始信号
void IIC_Stop(void); //发送IIC停止信号
void IIC_Send_Byte(u8 txd); //IIC发送一个字节
u8 IIC_Read_Byte(unsigned char ack);//IIC读取一个字节
u8 IIC_Wait_Ack(void); //IIC等待ACK信号
void IIC_Ack(void); //IIC发送ACK信号
void IIC_NAck(void); //IIC不发送ACK信号
void IIC_Write_One_Byte(u8 daddr,u8 addr,u8 data);
u8 IIC_Read_One_Byte(u8 daddr,u8 addr);
#define SCD4x_ENABLE_DEBUGLOG 0 //debug SCD4x
//The default I2C address for the SCD4x is 0x62.
#define SCD4x_ADDRESS 0x62
//Available commands
//Basic Commands
#define SCD4x_COMMAND_START_PERIODIC_MEASUREMENT 0x21b1
#define SCD4x_COMMAND_READ_MEASUREMENT 0xec05 // execution time: 1ms
#define SCD4x_COMMAND_STOP_PERIODIC_MEASUREMENT 0x3f86 // execution time: 500ms
//On-chip output signal compensation
#define SCD4x_COMMAND_SET_TEMPERATURE_OFFSET 0x241d // execution time: 1ms
#define SCD4x_COMMAND_GET_TEMPERATURE_OFFSET 0x2318 // execution time: 1ms
#define SCD4x_COMMAND_SET_SENSOR_ALTITUDE 0x2427 // execution time: 1ms
#define SCD4x_COMMAND_GET_SENSOR_ALTITUDE 0x2322 // execution time: 1ms
#define SCD4x_COMMAND_SET_AMBIENT_PRESSURE 0xe000 // execution time: 1ms
//Field calibration
#define SCD4x_COMMAND_PERFORM_FORCED_CALIBRATION 0x362f // execution time: 400ms
#define SCD4x_COMMAND_SET_AUTOMATIC_SELF_CALIBRATION_ENABLED 0x2416 // execution time: 1ms
#define SCD4x_COMMAND_GET_AUTOMATIC_SELF_CALIBRATION_ENABLED 0x2313 // execution time: 1ms
//Low power
#define SCD4x_COMMAND_START_LOW_POWER_PERIODIC_MEASUREMENT 0x21ac
#define SCD4x_COMMAND_GET_DATA_READY_STATUS 0xe4b8 // execution time: 1ms
//Advanced features
#define SCD4x_COMMAND_PERSIST_SETTINGS 0x3615 // execution time: 800ms
#define SCD4x_COMMAND_GET_SERIAL_NUMBER 0x3682 // execution time: 1ms
#define SCD4x_COMMAND_PERFORM_SELF_TEST 0x3639 // execution time: 10000ms
#define SCD4x_COMMAND_PERFORM_FACTORY_RESET 0x3632 // execution time: 1200ms
#define SCD4x_COMMAND_REINIT 0x3646 // execution time: 20ms
//Low power single shot - SCD41 only
#define SCD4x_COMMAND_MEASURE_SINGLE_SHOT 0x219d // execution time: 5000ms
#define SCD4x_COMMAND_MEASURE_SINGLE_SHOT_RHT_ONLY 0x2196 // execution time: 50ms
typedef union
{
int16_t signed16;
uint16_t unsigned16;
} scd4x_int16_uint16_t; // Avoid any ambiguity casting int16_t to uint16_t
typedef union
{
uint16_t unsigned16;
uint8_t bytes[2];
} scd4x_uint16_Bytes_t; // Make it easy to convert 2 x uint8_t to uint16_t
typedef struct
{
scd4x_uint16_Bytes_t tempCO2;
scd4x_uint16_Bytes_t tempHumidity;
scd4x_uint16_Bytes_t tempTemperature;
}scd4x_SensorData_t;
extern scd4x_SensorData_t SCD4x_SensorData; //save SCD4x sensor data
bool SCD4x_StartPeriodicMeasurement(void);
bool SCD4x_stopPeriodicMeasurement(uint16_t delayTime); // execution time: 500ms
bool SCD4x_readMeasurement(uint16_t *co2, float *temperature, float *humidity, uint8_t *Error);
bool SCD4x_getSerialNumber(char *serialNumber); //return 13 byte string
bool SCD4x_performSelfTest(void); // executed time 10000 ms
bool SCD4x_performFactoryReset(uint16_t delayTime); // executed time 1200 ms
bool SCD4x_reInit(uint16_t delayTime); // executed time 20 ms
bool SCD4x_getDataReadyStatus(void); // executed time 1 ms
bool SCD4x_sendCommand(uint16_t command);
bool SCD4x_sendCommand_CmdData_CRC(uint16_t command, uint16_t arguments);
bool SCD4x_readRegister(uint16_t registerAddress, uint16_t *response, uint16_t delayTime);
char SCD4x_convertHexToASCII(uint8_t digit);
uint8_t SCD4x_computeCRC8(uint8_t data[], uint8_t len); //CRC8校验
//===========================================================================//
#endif
//========================== end of file ==================================//
IO方向设置不理解参考往期文章STM32驱动AHT10/AHT20/AHT30温湿度传感器源码-CSDN博客
这里有做说明 ,https://blog.csdn.net/man_pangpang/article/details/139071176?utm_source%20=%20uc_fansmsg
主要说明如何配置iic方向;
主程序如下:
..............
uint16_t CO2 = 0; //ppm
float temperature = 0; //摄氏度
float humidity = 0; //湿度 百分比
uint8_t error = 0;
int main(void)
{
u16 ikL=0;
.............
IIC_Init();
// init_scd40();
SCD4x_stopPeriodicMeasurement(600);
//SCD4x软件重启
SCD4x_reInit(20);
//开始周期测量
SCD4x_StartPeriodicMeasurement();
while (1)
{
ikL++;
if(ikL>10)
{
ikL=0;
SCD4x_readMeasurement(&CO2, &temperature, &humidity, &error);
//上句即可得到温度湿度以及二氧化碳浓度数据
}
delay_ms(1000);
}
}
创作不易,全部开源各位且行且珍惜,请各位履行点赞关注评论转发义务。