二分法查NTC温度表

在使用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)
  1. 二分法查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);
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,406评论 6 503
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,732评论 3 393
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,711评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,380评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,432评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,301评论 1 301
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,145评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,008评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,443评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,649评论 3 334
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,795评论 1 347
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,501评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,119评论 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,731评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,865评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,899评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,724评论 2 354

推荐阅读更多精彩内容

  • 姓名:仝启龙 学号:17101223413 本文转自 单片机公众号 【嵌牛导读】 AD程序我们经常是模仿别人已有...
    軒轅龍阅读 7,416评论 0 1
  • 选择题部分 1.(),只有在发生短路事故时或者在负荷电流较大时,变流器中才会有足够的二次电流作为继电保护跳闸之用。...
    skystarwuwei阅读 12,905评论 0 7
  • 专业考题类型管理运行工作负责人一般作业考题内容选项A选项B选项C选项D选项E选项F正确答案 变电单选GYSZ本规程...
    小白兔去钓鱼阅读 8,988评论 0 13
  • ** PT100是热敏电阻,使用中通过热敏电阻阻值变化来测算出被测温度;** 通常使用惠斯通电桥法电路来测量需要测...
    Ben2Feng阅读 22,657评论 1 2
  • 有去过越南的经历的朋友,除了当地的街道、环境以及庞大的摩托军团会留下深刻的印象外,还有一样应该不会忘记的,就是咖啡...
    陈居辉阅读 1,269评论 0 0