增加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

View File

@ -10,6 +10,7 @@
#include "lwip/inet_chksum.h"
#include <string.h>
#include "lwip/prot/ip4.h"
#include "sht40.h"
/* Utility macros */
#define MIN(a, b) ((a) < (b) ? (a) : (b))
@ -422,6 +423,9 @@ static void tcp_client_entry(void *parameter)
reconnect_count = 0;
reconnect_delay = TCP_CLIENT_INIT_RECONNECT_DELAY;
int report_interval = 5000; // 5秒上报一次温湿度数据
osal_tick_t last_report_time = 0;
while (1)
{
/* Check Link Status */
@ -438,6 +442,59 @@ static void tcp_client_entry(void *parameter)
}
}
/* 定期读取并上报温湿度数据 */
osal_tick_t current_time = osal_tick_get();
if (current_time - last_report_time >= report_interval)
{
float temperature = 0.0f, humidity = 0.0f;
int result = sht40_read_temperature_humidity(&temperature, &humidity);
if (result == 0)
{
char sensor_data[64];
int temp_int = (int)(temperature * 100);
int hum_int = (int)(humidity * 100);
/* 处理负值温度显示 */
int temp_integer = temp_int / 100;
int temp_decimal = temp_int % 100;
if (temp_decimal < 0) temp_decimal = -temp_decimal;
int hum_integer = hum_int / 100;
int hum_decimal = hum_int % 100;
if (hum_decimal < 0) hum_decimal = -hum_decimal;
if (temp_integer >= 0)
{
snprintf(sensor_data, sizeof(sensor_data), "TEMP=+%d.%02d℃,HUM=%d.%02d%%RH\n",
temp_integer, temp_decimal, hum_integer, hum_decimal);
}
else
{
snprintf(sensor_data, sizeof(sensor_data), "TEMP=%d.%02d℃,HUM=%d.%02d%%RH\n",
temp_integer, temp_decimal, hum_integer, hum_decimal);
}
if (send(sock, sensor_data, strlen(sensor_data), 0) < 0)
{
if (errno != EWOULDBLOCK)
{
osal_log_e("Send sensor data failed: %d", errno);
break;
}
}
else
{
osal_log_i("Sent sensor data: %s", sensor_data);
}
}
else
{
osal_log_e("Failed to read sensor data, result: %d", result);
}
last_report_time = current_time;
}
/* Wait for data with timeout */
fd_set rset;
struct timeval tv;
@ -588,6 +645,27 @@ int main(void)
rt_kprintf("Failed to create thread 'eth_input'\n");
}
/* Initialize SHT40 sensor */
if (sht40_init() != 0)
{
osal_log_e("SHT40 sensor initialization failed");
}
else
{
osal_log_i("SHT40 sensor initialized successfully");
/* Use heater once during initialization for self-calibration */
osal_log_i("Performing SHT40 self-calibration using heater...");
if (sht40_heater_enable(1) == 0) // Use medium power (110mW)
{
osal_log_i("SHT40 self-calibration completed successfully");
}
else
{
osal_log_e("SHT40 self-calibration failed");
}
}
/* Create TCP Client Thread */
tid = osal_thread_create("tcp_client", tcp_client_entry, NULL, 2048, 15);
if (tid != NULL)
@ -621,3 +699,4 @@ int main(void)
return 0;
}

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); // 默认使用高精度
}

35
app/sht40.h Normal file
View File

@ -0,0 +1,35 @@
/*
* SHT40 温湿度传感器驱动
* 功能通过I2C1读取SHT40传感器的温湿度数据
* 依赖STM32 HAL库
* 跨平台仅适用于STM32F4系列使用HAL库的I2C接口
*/
#ifndef __SHT40_H__
#define __SHT40_H__
#include <stdint.h>
#include "stm32f4xx_hal.h"
/* SHT40 I2C地址 */
#define SHT40_I2C_ADDR 0x44
/* SHT40命令 */
#define SHT40_CMD_MEASURE_HIGH_PRECISION 0xFD // 高精度测量(高重复性)
#define SHT40_CMD_MEASURE_MED_PRECISION 0xF6 // 中精度测量(中重复性)
#define SHT40_CMD_MEASURE_LOW_PRECISION 0xE0 // 低精度测量(低重复性)
#define SHT40_CMD_RESET 0x89 // 软复位
#define SHT40_CMD_READ_SERIAL 0x00 // 读取序列号
#define SHT40_CMD_HEATER_HIGH 0x94 // 加热器开启高功率200mW
#define SHT40_CMD_HEATER_MED 0x91 // 加热器开启中功率110mW
#define SHT40_CMD_HEATER_LOW 0x8D // 加热器开启低功率20mW
/* 函数声明 */
int sht40_init(void);
int sht40_read_temperature_humidity(float *temperature, float *humidity);
int sht40_read_temperature_humidity_with_precision(float *temperature, float *humidity, uint8_t precision);
int sht40_reset(void);
int sht40_read_serial(uint32_t *serial);
int sht40_heater_enable(uint8_t power_level);
#endif