1. 项目概述
TMP117AIDRVR是TI推出的一款医疗级高精度数字温度传感器,我在最近的一个便携式医疗监测设备项目中首次使用了这款芯片。相比常见的DS18B20或LM75,TMP117在精度和功耗方面都有显著提升,特别适合对温度测量要求苛刻的应用场景。
这个驱动方案基于STM32L4系列MCU的HAL库开发,通过I2C接口与传感器通信。选择STM32L4主要是因为其低功耗特性与TMP117完美匹配,整个系统在1Hz采样频率下平均工作电流可以控制在50μA以内,使用CR2032纽扣电池即可连续工作数月。
2. 硬件设计要点
2.1 电路连接方案
TMP117采用6引脚WSON封装(2mm×2mm),硬件连接非常简单:
code复制VDD ---- 3.3V
GND ---- GND
SCL ---- PB6(I2C1_SCL)
SDA ---- PB7(I2C1_SDA)
ADD0 -- GND(地址0x48)
ALERT -- NC(未使用)
注意:虽然TMP117支持1.8-5.5V宽电压供电,但为了与STM32L4兼容,建议使用3.3V供电。ADD0引脚接地将I2C地址设为0x48,接VDD则为0x49。
2.2 PCB布局注意事项
- 热耦合设计:传感器应远离MCU等发热元件,必要时可使用导热胶将TMP117与待测物体紧密接触
- 去耦电容:VDD引脚需就近放置0.1μF陶瓷电容
- 走线长度:I2C信号线长度建议控制在20cm以内,长距离传输需加330Ω上拉电阻
- ESD保护:在SDA/SCL线上串联100Ω电阻可提高ESD耐受能力
3. 软件驱动实现
3.1 HAL库I2C初始化
c复制I2C_HandleTypeDef hi2c1;
void MX_I2C1_Init(void)
{
hi2c1.Instance = I2C1;
hi2c1.Init.Timing = 0x00707CBB; // 400kHz
hi2c1.Init.OwnAddress1 = 0;
hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
hi2c1.Init.OwnAddress2 = 0;
hi2c1.Init.OwnAddress2Masks = I2C_OA2_NOMASK;
hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
if (HAL_I2C_Init(&hi2c1) != HAL_OK)
{
Error_Handler();
}
// 配置时钟源为SYSCLK
__HAL_RCC_I2C1_CLK_ENABLE();
}
3.2 TMP117寄存器定义
c复制#define TMP117_I2C_ADDR 0x48 << 1 // HAL库要求左移1位
// 寄存器地址
#define TEMP_RESULT_REG 0x00
#define CONFIG_REG 0x01
#define THIGH_LIMIT_REG 0x02
#define TLOW_LIMIT_REG 0x03
#define EEPROM_UL_REG 0x04
#define EEPROM1_REG 0x05
#define EEPROM2_REG 0x06
#define TEMP_OFFSET_REG 0x07
#define EEPROM3_REG 0x08
#define DEVICE_ID_REG 0x0F
// 配置寄存器选项
#define CONV_MODE_CONT 0x0000 // 连续转换模式
#define CONV_MODE_SHUT 0x0001 // 关断模式
#define CONV_MODE_ONE 0x0002 // 单次转换模式
#define AVG_1_SAMPLE 0x0000 // 1次平均
#define AVG_8_SAMPLES 0x0020 // 8次平均
#define AVG_32_SAMPLES 0x0040 // 32次平均
#define AVG_64_SAMPLES 0x0060 // 64次平均
3.3 温度读取函数实现
c复制float TMP117_ReadTemperature(void)
{
uint8_t rx_data[2];
int16_t temp_raw;
float temperature;
// 读取温度寄存器(2字节)
HAL_I2C_Mem_Read(&hi2c1, TMP117_I2C_ADDR, TEMP_RESULT_REG,
I2C_MEMADD_SIZE_8BIT, rx_data, 2, HAL_MAX_DELAY);
// 合并数据
temp_raw = (rx_data[0] << 8) | rx_data[1];
// 转换为实际温度(LSB=0.0078125°C)
temperature = temp_raw * 0.0078125f;
return temperature;
}
4. 高级功能实现
4.1 低功耗模式配置
对于电池供电设备,建议使用单次转换模式:
c复制void TMP117_SetSingleShotMode(void)
{
uint8_t config_data[2] = {0};
// 读取当前配置
HAL_I2C_Mem_Read(&hi2c1, TMP117_I2C_ADDR, CONFIG_REG,
I2C_MEMADD_SIZE_8BIT, config_data, 2, HAL_MAX_DELAY);
// 设置单次转换模式
config_data[1] &= ~0x03; // 清除模式位
config_data[1] |= CONV_MODE_ONE;
// 写回配置
HAL_I2C_Mem_Write(&hi2c1, TMP117_I2C_ADDR, CONFIG_REG,
I2C_MEMADD_SIZE_8BIT, config_data, 2, HAL_MAX_DELAY);
}
4.2 温度报警功能
通过配置THIGH和TLOW寄存器实现硬件报警:
c复制void TMP117_SetAlertLimits(float high, float low)
{
uint8_t limit_data[2];
int16_t high_raw = (int16_t)(high / 0.0078125f);
int16_t low_raw = (int16_t)(low / 0.0078125f);
// 设置高温阈值
limit_data[0] = (high_raw >> 8) & 0xFF;
limit_data[1] = high_raw & 0xFF;
HAL_I2C_Mem_Write(&hi2c1, TMP117_I2C_ADDR, THIGH_LIMIT_REG,
I2C_MEMADD_SIZE_8BIT, limit_data, 2, HAL_MAX_DELAY);
// 设置低温阈值
limit_data[0] = (low_raw >> 8) & 0xFF;
limit_data[1] = low_raw & 0xFF;
HAL_I2C_Mem_Write(&hi2c1, TMP117_I2C_ADDR, TLOW_LIMIT_REG,
I2C_MEMADD_SIZE_8BIT, limit_data, 2, HAL_MAX_DELAY);
// 启用ALERT引脚功能
uint8_t config_data[2];
HAL_I2C_Mem_Read(&hi2c1, TMP117_I2C_ADDR, CONFIG_REG,
I2C_MEMADD_SIZE_8BIT, config_data, 2, HAL_MAX_DELAY);
config_data[1] |= 0x04; // 设置ALERT极性(高电平有效)
config_data[0] |= 0x02; // 启用ALERT功能
HAL_I2C_Mem_Write(&hi2c1, TMP117_I2C_ADDR, CONFIG_REG,
I2C_MEMADD_SIZE_8BIT, config_data, 2, HAL_MAX_DELAY);
}
5. 校准与精度优化
5.1 温度偏移校准
TMP117提供温度偏移寄存器用于系统级校准:
c复制void TMP117_Calibrate(float offset)
{
uint8_t offset_data[2];
int16_t offset_raw = (int16_t)(offset / 0.0078125f);
offset_data[0] = (offset_raw >> 8) & 0xFF;
offset_data[1] = offset_raw & 0xFF;
HAL_I2C_Mem_Write(&hi2c1, TMP117_I2C_ADDR, TEMP_OFFSET_REG,
I2C_MEMADD_SIZE_8BIT, offset_data, 2, HAL_MAX_DELAY);
}
5.2 多采样平均配置
通过配置CONFIG寄存器的AVG位可提高测量稳定性:
c复制void TMP117_SetAveraging(uint8_t avg_mode)
{
uint8_t config_data[2];
HAL_I2C_Mem_Read(&hi2c1, TMP117_I2C_ADDR, CONFIG_REG,
I2C_MEMADD_SIZE_8BIT, config_data, 2, HAL_MAX_DELAY);
// 清除原有平均设置
config_data[1] &= ~0x60;
switch(avg_mode) {
case 8:
config_data[1] |= AVG_8_SAMPLES;
break;
case 32:
config_data[1] |= AVG_32_SAMPLES;
break;
case 64:
config_data[1] |= AVG_64_SAMPLES;
break;
default: // 默认1次
config_data[1] |= AVG_1_SAMPLE;
}
HAL_I2C_Mem_Write(&hi2c1, TMP117_I2C_ADDR, CONFIG_REG,
I2C_MEMADD_SIZE_8BIT, config_data, 2, HAL_MAX_DELAY);
}
6. 实际应用案例
6.1 医疗体温监测实现
c复制#define TEMP_MEASURE_INTERVAL 1000 // 1秒间隔
void MedicalTempMonitorTask(void)
{
static float temp_history[10];
static uint8_t index = 0;
float current_temp;
// 启动单次转换
TMP117_SetSingleShotMode();
// 等待转换完成(约15.5ms)
HAL_Delay(20);
// 读取温度
current_temp = TMP117_ReadTemperature();
// 存储历史数据
temp_history[index] = current_temp;
index = (index + 1) % 10;
// 计算平均体温
float avg_temp = 0;
for(int i=0; i<10; i++) {
avg_temp += temp_history[i];
}
avg_temp /= 10;
// 判断发烧警报
if(avg_temp > 37.5f) {
TriggerFeverAlarm();
}
}
6.2 环境温度监测方案
对于环境监测应用,可采用不同的配置策略:
c复制void EnvMonitor_Init(void)
{
// 设置8次平均,提高稳定性
TMP117_SetAveraging(8);
// 设置连续转换模式,1Hz速率
uint8_t config_data[2] = {0x00, 0x00};
config_data[1] = CONV_MODE_CONT | AVG_8_SAMPLES;
HAL_I2C_Mem_Write(&hi2c1, TMP117_I2C_ADDR, CONFIG_REG,
I2C_MEMADD_SIZE_8BIT, config_data, 2, HAL_MAX_DELAY);
// 设置温度报警范围(-10°C ~ 60°C)
TMP117_SetAlertLimits(60.0f, -10.0f);
}
7. 常见问题排查
7.1 I2C通信失败
症状:HAL_I2C函数返回HAL_ERROR或HAL_TIMEOUT
排查步骤:
- 检查硬件连接:确认VDD、GND、SCL、SDA连接正确
- 测量I2C信号:用示波器检查SCL/SDA波形是否正常
- 确认上拉电阻:通常4.7kΩ上拉,高速模式可减小到2.2kΩ
- 检查地址设置:确保ADD0引脚电平与代码中地址一致
7.2 温度读数异常
症状:温度值明显偏离实际值或跳变剧烈
解决方案:
- 检查电源质量:VDD纹波应小于50mV
- 避免热源干扰:传感器应远离MCU、LDO等发热元件
- 增加采样平均:使用TMP117_SetAveraging()提高稳定性
- 执行校准:使用已知温度源进行偏移校准
7.3 高功耗问题
症状:系统功耗高于预期值
优化措施:
- 使用单次转换模式:测量完成后自动进入休眠
- 延长采样间隔:根据应用需求调整测量频率
- 关闭不用的功能:如禁用ALERT引脚
- 检查I2C总线:确保没有持续的总线活动
8. 性能优化技巧
- 中断驱动设计:利用ALERT引脚中断代替轮询,进一步降低MCU功耗
- 温度补偿算法:针对非线性误差,可在软件中实现二次补偿
- EEPROM利用:将校准参数存储在TMP117内置EEPROM中
- 动态精度调整:根据应用场景动态切换采样率和平均次数
- 数据滤波处理:在软件中实现移动平均或卡尔曼滤波算法
通过实际项目验证,这套驱动方案在医疗体温计应用中实现了±0.05°C的测量稳定性,系统待机电流控制在15μA以下,完全满足医疗设备的苛刻要求。对于需要更高精度的场合,建议使用64次平均模式并配合软件滤波算法。
