NTC查表法,採用二分法

做溫控器,傳感器採用NTC熱敏電阻,前幾年做的代碼,爲了省事方便,直接採用查詢方法,從頭到尾查詢一邊,一個200個元素的一維數組,例如NTC_ADC_TAB[200],最多要查詢200次!方法很笨!

對於強迫症的工程師來說,這是個打心眼裏彆扭的事情,就像穿西裝,打領帶這麼彆扭!

最近項目不忙,對溫控器的代碼做了優化重構,順便把溫度查表函數做了優化更改,採用二分法,效率顯著提升,廢話不多,SHOW THE CODE:
————————————————
 

以下代碼採用編程平臺:IAR FOR STM8
硬件平臺:stm8l152
ADC分辨率:12位
已經在產品上驗證並批量出貨!PS:做一個靠譜的網友!
 
/*********************** 宏定義 *********************************/
#define NTC_ADC_MAX    201
 
/**************** NTC熱敏電阻轉換成ADC的值 ***********************/
const uint16_t NTC_ADC_Tab[NTC_ADC_MAX]={
    2559 ,2555 ,2551 ,2546 ,2542 ,2538 ,2534 ,2529 ,2525 ,2521 ,// 25.0~25.9 ℃
    2517 ,2513 ,2508 ,2504 ,2500 ,2496 ,2491 ,2487 ,2483 ,2479 ,// 26.0~26.9 ℃
    2474 ,2470 ,2466 ,2461 ,2457 ,2453 ,2449 ,2444 ,2440 ,2436 ,// 27.0~27.9 ℃
    2432 ,2427 ,2423 ,2419 ,2415 ,2410 ,2406 ,2402 ,2397 ,2393 ,// 28.0~28.9 ℃
    2389 ,2385 ,2380 ,2376 ,2372 ,2368 ,2363 ,2359 ,2355 ,2350 ,// 29.0~29.9 ℃
    2346 ,2342 ,2338 ,2333 ,2329 ,2325 ,2320 ,2316 ,2312 ,2308 ,// 30.0~30.9 ℃
    2303 ,2299 ,2295 ,2291 ,2286 ,2282 ,2278 ,2273 ,2269 ,2265 ,// 31.0~31.9 ℃
    2261 ,2256 ,2252 ,2248 ,2243 ,2239 ,2235 ,2231 ,2226 ,2222 ,// 32.0~32.9 ℃
    2218 ,2214 ,2209 ,2205 ,2201 ,2196 ,2192 ,2188 ,2184 ,2179 ,// 33.0~33.9 ℃
    2175 ,2171 ,2167 ,2162 ,2158 ,2154 ,2150 ,2145 ,2141 ,2137 ,// 34.0~34.9 ℃
    2133 ,2128 ,2124 ,2120 ,2116 ,2111 ,2107 ,2103 ,2099 ,2095 ,// 35.0~35.9 ℃
    2090 ,2086 ,2082 ,2078 ,2073 ,2069 ,2065 ,2061 ,2057 ,2052 ,// 36.0~36.9 ℃
    2048 ,2044 ,2040 ,2036 ,2031 ,2027 ,2023 ,2019 ,2015 ,2010 ,// 37.0~37.9 ℃
    2006 ,2002 ,1998 ,1994 ,1990 ,1985 ,1981 ,1977 ,1973 ,1969 ,// 38.0~38.9 ℃
    1965 ,1960 ,1956 ,1952 ,1948 ,1944 ,1940 ,1936 ,1932 ,1927 ,// 39.0~39.9 ℃
    1923 ,1919 ,1915 ,1911 ,1907 ,1903 ,1899 ,1895 ,1890 ,1886 ,// 40.0~40.9 ℃
    1882 ,1878 ,1874 ,1870 ,1866 ,1862 ,1858 ,1854 ,1850 ,1846 ,// 41.0~41.9 ℃
    1842 ,1838 ,1833 ,1829 ,1825 ,1821 ,1817 ,1813 ,1809 ,1805 ,// 42.0~42.9 ℃
    1801 ,1797 ,1793 ,1789 ,1785 ,1781 ,1777 ,1773 ,1769 ,1765 ,// 43.0~43.9 ℃
    1761 ,1757 ,1753 ,1750 ,1746 ,1742 ,1738 ,1734 ,1730 ,1726 ,// 44.0~44.9 ℃
    1722 ,// 45 ℃
};
 
/**
  * @brief  二分法查表法,得出單路溫度值
  * @param  pos
  * @retval TempSingleValue
  */
uint16_t get_single_temp(uint8_t pos)
{
    uint16_t    End = NTC_ADC_MAX - 1;// 數組下標最後一個數
    uint16_t    Front = 0;// 數組第一個數
    uint8_t     half = 0;
    uint16_t    TempSingleADC = 0;// 單次轉換的ADC值
    uint16_t    TempSingleValue = 0;// 單次換算成的溫度值,用來函數返回值;
 
    ADC_Channel_TypeDef    ADC_Channel_X = ADC_Channel_0;
    
    switch(pos)
    {
        case 0:
          ADC_Channel_X = ADC_Channel_0;
          break;
        case 1:
          ADC_Channel_X = ADC_Channel_1;
          break;
        case 2:
          ADC_Channel_X = ADC_Channel_2;
          break;
        default :
          break;
    }
    
    /* Enable ADC1 clock */
    CLK_PeripheralClockConfig(CLK_Peripheral_ADC1, ENABLE);
 
    /* Initialize and configure ADC1 */
    ADC_Init(ADC1, ADC_ConversionMode_Continuous, ADC_Resolution_12Bit, ADC_Prescaler_2);
 
    /* ADC channel used for IDD measurement */
    ADC_SamplingTimeConfig(ADC1, ADC_Group_FastChannels, ADC_SamplingTime_192Cycles);
 
    /* Enable ADC1 */
    ADC_Cmd(ADC1, ENABLE);
    Delay(500);
 
    /* Disable SchmittTrigger for ADC_Channel, to save power */
    ADC_SchmittTriggerConfig(ADC1, ADC_Channel_X, DISABLE);
 
    /* Enable ADC1 Channel used for LAD measurement */
    ADC_ChannelCmd(ADC1, ADC_Channel_X, ENABLE);
    Delay(500);
    ADC_SoftwareStartConv (ADC1);//開啓軟件轉換
 
    while(!ADC_GetFlagStatus (ADC1,ADC_FLAG_EOC));//等待轉換結束
    ADC_ClearFlag (ADC1,ADC_FLAG_EOC);//清除相關標識
    TempSingleADC = ADC_GetConversionValue (ADC1);//獲取轉換值;
    //TempSingleADC = 1722;// 調試二分法查表用的臨時賦值,調試代碼用;
    
    /* DeInitialize ADC1 */
    ADC_DeInit(ADC1);
    /* Disable ADC1 clock */
    CLK_PeripheralClockConfig(CLK_Peripheral_ADC1, DISABLE);
    ADC_ChannelCmd(ADC1, ADC_Channel_X, DISABLE); 
 
    /**********二分法查表求溫度值*********/
    if((TempSingleADC <= NTC_ADC_Tab[0])&&(TempSingleADC >= NTC_ADC_Tab[NTC_ADC_MAX-1]))
    {
        for(half=100;End-Front != 1;)
        {
            if(TempSingleADC > NTC_ADC_Tab[half])
            {
                End = half;
                half = (End + Front)/2;
            }
            else if(TempSingleADC < NTC_ADC_Tab[half])
            {
                Front = half;
                half = (Front + End)/2;
            }
            else// 正好等於表格中的值
            {
                TempSingleValue = 2500+half*10+(NTC_ADC_Tab[half]-TempSingleADC)*10/(NTC_ADC_Tab[half]-NTC_ADC_Tab[half+1]);
                break;
            }
        }
        if(End-Front == 1)// 在表格兩個值之間的數
        {
            TempSingleValue = 2500+half*10+(NTC_ADC_Tab[half]-TempSingleADC)*10/(NTC_ADC_Tab[half]-NTC_ADC_Tab[half+1]);
        }
    }
    else
    {
        TempSingleValue = 0;          // 溫度超出數組範圍,就返回0度
    }
    return TempSingleValue;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章