STC单片机测8路NTC测温度

            
1.    单片机型号:STC15F2K32S2,NTC电阻,内部自带ADC检测ADC,

2.    怎么样把ADC值转为温度是最容易让大家不知从何下手,有查表等思路,但是我自己分析的不是查表,查表速度慢,单片机内存也只有那么大,我选择的方法是ADC值和温度直接联系,我下午特意去奶茶店找了一点冰块,来测了几十个点的温度,然后建立ADC值与温度的关系,参考温度是胜利万用表的温度。STC单片机测8路NTC测温度_第1张图片

注意:这个地方测ADC值不要测一段连续的温度的ADC值(要分点测试比如,16,18,20等 ),相信你有更好的办法,我测高温度是用热水测得,低温度是在奶茶店找的冰测得。


3.我们用的分析软件是新建 Excel 表

STC单片机测8路NTC测温度_第2张图片STC单片机测8路NTC测温度_第3张图片STC单片机测8路NTC测温度_第4张图片STC单片机测8路NTC测温度_第5张图片STC单片机测8路NTC测温度_第6张图片STC单片机测8路NTC测温度_第7张图片

注意:这个数据曲线不是随便乱选的,你测了那么多点,你要看经过的点最多的,当然不可能是性线关系,这个要根据你自己的数据去分析,你公式出来了,然后用C语言可以把这个每一个温度的ADC值算出来,然后用NTC电阻测几个温度对比一下我们得出来公式的。我的参考温度还是是胜利万用表测出来的温度。

STC单片机测8路NTC测温度_第8张图片

如以上还有不懂的,可以加我QQ:2681075556

/* ***************************************************** */
// 工  程   : my
// 文件名   : main.c
// 处理器   : STC
// 编译环境 : Keil4 C51 
// 系统时钟 : 内部自带22.1184MHZ
// 版    本	: V1.0 
// 生成日期	: 2017-005-02	  					
// 修改日期	:  
// 简单描述 : 八路NTC温度
// 开发人才 :Made in Liu Ren fu(大白菜)
/* ***************************************************** */
#include 
#include "adc.h"
#include "lcd12864.h"
#include "uart.h"
#include "math.h"
#include "key.h"
/******************全局变量***********************/
u16 tab[8]={0};	//存储ADC值
float ADC_Value[8]={0};//存储温度
u8 L_num[8]={15,15,15,15,15,15,15,15}; //设置低报警温度值,默认
u8 H_num[8]={40,40,40,40,40,40,40,40}; //设置高报警温度值
/************************************************/

sbit OE1_573 = P2^7;
sbit OE2_573 = P4^6;
sbit OE3_573 = P4^5;


//========================================================================
// 函数: void IO_Inti()
// 描述: 初始化IO
// 参数: ch:选择要转换的ADC通道
//========================================================================
void IO_Inti()
{
	P0M1=0;
	P0M0=0XFF;
	P1M1 = 0Xff;
	P1M0 = 0X00;
	P2M1=0;
	P2M0=0;
	P3M1=0;
	P3M0=0;
	P4M1=0;
	P4M0=0;
	P5M1=0;
	P5M0=0;
}

//========================================================================
// 函数: float Get_Temperature(u8 ch)
// 描述: (log(y)-log(635.69))/-0.029=x
// 参数: ch:选择要转换的ADC通道
//========================================================================
float Get_Temperature(u8 ch)
{
	 const float  XS = 635.69;
	 u16 ADC_V=0;
	 float temp = Get_ADC10bitResult(ch);
	 temp = log(temp);
	 temp -= log(XS);
	 temp /= -0.029; 

	 return temp;
}

//========================================================================
// 函数: int  filter(u8 ch) 
// 描述: 软件滤波
// 参数: ch滤波值
//========================================================================
#define N 12 
int  filter(u8 ch) 
{ 
		float sum = 0;
		u8 count=0;
		for(count=0;count 1))//判断高报警位按键与是否可以设置温度  
{
		 DelayMS(2);//延时消抖
		 if((SW2 == 0) && (flag_1 > 1))//判断高报警位按键与是否可以设置温度
		 {
		  while(!SW2);//松手检测
		  switch(flag_1)
		  {
		  	case 2:H_num[0]++;
				if(H_num[0]==99)
				{
				  H_num[0]=30;
				}break;	
			case 3:H_num[1]++;
				if(H_num[1]==99)
				{
				  H_num[1]=30;
				}break;
			case 4:H_num[2]++;
				if(H_num[2]==99)
				{
				  H_num[2]=30;
				}break;
			case 5:H_num[3]++;
				if(H_num[3]==99)
				{
				  H_num[3]=30;
				}break;	
			case 6:H_num[4]++;
				if(H_num[4]==99)
				{
				  H_num[4]=30;
				}break;
		  	case 7:H_num[5]++;
				if(H_num[5]==99)
				{
				  H_num[5]=30;
				}break;		
			case 8:H_num[6]++;
				if(H_num[6]==99)
				{
				  H_num[6]=30;
				}break;
			case 9:H_num[7]++;
				if(H_num[7]==99)
				{
				  H_num[7]=30;
				}break;
			default:break;
		  }	
      }
}   
 ///////////////////////////////////////
if((SW3 == 0) && (flag_1 > 1))//判断低报警位按键与是否可以设置温度  
{
		 DelayMS(2);//延时消抖
		 if((SW3 == 0) && (flag_1 > 1))//判断低报警位按键与是否可以设置温度 
		 {
		  while(!SW3); //松手检测
		  switch(flag_1)
		  {
		  	case 2:L_num[0]--;
				if(L_num[0]==0)
				{
				  L_num[0]=30;
				}break;	
			case 3:L_num[1]--;
				if(L_num[1]==0)
				{
				  L_num[1]=30;
				}break;
			case 4:L_num[2]--;
				if(L_num[2]==0)
				{
				  L_num[2]=30;
				}break;
			case 5:L_num[3]--;
				if(L_num[3]==0)
				{
				  L_num[3]=30;
				}break;	
			case 6:L_num[4]--;
				if(L_num[4]==0)
				{
				  L_num[4]=30;
				}break;
		  	case 7:L_num[5]--;
				if(L_num[5]==0)
				{
				  L_num[5]=30;
				}break;		
			case 8:L_num[6]--;
				if(L_num[6]==0)
				{
				  L_num[6]=30;
				}break;
			case 9:L_num[7]--;
				if(L_num[7]==0)
				{
				  L_num[7]=30;
				}break;
			default:break;
		  }	
      } 
  }
/////////////////////////////
	 if(SW4 == 0)//判断是否有按键按下
	 {
		 DelayMS(1);//延时消抖
		 if(SW4 == 0)//判断是否有按键按下
		 {
		 	  while(!SW1);//松手检测
			  TR1=1;
		  }

	  }
}

void main()
{
	

	IO_Inti();	//IO初始化
	LCD_inti();//初始化LCD12864
	Timer1Init();//初始化定时器1
	Timer0Init();//初始化定时器0
	UART_init();//初始化串口														   
	AD_Inti();	//ADC初始化
	while(1)
	{ 	
	  Control_KEY();//按键检测
	  UART_Test();	//ADC读取
	  if((L_num[0] >= ADC_Value[0])) //温度少于设定低温度是加热水
	  {
	  	  OE1_573 = 1;//打开573使能端
		  OE2_573 = 0;//573使关闭能端
		  P0 = 0xef;
	  }
	  if((H_num[0] <= ADC_Value[0])) //温度大于设定高温度是加冷水
	  {
	  	  OE1_573 = 0;//打开573使能端
		  OE2_573 = 1;//573使关闭能端
		  P0 = 0xef;
	  }
	}	
}


void tm0() interrupt 1
{
	 static  u16 flag=0;
	 flag++;
	 if(flag>=300)
	 {
	   flag=0;
	   Dis_play(3,1,L_num[0]); //报警值显示
	   Dis_play(3,2,L_num[1]); 
	   Dis_play(3,3,L_num[2]); 
	   Dis_play(3,4,L_num[3]); 
	   Dis_play(7,1,L_num[4]); 
	   Dis_play(7,2,L_num[5]); 
	   Dis_play(7,3,L_num[6]); 
	   Dis_play(7,4,L_num[7]); 

	   Dis_play(1,1,H_num[0]); 
	   Dis_play(1,2,H_num[1]); 
	   Dis_play(1,3,H_num[2]); 
	   Dis_play(1,4,H_num[3]); 
	   Dis_play(5,1,H_num[4]); 
	   Dis_play(5,2,H_num[5]); 
	   Dis_play(5,3,H_num[6]); 
	   Dis_play(5,4,H_num[7]); 
	 }
}


void tm1() interrupt 3
{
  	static  u16 flag=0;
	flag++;
	if(flag>=300)	//10ms
	{
	   	flag = 0;
		display_start();
		Dis_play(2,1,(u8)ADC_Value[0]);	//温度显示
		Dis_play(2,2,(u8)ADC_Value[1]);
		Dis_play(2,3,(u8)ADC_Value[2]);
		Dis_play(2,4,(u8)ADC_Value[3]);

		Dis_play(6,1,(u8)ADC_Value[4]);
		Dis_play(6,2,(u8)ADC_Value[5]);
		Dis_play(6,3,(u8)ADC_Value[6]);
		Dis_play(6,4,(u8)ADC_Value[7]);
	}
}


								            


 

#ifndef __ADC_H_
#define __ADC_H_

#include "config.h"
#include "lcd12864.h"
#include 
#include "intrins.h"
#include "uart.h"
#include  	       // 为使用KEIL自带的库函数printf而加入

#define ADC_POWER   0x80            //ADC电源控制位
#define ADC_FLAG    0x10            //ADC完成标志
#define ADC_START   0x08            //ADC起始控制位
#define ADC_SPEEDLL 0x00            //540个时钟
#define ADC_SPEEDL  0x20            //360个时钟
#define ADC_SPEEDH  0x40            //180个时钟
#define ADC_SPEEDHH 0x60            //90个时钟

void AD_Inti(void);
u16 Get_ADC10bitResult(u8 channel);


#endif



#include "adc.h"

void AD_Inti(void)
{

	ADC_RESL=0;	//清除结果寄存器
	ADC_RES=0;	//清除结果寄存器
	ADC_CONTR &= 0x10;//清除转换完成标志位
	P1ASF = 0xff;       //P1做ADC
    ADC_CONTR = 0xE0;   //90T, ADC power on
	 _nop_();
    _nop_();
    _nop_();
    _nop_();

}

//========================================================================
// 函数: u16    Get_ADC10bitResult(u8 channel)
// 描述: 查询法读一次ADC结果.
// 参数: channel: 选择要转换的ADC.
// 返回: 10位ADC结果.
// 版本: V1.0, 2012-10-22
//========================================================================
u16 Get_ADC10bitResult(u8 channel)  //channel = 0~7
{

	u16 AD_v = 0;
    ADC_RES = 0;
    ADC_RESL = 0;

    ADC_CONTR = (ADC_CONTR & 0xe0) | 0x08 | channel;    //start the ADC
    _nop_();
    _nop_();
    _nop_();
    _nop_();

    while((ADC_CONTR & 0x10) == 0)  ;   //wait for ADC finish
    ADC_CONTR &= ~0x10;     //清除ADC结束标志
	AD_v = ((u16)ADC_RES << 2) | (ADC_RESL & 3);
    return (AD_v);
}



 

 

 

 


 

你可能感兴趣的:(STC15单片机)