В одном из проектов подключал термопару к 10-разрядному встроенному АЦП микроконтроллера. Предусилителдь собирал на zero-drift ОУ. Для компенсации холодного спая использовал цифровой термометр DS18B20. Линеаризацию и компенсацию CJ делал так:
Код
//----------------------------- Константы: -----------------------------------
#define ADC_RES 1023 //разрешение АЦП, квантов
#define ADC_REF 2500 //опорное напряжение АЦП, мВ
#define R_FB 100.0 //номинал резистора обратной связи ОУ, кОм
#define R_GND 1.0 //номинал резистора с инв. входа ОУ на землю, кОм
#define TCJ_K 40.0 //температурный коэффициент для CJ, мкВ/°C
#define TCJ_RES 0.1 //дискретность температуры холодного спая, °C
#define FIR_N (int)(TSAMPLE * 1E3 / T_SYS) //количество точек цифрового фильтра
#define GAIN ((R_FB + R_GND) / R_GND) //коэффициент усиления сигнала термопары
#define TC_V_MAX 24 //максимальное напряжение термопары, мВ
#define TC_POINTS (TC_V_MAX + 1) //количество точек таблицы
//Таблица линеаризации термопары K-типа. В таблице даны значения
//температуры в десятых долях градуса в зависимости от напряжения.
//Диапазон температур 0...+578.7°C.
//Шаг напряжения - 1 мВ, диапазон 0..+24 мВ:
const int __flash Lin[TC_POINTS] =
{
0, 250, 495, 736, 976, // 0.. 4 мВ
1220, 1466, 1715, 1965, 2215, // 5.. 9 мВ
2462, 2707, 2950, 3190, 3430, //10..14 мВ
3668, 3906, 4143, 4378, 4614, //15..19 мВ
4849, 5083, 5318, 5553, 5787 //20..24 мВ
};
//----------------------- Вычисление температуры: ----------------------------
int Convert(long code, int tcj)
{
//вычисление напряжения термопары в мкВ:
int Vtc = (((code * ADC_REF) / ADC_RES) * 1000L) / (long)(FIR_N * GAIN);
//вычисление эквивалентного напряжения холодного спая:
//делается приближение, что в диапазоне рабочих температур
//холодного спая коэффициент термопары постоянен
//tcj имеет дискретность TCJ_RES
//TC_K имеет размерность мкВ/°C
//Vcj представлено в мкВ
int Vcj = tcj * (int)(TCJ_K * TCJ_RES);
//вычисление напряжения термопары с компенсацией холодного спая:
int Vhj = Vtc + Vcj;
//получение целого числа милливольт:
signed char Index = Vhj / 1000;
//проверка выхода за диапазон вниз:
if(Index < 0) return(0);
//проверка выхода за диапазон вверх:
if(Index > TC_POINTS - 2) return(Lin[TC_POINTS - 1] + 1);
//чтение первой точки таблицы:
int p1 = Lin[Index];
//чтение второй точки таблицы:
int p2 = Lin[++Index];
//вычисление дельты на интервале 1 мВ:
int DeltaT = p2 - p1;
//вычисление дробной части милливольт:
int DeltaV = Vhj % 1000;
//линейная интерполяция по отрезку 1 мВ,
//p1 - температура в десятых градуса:
p1 = p1 + (long)DeltaV * DeltaT / 1000L;
return(p1);
}