在使用ADC采样温度值时,我们有3种思想去设计程序
1)excel拟合个函数 2)程序线性查值 3)直接用经验公式
今天主要分享查表的方法
1.NTC温度对应的ADC值查找表
// R25=10k,B=3950,Rup=10k,ADC=12bit
static const uint16_t cNTCTable[] = {
3887, 3874, 3860, 3845, 3830, 3813, 3796, 3778, 3760, 3740, // -29~-20
3720, 3698, 3676, 3653, 3629, 3604, 3578, 3551, 3524, 3495, // -19~-10
3465, 3435, 3403, 3371, 3337, 3303, 3267, 3231, 3194, 3156, // -9~0
3118, 3078, 3038, 2997, 2955, 2913, 2870, 2826, 2782, 2738, // 1~10
2693, 2648, 2602, 2556, 2510, 2464, 2417, 2371, 2324, 2278, // 11~20
2231, 2185, 2139, 2093, 2048, 2002, 1957, 1913, 1868, 1825, // 21~30
1781, 1739, 1697, 1655, 1614, 1574, 1534, 1495, 1456, 1419, // 31~40
1382, 1346, 1310, 1275, 1241, 1208, 1175, 1143, 1112, 1081, // 41~50
1052, 1023, 994, 967, 940, 914, 888, 863, 839, 815, // 51~60
792, 770, 748, 727, 707, 687, 668, 649, 631, 613, // 61~70
596, 579, 563, 547, 532, 517, 502, 488, 475, 462, // 71~80
449, 436, 424, 413, 401, 390, 380, 369, 359, 350, // 81~90
340, 331, 322, 314, 305, 297, 289, 282, 274, 267, // 91~100
260, 253, 247, 240, 234, 228, 222, 217, 211, 206 // 101~110
};
2.宏定义
// NCT温度表数目
#define NTC_TABLE_COUNT (sizeof(cNTCTable) / sizeof(cNTCTable[0]))
// NTC温度表起始温度
#define NTC_TABLE_T_FIRST (-29)
- 二分法查NTC温度表
static uint8_t NTC_SearchTable(uint16_t adc_val)
{
uint8_t s_idx, m_idx, e_idx;
uint16_t m_val;
// 检查数据合法性
if (adc_val > cNTCTable[0] || adc_val < cNTCTable[NTC_TABLE_COUNT - 1]) {
return 0xff;
}
s_idx = 0;
e_idx = NTC_TABLE_COUNT - 1;
// 二分法查找
while (s_idx + 1 < e_idx) {
m_idx = (s_idx + e_idx) >> 1;
m_val = cNTCTable[m_idx];
if (adc_val < m_val) {
s_idx = m_idx;
} else if (adc_val > m_val) {
e_idx = m_idx;
} else {
return m_idx;
}
}
return s_idx;
}
4./测量NTC和固定电阻分压
static uint16_t NTC_ADCConv(void)
{
uint16_t val;
// Enable ADC1 clock
CLK_PeripheralClockConfig(CLK_Peripheral_ADC1, ENABLE);
ADC_DeInit(ADC1);
// Initialise and configure ADC1
ADC_Init(ADC1, ADC_ConversionMode_Single, ADC_Resolution_12Bit, ADC_Prescaler_1);
// ADC_CLK=2MHz, SamplingTime=8us
ADC_SamplingTimeConfig(ADC1, ADC_Group_SlowChannels, ADC_SamplingTime_16Cycles);
// Enable ADC1
ADC_Cmd(ADC1, ENABLE);
// Enable ADC1 Channel 14
ADC_ChannelCmd(ADC1, ADC_Channel_14, ENABLE);
// Start ADC1 Conversion using Software trigger
ADC_SoftwareStartConv(ADC1);
while (ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET);
val = ADC_GetConversionValue(ADC1);
ADC_Cmd(ADC1, DISABLE);
CLK_PeripheralClockConfig(CLK_Peripheral_ADC1, DISABLE);
return val;
}
5.初始化IO
void NTC_Init(void)
{
// PB4, ADC1_IN14
GPIO_Init(GPIOB, GPIO_Pin_4, GPIO_Mode_In_FL_No_IT);
}
6.取得温度
// 参数:返回温度整数部分,返回温度小数部分
// 返回:是否获取温度成功
bool NTC_GetT(int8_t *t_z, uint8_t *t_f)
{
uint16_t adc_val;
uint8_t idx;
const uint16_t *pt;
adc_val = NTC_ADCConv();
idx = NTC_SearchTable(adc_val);
if (idx == 0xff) {
return FALSE;
}
pt = cNTCTable + idx;
*t_z = idx + NTC_TABLE_T_FIRST;
*t_f = (*pt - adc_val) * 10 / (*pt - *(pt + 1));
return TRUE;
}
采样电阻值和实际温度值对应(两个数组影射)
#define Res1 10000 //10K
#define BValue 3950
float Rt,Voltage,Temperature;
#define TEMP_NUM 241
int nuiTempTab[TEMP_NUM]=
{
95337,92655,90058,87540,85100,82736,80444,78222,76068,73980,
71955,69992,68088,66241,64449,62712,61026,59390,57803,56263,
54769,53318,51911,50544,49217,47929,46679,45464,44285,43140,
42027,40947,39897,38878,37887,36924,35989,35080,34196,33337,
32503,31691,30902,30135,29389,28664,27959,27273,26605,25956,
25325,24711,24113,23532,22966,22415,21879,21357,20850,20355,
19874,19406,18950,18506,18073,17652,17242,16842,16453,16074,
15704,15345,14994,14652,14319,13995,13679,13371,13070,12777,
12492,12213,11942,11677,11419,11168,10922,10683,10449,10222,
10000,9783,9571,9365,9164,8967,8776,8588,8406,8228,8054,7884,
7718,7556,7398,7244,7093,6946,6802,6662,6525,6391,6260,6132,
6007,5885,5766,5650,5536,5425,5316,5210,5106,5004,4905,4808,
4714,4621,4530,4442,4355,4270,4187,4106,4027,3950,3874,3800,
3727,3656,3587,3519,3452,3387,3323,3261,3200,3140,3082,3025,
2969,2914,2860,2808,2756,2706,2657,2608,2561,2515,2470,2425,
2382,2339,2297,2256,2216,2177,2139,2101,2064,2028,1992,1958,
1924,1890,1857,1825,1794,1763,1733,1703,1674,1646,1618,1591,
1564,1537,1512,1486,1461,1437,1413,1390,1367,1344,1322,1300,
1279,1258,1238,1218,1198,1178,1159,1141,1122,1105,1087,1070,
1053,1036,1019,1003,988,972,957,942,927,913,899,885,871,858,
845,832,819,806,794,782,770,759,747,736,725,714,703,693,683,
672,663,
};
int trueTempTab[TEMP_NUM]=
{
-200,-195,-190,-185,-180,-175,-170,-165,-160,-155,
-150,-145,-140,-135,-130,-125,-120,-115,-110,-105,
-100,-95,-90,-85,-80,-75,-70,-65,-60,-55,-50,-45,
-40,-35,-30,-25,-20,-15,-10,-05,00,05,10,15,20,25,
30,35,40,45,50,55,60,65,70,75,80,85,90,95,100,105,
110,115,120,125,130,135,140,145,150,155,160,165,170,
175,180,185,190,195,200,205,210,215,220,225,230,235,
240,245,250,255,260,265,270,275,280,285,290,295,300,
305,310,315,320,325,330,335,340,345,350,355,360,365,
370,375,380,385,390,395,400,405,410,415,420,425,430,
435,440,445,450,455,460,465,470,475,480,485,490,495,
500,505,510,515,520,525,530,535,540,545,550,555,560,
565,570,575,580,585,590,595,600,605,610,615,620,625,
630,635,640,645,650,655,660,665,670,675,680,685,690,
695,700,705,710,715,720,725,730,735,740,745,750,755,
760,765,770,775,780,785,790,795,800,805,810,815,820,
825,830,835,840,845,850,855,860,865,870,875,880,885,
890,895,900,905,910,915,920,925,930,935,940,945,950,
955,960,965,970,975,980,985,990,995,1000,
};
int CalcTemp(int nuiResVal)
{
int temperature;
int k;
int m;
int nuiTempMin = 0;
int nuiTempMax = TEMP_NUM;
int nuiMidVal = 0;
while(nuiResVal >= nuiTempTab[nuiTempMax])
{
nuiMidVal = (nuiTempMax + nuiTempMin) / 2;
if((nuiMidVal == nuiTempMin) || (nuiMidVal == nuiTempMax))
{
break;
}
if(nuiResVal >= nuiTempTab[nuiMidVal])
{
nuiTempMax = nuiMidVal;
}
else
{
nuiTempMin = nuiMidVal;
}
}
if (nuiResVal == nuiTempTab[nuiTempMin])
{
return trueTempTab[nuiTempMin];
}
if (nuiResVal == nuiTempTab[nuiTempMax])
{
return trueTempTab[nuiTempMax];
}
k = nuiTempTab[nuiTempMin] - nuiTempTab[nuiTempMax];
m = (trueTempTab[nuiTempMax] - trueTempTab[nuiTempMin]) * (nuiResVal - nuiTempTab[nuiTempMax]) / k;
temperature = trueTempTab[nuiTempMin] + m;
return temperature;
}
Voltage=(float)ADC_ConvertedValue*(3.3/4096);
Rt=(Res1*(float)ADC_ConvertedValue)/(4096-(float)ADC_ConvertedValue);
Temperature = CalcTemp(Rt);
printf("\r\n 电压值%f \r\n",Voltage);
printf("\r\n 电阻值%f \r\n",Rt/1000);
printf("\r\n AD值%d \r\n",ADC_ConvertedValue);
printf("\r\n 温度值%f\r\n",Temperature/10);
网友评论