4. 温度采集模块实现
任务说明
本案例实现BMS(电池管理系统)中的多点温度采集模块,支持最多8个温度传感器通道,完成温度读取、开路/短路故障检测,并对采集到的有效温度执行一致性检查——当最高与最低温度差值超过设定阈值(默认5℃)时,判定为温度不一致并输出告警。
模块设计
温度采集模块由三部分组成:传感器驱动抽象层(模拟NTC热敏电阻经ADC转换后的数字量)、温度计算与滤波(将ADC值转换为摄氏度,并做一阶低通滤波)、一致性检查逻辑(比较各通道有效温度极差)。模块对外提供初始化、单次采集、一致性检查三个接口。
代码实现
// temp_module.h
#ifndef TEMP_MODULE_H
#define TEMP_MODULE_H
#include <stdint.h>
#include <stdbool.h>
#define TEMP_MAX_CHANNELS 8
#define TEMP_ADC_FULL_SCALE 4095.0f
#define TEMP_CONSIST_THRESH 5.0f // 一致性阈值(℃)
#define TEMP_INVALID (-100.0f) // 无效温度标记
typedef struct {
float temp_c[TEMP_MAX_CHANNELS]; // 滤波后温度
bool fault[TEMP_MAX_CHANNELS]; // true=开路/短路故障
uint8_t valid_cnt; // 有效通道数
float max_temp; // 有效通道最高温
float min_temp; // 有效通道最低温
bool inconsistent; // 一致性检查结果
} TempModule_t;
void Temp_Init(TempModule_t *mod);
void Temp_ProcessChannel(TempModule_t *mod, uint8_t ch, uint16_t adc_raw);
void Temp_ConsistencyCheck(TempModule_t *mod);
#endif
// temp_module.c
#include "temp_module.h"
#define TEMP_ALPHA 0.2f // 一阶低通滤波系数
// NTC查表:ADC值 -> 温度(℃),稀疏表+线性插值
static const uint16_t adc_table[] = {400, 800, 1200, 1600, 2000, 2400, 2800, 3200, 3600};
static const float temp_table[] = {60.0f, 50.0f, 41.0f, 33.0f, 26.0f, 20.0f, 15.0f, 11.0f, 8.0f};
#define TABLE_SIZE (sizeof(adc_table)/sizeof(adc_table[0]))
static float adc_to_temp(uint16_t adc) {
if (adc <= adc_table[0]) return temp_table[0];
if (adc >= adc_table[TABLE_SIZE-1]) return temp_table[TABLE_SIZE-1];
for (uint8_t i = 0; i < TABLE_SIZE-1; i++) {
if (adc >= adc_table[i] && adc < adc_table[i+1]) {
float ratio = (float)(adc - adc_table[i]) / (adc_table[i+1] - adc_table[i]);
return temp_table[i] + ratio * (temp_table[i+1] - temp_table[i]);
}
}
return temp_table[TABLE_SIZE-1];
}
void Temp_Init(TempModule_t *mod) {
for (uint8_t i = 0; i < TEMP_MAX_CHANNELS; i++) {
mod->temp_c[i] = 25.0f; // 默认25℃
mod->fault[i] = false;
}
mod->valid_cnt = 0;
mod->max_temp = TEMP_INVALID;
mod->min_temp = TEMP_INVALID;
mod->inconsistent = false;
}
void Temp_ProcessChannel(TempModule_t *mod, uint8_t ch, uint16_t adc_raw) {
if (ch >= TEMP_MAX_CHANNELS) return;
// 故障检测:开路≈4095,短路≈0(含2%裕量)
if (adc_raw >= 4015 || adc_raw <= 80) {
mod->fault[ch] = true;
mod->temp_c[ch] = TEMP_INVALID;
return;
}
mod->fault[ch] = false;
// 查表得到瞬时温度,再做一阶低通滤波
float instant = adc_to_temp(adc_raw);
mod->temp_c[ch] = mod->temp_c[ch] + TEMP_ALPHA * (instant - mod->temp_c[ch]);
}
void Temp_ConsistencyCheck(TempModule_t *mod) {
mod->valid_cnt = 0;
mod->max_temp = TEMP_INVALID;
mod->min_temp = TEMP_INVALID;
for (uint8_t i = 0; i < TEMP_MAX_CHANNELS; i++) {
if (mod->fault[i]) continue; // 故障通道不参与
if (mod->valid_cnt == 0) {
mod->max_temp = mod->min_temp = mod->temp_c[i];
} else {
if (mod->temp_c[i] > mod->max_temp) mod->max_temp = mod->temp_c[i];
if (mod->temp_c[i] < mod->min_temp) mod->min_temp = mod->temp_c[i];
}
mod->valid_cnt++;
}
// 有效通道数≥2才做一致性判定
if (mod->valid_cnt >= 2) {
mod->inconsistent = ((mod->max_temp - mod->min_temp) > TEMP_CONSIST_THRESH);
} else {
mod->inconsistent = false; // 有效通道不足,不告警
}
}
// main.c 示例调用
#include <stdio.h>
#include "temp_module.h"
int main(void) {
TempModule_t bms_temp;
Temp_Init(&bms_temp);
// 模拟一轮采集:8个通道的ADC原始值
uint16_t adc_samples[TEMP_MAX_CHANNELS] = {
1800, // 约29℃
1850, // 约28℃
4090, // 开路故障
1750, // 约30℃
1900, // 约27℃
50, // 短路故障
1820, // 约29℃
3000 // 约13℃(明显偏低)
};
for (uint8_t ch = 0; ch < TEMP_MAX_CHANNELS; ch++) {
Temp_ProcessChannel(&bms_temp, ch, adc_samples[ch]);
}
Temp_ConsistencyCheck(&bms_temp);
// 打印结果
printf("有效通道数: %u\n", bms_temp.valid_cnt);
for (uint8_t i = 0; i < TEMP_MAX_CHANNELS; i++) {
if (bms_temp.fault[i])
printf("CH%u: 故障\n", i);
else
printf("CH%u: %.1f℃\n", i, bms_temp.temp_c[i]);
}
if (bms_temp.valid_cnt >= 2) {
printf("最高温: %.1f℃, 最低温: %.1f℃, 极差: %.1f℃\n",
bms_temp.max_temp, bms_temp.min_temp,
bms_temp.max_temp - bms_temp.min_temp);
}
printf("一致性检查: %s\n", bms_temp.inconsistent ? "不一致(告警)" : "一致");
return 0;
}
编译与运行
# 将上述三个文件置于同一目录,执行:
gcc -Wall -std=c99 main.c temp_module.c -o temp_module
./temp_module
验证方法与判定标准
运行程序后,观察输出:
- CH2(ADC=4090)与CH5(ADC=50)应显示“故障”,不参与温度统计;
- 有效通道数为6,最高温约30℃(CH3),最低温约13℃(CH7),极差约17℃,超过5℃阈值;
- 最终输出“一致性检查: 不一致(告警)”。
若将CH7的ADC值改为1800(约29℃),重新编译运行,则极差约3℃,应输出“一致性检查: 一致”。
判定标准:程序能正确识别开路/短路故障,有效通道统计准确,一致性判定结果与上述预期一致,即视为通过。