×
嵌入式 > 技术百科 > 详情

STM8L的NTC热敏检测

发布时间:2020-12-17 发布时间:
|

随手小记一下,如果有错误还望大佬指正。


至关重要的就是确定型号,程序其实没多少东西。


首先你要先确定你的热敏电阻的型号,如果你是从淘宝购买,可以去问客服。如果你不知道型号如何,可以列一个表,在STM中利用你的分压公式,计算出你的电阻在温度多少的时候,电阻是多少。程序在下方,如图。要想问参考温度怎么得到的,那就是用另一个温度传感器。

热敏电阻的电阻值是随着温度的变化而变化的,温度越高电阻越小。


static float temp_res[61] = {

43.1172,41.1663,39.3153,37.5587,35.891,

34.3074,32.8029,31.3734,30.0145,28.7225,

27.4936,26.3245,25.2119,24.1527,23.1442,

22.1835,21.2682,20.3959,19.5644,18.7714,

18.0151,17.2935,16.6048,15.9475,15.3198,

14.7203,14.1475,13.6003,13.0772,12.5771,

12.0988,11.6413,11.2037,10.7848,10.3839,

10,9.6324,9.2802,8.9428,8.6195,

8.3096,8.0124,7.7275,7.4541,7.1919,

6.9403,6.6987,6.4669,6.2442,6.0304,

5.825,5.6276,5.438,5.2557,5.0804,

4.9119,4.7498,4.5939,4.4439,4.2995,

4.1605

}; //数组的【0】代表-10摄氏度,数组最高到50摄氏度 每增加一个数就上升一度  对应的元素代表此温度下的电组值 以K为单位

建好数组后,就要想怎么将阻值采集出来,由于只能采集电压值,所以你要在外围搭建一个小电路,我才用的是串联分压,与10K电阻串联。在中点采集的电压即是这个电阻电压。

AD采集代码


void sys_adc_init(void)

{

  GPIO_DeInit(GPIOB);//复位GPIOB

  GPIO_Init(GPIOB,GPIO_Pin_0,GPIO_Mode_In_FL_No_IT);//初始化B0为浮空输入

  CLK_PeripheralClockConfig (CLK_Peripheral_ADC1,ENABLE);//开启ADC时钟

  ADC_Init (ADC1,ADC_ConversionMode_Single,ADC_Resolution_12Bit,ADC_Prescaler_1);//ADC1,单次采样,12位,1分频

  ADC_Cmd(ADC1,ENABLE);//ADC1使能

  ADC_ChannelCmd (ADC1,ADC_Channel_18,ENABLE);//ADC1 18通道使能  18通道是B0 通道号对应什么引脚在PDF里

}

 

u16 sys_adc_read(void)

{

  ADC_SoftwareStartConv (ADC1);//开启软件转换         

  while(!ADC_GetFlagStatus (ADC1,ADC_FLAG_EOC));//等待转换结束

  ADC_ClearFlag (ADC1,ADC_FLAG_EOC);//清除相关标识    

  return ADC_GetConversionValue (ADC1);

}

计算电阻公式


float compute_res(u16 adc_value) //计算对应ad值下的电阻值

{

  float res;

  res = (float)(10 * adc_value) / (float)(4095 - adc_value); //10是与热敏电阻串联的电阻大小 以K为单位

  return res;

}

进行电阻值在数组区间查询:


void find_temp(float real_res) //计算出电阻值后,用for循环查询估摸出处于哪个区间里。

{

  for(u8 i=0;i<61;i++) //正着数找到温度最大值

  {

    if(real_res > temp_res[i])

    {

      temp_max_flag = i;

      break;

    }

  }

  //其实这两个温度就是差1度,也可以temp_min_flag = temp_max_flag - 1;

  

  for(int8_t i=60;i>=0;i--)//倒着数找温度最小值

  {

    if(real_res < temp_res[i])

    {

      temp_min_flag = i;

      break;

    }

  }

}

 

//温度最低值

temp_min = -20 + temp_min_flag; //-20是最低温度

 真实温度计算:


/********************

 看看再这个温度区间里,真实的value占多少,一度这个区间的

相当于在这1度的区间内,将其线性化

********************/

    temp_real_region =  temp_res[temp_min_flag] - c; //c是计算的电阻值。

    temp_region =  temp_res[temp_min_flag] - temp_res[temp_max_flag];

    

    d = temp_real_region / temp_region;

    //真实温度就是最小温度,加上占的那区间的百分比

    temp = (float)temp_min + d; 

主函数:


void main(void)

{

  u16 u16_adc1_value;//记录每次采集的AD值

  int16_t temp_min;//当前阻值温度的可能的最小值

  float c,d;//防止直接给函数赋值失败,先让其计算一下

  float temp_real_region,temp_region,temp; //计算真实温度的变量

  

  sys_clock_init();//时钟初始化

  sys_adc_init();//AD初始化

  usart_init(115200);//串口初始化

  while (1)

  {    

      

    u16_adc1_value = sys_adc_read(); //取出电压值

    

    c = compute_res(u16_adc1_value);//计算

    

    find_temp(c);

    

    temp_min = -10 + temp_min_flag; //估摸一下温度准不准

    

    

    /********************

    看看再这个温度区间里,真实的value占多少,一度这个区间的

    ********************/

    temp_real_region =  temp_res[temp_min_flag] - c;

    temp_region =  temp_res[temp_min_flag] - temp_res[temp_max_flag];

    

    d = temp_real_region / temp_region;

    //真实温度就是最小温度,加上占的那区间的百分比

    temp = (float)temp_min + d; 

    

    

    mprintf("阻值value结果为: "); 

    mprintf("%dn",u16_adc1_value);

    mprintf("最高阻值为: ");

    mprintf("%fn",c);

    mprintf("最低温度为: ");

    mprintf("%dn",temp_min);

    mprintf("真实温度为: ");

    mprintf("%fn",temp);

  }

}


得到的结果:

经过电压表测量,AD值正确,电阻值正确, 经查表,温度值在电阻值区间内。




『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
NS推出采用第二代PowerWise技术的能源管理单元及先进电源控制器