增加I2C 使用SHT40温湿度传感器上传TCP客户端数据

This commit is contained in:
冯佳
2026-03-03 16:39:19 +08:00
parent 23bb103fb5
commit cc4c361df6
16 changed files with 1854 additions and 393 deletions

243
app/sht40.c Normal file
View File

@ -0,0 +1,243 @@
/*
* 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); // 默认使用高精度
}