做温控器,传感器采用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;
}
PS: 经过几年的小积累,本电工的小公司开张接客啦!目前做电子项目开发,温控器,记录仪,工业现场总线采集模块产品,有需要的朋友,加qq:741684134 !!!