// // Created by dell on 24-12-20. // TMP112A Temperature Sensor Driver Implementation // #include "tmp112.h" /* Private function prototypes */ static i2c_status_t tmp112a_write_register(uint8_t reg_addr, uint16_t value); static i2c_status_t tmp112a_read_register(uint8_t reg_addr, uint16_t *value); static float tmp112a_raw_to_celsius(uint16_t raw_data); static uint16_t tmp112a_celsius_to_raw(float temperature); /*! \brief 初始化TMP112A传感器 \param[in] none \param[out] none \retval tmp112a_status_t */ tmp112a_status_t tmp112a_init(void) { i2c_status_t i2c_status; /* 配置传感器为默认设置 */ i2c_status = tmp112a_config(TMP112A_CONFIG_DEFAULT); if (i2c_status != I2C_STATUS_SUCCESS) { return TMP112A_STATUS_ERROR; } /* 等待配置生效 */ delay_ms(1); return TMP112A_STATUS_SUCCESS; } /*! \brief 配置TMP112A传感器 \param[in] config: 配置值 \param[out] none \retval tmp112a_status_t */ tmp112a_status_t tmp112a_config(uint16_t config) { i2c_status_t status = tmp112a_write_register(TMP112A_CONFIG_REG, config); return (status == I2C_STATUS_SUCCESS) ? TMP112A_STATUS_SUCCESS : TMP112A_STATUS_ERROR; } /*! \brief 读取温度 \param[in] none \param[out] result: 结果结构体指针 \retval tmp112a_status_t */ tmp112a_status_t tmp112a_read_temperature(tmp112a_result_t *result) { uint16_t raw_data; i2c_status_t status; if (result == NULL) { return TMP112A_STATUS_INVALID_PARAM; } /* 读取温度寄存器 */ status = tmp112a_read_register(TMP112A_TEMP_REG, &raw_data); if (status != I2C_STATUS_SUCCESS) { return TMP112A_STATUS_ERROR; } /* 解析温度数据 */ result->raw_data = raw_data; result->temperature_c = tmp112a_raw_to_celsius(raw_data); result->temperature_f = result->temperature_c * 9.0f / 5.0f + 32.0f; /* 检查温度范围 */ if (result->temperature_c < TMP112A_TEMP_MIN || result->temperature_c > TMP112A_TEMP_MAX) { return TMP112A_STATUS_OUT_OF_RANGE; } /* 检查报警标志 */ uint16_t config_reg; status = tmp112a_read_register(TMP112A_CONFIG_REG, &config_reg); if (status == I2C_STATUS_SUCCESS) { result->alert_flag = (config_reg & TMP112A_CONFIG_AL) ? true : false; } else { result->alert_flag = false; } return TMP112A_STATUS_SUCCESS; } /*! \brief 设置温度阈值 \param[in] low_temp: 低温阈值 (°C) \param[in] high_temp: 高温阈值 (°C) \param[out] none \retval tmp112a_status_t */ tmp112a_status_t tmp112a_set_thresholds(float low_temp, float high_temp) { uint16_t low_raw, high_raw; i2c_status_t status; /* 参数验证 */ if (low_temp < TMP112A_TEMP_MIN || low_temp > TMP112A_TEMP_MAX || high_temp < TMP112A_TEMP_MIN || high_temp > TMP112A_TEMP_MAX || low_temp >= high_temp) { return TMP112A_STATUS_INVALID_PARAM; } /* 转换温度为原始值 */ low_raw = tmp112a_celsius_to_raw(low_temp); high_raw = tmp112a_celsius_to_raw(high_temp); /* 写入低温阈值 */ status = tmp112a_write_register(TMP112A_TLOW_REG, low_raw); if (status != I2C_STATUS_SUCCESS) { return TMP112A_STATUS_ERROR; } /* 写入高温阈值 */ status = tmp112a_write_register(TMP112A_THIGH_REG, high_raw); if (status != I2C_STATUS_SUCCESS) { return TMP112A_STATUS_ERROR; } return TMP112A_STATUS_SUCCESS; } /*! \brief 进入关机模式 \param[in] none \param[out] none \retval tmp112a_status_t */ tmp112a_status_t tmp112a_shutdown(void) { uint16_t config_reg; i2c_status_t status; /* 读取当前配置 */ status = tmp112a_read_register(TMP112A_CONFIG_REG, &config_reg); if (status != I2C_STATUS_SUCCESS) { return TMP112A_STATUS_ERROR; } /* 设置关机位 */ config_reg |= TMP112A_CONFIG_SD; /* 写回配置 */ status = tmp112a_write_register(TMP112A_CONFIG_REG, config_reg); return (status == I2C_STATUS_SUCCESS) ? TMP112A_STATUS_SUCCESS : TMP112A_STATUS_ERROR; } /*! \brief 退出关机模式 \param[in] none \param[out] none \retval tmp112a_status_t */ tmp112a_status_t tmp112a_wakeup(void) { uint16_t config_reg; i2c_status_t status; /* 读取当前配置 */ status = tmp112a_read_register(TMP112A_CONFIG_REG, &config_reg); if (status != I2C_STATUS_SUCCESS) { return TMP112A_STATUS_ERROR; } /* 清除关机位 */ config_reg &= ~TMP112A_CONFIG_SD; /* 写回配置 */ status = tmp112a_write_register(TMP112A_CONFIG_REG, config_reg); if (status != I2C_STATUS_SUCCESS) { return TMP112A_STATUS_ERROR; } /* 等待传感器启动 */ delay_ms(1); return TMP112A_STATUS_SUCCESS; } /*! \brief 单次转换 \param[in] none \param[out] result: 结果结构体指针 \retval tmp112a_status_t */ tmp112a_status_t tmp112a_one_shot(tmp112a_result_t *result) { uint16_t config_reg; i2c_status_t status; uint8_t timeout = 100; // 100ms超时 if (result == NULL) { return TMP112A_STATUS_INVALID_PARAM; } /* 读取当前配置 */ status = tmp112a_read_register(TMP112A_CONFIG_REG, &config_reg); if (status != I2C_STATUS_SUCCESS) { return TMP112A_STATUS_ERROR; } /* 启动单次转换 */ config_reg |= TMP112A_CONFIG_OS; status = tmp112a_write_register(TMP112A_CONFIG_REG, config_reg); if (status != I2C_STATUS_SUCCESS) { return TMP112A_STATUS_ERROR; } /* 等待转换完成 */ do { delay_ms(1); status = tmp112a_read_register(TMP112A_CONFIG_REG, &config_reg); if (status != I2C_STATUS_SUCCESS) { return TMP112A_STATUS_ERROR; } timeout--; } while ((config_reg & TMP112A_CONFIG_OS) && timeout > 0); if (timeout == 0) { return TMP112A_STATUS_TIMEOUT; } /* 读取转换结果 */ return tmp112a_read_temperature(result); } /*! \brief 获取状态字符串 \param[in] status: 状态码 \param[out] none \retval const char* 状态字符串 */ const char* tmp112a_get_status_string(tmp112a_status_t status) { switch (status) { case TMP112A_STATUS_SUCCESS: return "SUCCESS"; case TMP112A_STATUS_ERROR: return "ERROR"; case TMP112A_STATUS_TIMEOUT: return "TIMEOUT"; case TMP112A_STATUS_INVALID_PARAM: return "INVALID_PARAM"; case TMP112A_STATUS_OUT_OF_RANGE: return "OUT_OF_RANGE"; default: return "UNKNOWN"; } } /* Private Functions Implementation */ /*! \brief 写入寄存器 \param[in] reg_addr: 寄存器地址 \param[in] value: 写入值 \param[out] none \retval i2c_status_t */ static i2c_status_t tmp112a_write_register(uint8_t reg_addr, uint16_t value) { uint8_t data[2]; data[0] = (value >> 8) & 0xFF; data[1] = value & 0xFF; return i2c_write_16bits(TMP112A_ADDR, reg_addr, data); } /*! \brief 读取寄存器 \param[in] reg_addr: 寄存器地址 \param[out] value: 读取值指针 \retval i2c_status_t */ static i2c_status_t tmp112a_read_register(uint8_t reg_addr, uint16_t *value) { uint8_t data[2]; i2c_status_t status; if (value == NULL) { return I2C_STATUS_INVALID_PARAM; } status = i2c_read_16bits(TMP112A_ADDR, reg_addr, data); if (status == I2C_STATUS_SUCCESS) { *value = ((uint16_t)data[0] << 8) | data[1]; } return status; } /*! \brief 将原始数据转换为摄氏度 \param[in] raw_data: 原始数据 \param[out] none \retval float 温度值(°C) */ static float tmp112a_raw_to_celsius(uint16_t raw_data) { int16_t temp_raw; /* TMP112A使用12位分辨率,数据在高12位 */ temp_raw = (int16_t)(raw_data >> 4); /* 处理负数 */ if (temp_raw & 0x800) { temp_raw |= 0xF000; // 符号扩展 } /* 转换为摄氏度 */ return (float)temp_raw * TMP112A_TEMP_RESOLUTION; } /*! \brief 将摄氏度转换为原始数据 \param[in] temperature: 温度值(°C) \param[out] none \retval uint16_t 原始数据 */ static uint16_t tmp112a_celsius_to_raw(float temperature) { int16_t temp_raw; /* 转换为原始值 */ temp_raw = (int16_t)(temperature / TMP112A_TEMP_RESOLUTION); /* 移位到高12位 */ return (uint16_t)(temp_raw << 4); }