/* * SHT40 温湿度传感器驱动 * 功能:通过I2C1读取SHT40传感器的温湿度数据 * 依赖:STM32 HAL库 * 跨平台:仅适用于STM32F4系列,使用HAL库的I2C接口 */ #include "sht40.h" #include "board.h" #include "osal.h" /* 外部I2C句柄 */ extern I2C_HandleTypeDef hi2c1; /* CRC校验函数 */ static uint8_t sht40_crc8(const uint8_t *data, uint8_t len) { const uint8_t POLYNOMIAL = 0x31; uint8_t crc = 0xFF; for (uint8_t i = 0; i < len; i++) { crc ^= data[i]; for (uint8_t j = 0; j < 8; j++) { if (crc & 0x80) { crc = (crc << 1) ^ POLYNOMIAL; } else { crc <<= 1; } } } return crc; } /** * @brief 初始化SHT40传感器 * @return 0成功,-1失败 */ int sht40_init(void) { return sht40_reset(); } /** * @brief 重置SHT40传感器 * @return 0成功,-1失败 */ int sht40_reset(void) { uint8_t cmd = SHT40_CMD_RESET; osal_log_i("SHT40: Sending reset command 0x%02X", cmd); if (HAL_I2C_Master_Transmit(&hi2c1, SHT40_I2C_ADDR << 1, &cmd, 1, 1000) != HAL_OK) { osal_log_e("SHT40 reset failed"); return -1; } osal_thread_mdelay(1); // 重置需要<1ms osal_log_i("SHT40: Reset successful"); return 0; } /** * @brief 读取SHT40传感器的序列号 * @param serial 序列号(4字节) * @return 0成功,-1失败 */ int sht40_read_serial(uint32_t *serial) { uint8_t cmd = SHT40_CMD_READ_SERIAL; uint8_t data[6]; //osal_log_i("SHT40: Sending read serial command 0x%02X", cmd); if (HAL_I2C_Master_Transmit(&hi2c1, SHT40_I2C_ADDR << 1, &cmd, 1, 1000) != HAL_OK) { osal_log_e("SHT40 send read serial command failed"); return -1; } osal_thread_mdelay(1); if (HAL_I2C_Master_Receive(&hi2c1, SHT40_I2C_ADDR << 1, data, 6, 1000) != HAL_OK) { osal_log_e("SHT40 read serial data failed"); return -1; } /* 校验数据 */ if (sht40_crc8(&data[0], 2) != data[2]) { osal_log_e("SHT40 serial CRC error (bytes 0-2)"); return -1; } if (sht40_crc8(&data[3], 2) != data[5]) { osal_log_e("SHT40 serial CRC error (bytes 3-5)"); return -1; } *serial = (uint32_t)(data[0] << 24) | (data[1] << 16) | (data[3] << 8) | data[4]; //osal_log_i("SHT40: Serial number: 0x%08X", *serial); return 0; } /** * @brief 开启SHT40传感器的加热器 * @param power_level 功率级别:0=低功率(20mW), 1=中功率(110mW), 2=高功率(200mW) * @return 0成功,-1失败 */ int sht40_heater_enable(uint8_t power_level) { uint8_t cmd; switch (power_level) { case 0: cmd = SHT40_CMD_HEATER_LOW; //osal_log_i("SHT40: Enabling heater (low power, 20mW)"); break; case 1: cmd = SHT40_CMD_HEATER_MED; //osal_log_i("SHT40: Enabling heater (medium power, 110mW)"); break; case 2: cmd = SHT40_CMD_HEATER_HIGH; //osal_log_i("SHT40: Enabling heater (high power, 200mW)"); break; default: osal_log_e("SHT40: Invalid heater power level"); return -1; } if (HAL_I2C_Master_Transmit(&hi2c1, SHT40_I2C_ADDR << 1, &cmd, 1, 1000) != HAL_OK) { osal_log_e("SHT40 heater enable failed"); return -1; } osal_thread_mdelay(1000); // 加热器持续1秒 //osal_log_i("SHT40: Heater operation completed"); return 0; } /** * @brief 读取SHT40传感器的温湿度数据(支持不同精度) * @param temperature 温度值(摄氏度) * @param humidity 湿度值(百分比) * @param precision 精度级别:0=低精度, 1=中精度, 2=高精度 * @return 0成功,-1失败 */ int sht40_read_temperature_humidity_with_precision(float *temperature, float *humidity, uint8_t precision) { uint8_t cmd; uint16_t delay_ms; switch (precision) { case 0: cmd = SHT40_CMD_MEASURE_LOW_PRECISION; delay_ms = 2; // 1.8ms //osal_log_i("SHT40: Using low precision measurement"); break; case 1: cmd = SHT40_CMD_MEASURE_MED_PRECISION; delay_ms = 5; // 4.5ms //osal_log_i("SHT40: Using medium precision measurement"); break; case 2: default: cmd = SHT40_CMD_MEASURE_HIGH_PRECISION; delay_ms = 10; // 8.2ms //osal_log_i("SHT40: Using high precision measurement"); break; } uint8_t data[6]; //osal_log_i("SHT40: Sending measure command 0x%02X to address 0x%02X", cmd, SHT40_I2C_ADDR); /* 发送测量命令 */ HAL_StatusTypeDef status = HAL_I2C_Master_Transmit(&hi2c1, SHT40_I2C_ADDR << 1, &cmd, 1, 1000); if (status != HAL_OK) { osal_log_e("SHT40 send measure command failed, status: %d", status); return -1; } //osal_log_i("SHT40: Measure command sent successfully"); /* 等待测量完成 */ osal_thread_mdelay(delay_ms); /* 读取测量结果 */ //osal_log_i("SHT40: Reading 6 bytes of data"); status = HAL_I2C_Master_Receive(&hi2c1, SHT40_I2C_ADDR << 1, data, 6, 1000); if (status != HAL_OK) { osal_log_e("SHT40 read data failed, status: %d", status); return -1; } //osal_log_i("SHT40: Data read successfully: 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X", // data[0], data[1], data[2], data[3], data[4], data[5]); /* 校验温度数据 */ if (sht40_crc8(&data[0], 2) != data[2]) { osal_log_e("SHT40 temperature CRC error"); return -1; } /* 校验湿度数据 */ if (sht40_crc8(&data[3], 2) != data[5]) { osal_log_e("SHT40 humidity CRC error"); return -1; } /* 计算温度值 */ uint16_t temp_raw = (data[0] << 8) | data[1]; *temperature = -45.0f + 175.0f * (float)temp_raw / 65535.0f; /* 计算湿度值 */ uint16_t hum_raw = (data[3] << 8) | data[4]; *humidity = -6.0f + 125.0f * (float)hum_raw / 65535.0f; /* 湿度值范围限制 */ if (*humidity < 0.0f) *humidity = 0.0f; if (*humidity > 100.0f) *humidity = 100.0f; return 0; } /** * @brief 读取SHT40传感器的温湿度数据(默认高精度) * @param temperature 温度值(摄氏度) * @param humidity 湿度值(百分比) * @return 0成功,-1失败 */ int sht40_read_temperature_humidity(float *temperature, float *humidity) { return sht40_read_temperature_humidity_with_precision(temperature, humidity, 2); // 默认使用高精度 }