STC单片机测8路NTC测温度

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

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

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


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


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

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

/* ***************************************************** */
// 工  程   : my
// 文件名   : main.c
// 处理器   : STC
// 编译环境 : Keil4 C51 
// 系统时钟 : 内部自带22.1184MHZ
// 版    本	: V1.0 
// 生成日期	: 2017-005-02	  					
// 修改日期	:  
// 简单描述 : 八路NTC温度
// 开发人才 :Made in Liu Ren fu(大白菜)
/* ***************************************************** */
#include <STC15F2K60S2.H>
#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<N;count++) 
		{ 
			sum += Get_Temperature(ch); 
			_nop_(); 
			_nop_(); 
			_nop_();  
		} 
		return (int)(sum/N); 
}

//========================================================================
// 函数: void UART_Test()
// 描述: 数据读取与串口测试
// 参数: 无
//========================================================================
void UART_Test()
{
	    tab[0]=Get_ADC10bitResult(0);      //读取通道0的ADC值
		ADC_Value[0] =  (float)filter(0);  //读取通道0的温度

		tab[1]=Get_ADC10bitResult(1);	   //读取通道1的ADC值
		ADC_Value[1] =  (float)filter(1);  //读取通道1的温度

		tab[2]=Get_ADC10bitResult(2);	   //读取通道2的ADC值
		ADC_Value[2] =  (float)filter(2);  //读取通道2的温度

		tab[3]=Get_ADC10bitResult(3);	   //读取通道3的ADC值
		ADC_Value[3] =  (float)filter(3);  //读取通道3的温度

		tab[4]=Get_ADC10bitResult(4);	   //读取通道4的ADC值
		ADC_Value[4] =  (float)filter(4);  //读取通道4的温度

		tab[5]=Get_ADC10bitResult(5);	   //读取通道5的ADC值
		ADC_Value[5] =  (float)filter(5);  //读取通道5的温度

		tab[6]=Get_ADC10bitResult(6);		//读取通道6的ADC值
		ADC_Value[6] =  (float)filter(6);   //读取通道6的温度

	   	tab[7]=Get_ADC10bitResult(7);	  //读取通道7的ADC值
		ADC_Value[7] =  (float)filter(7);  //读取通道7的温度
//发送串口监控显示
//		printf("通道0的AD值%d\n",tab[0]);
//		printf("通道0的温度值%f℃\n",ADC_Value[0]);
//		printf("通道1的AD值%d\n",tab[1]);
//		printf("通道1的温度值%f℃\n",ADC_Value[1]);
//		printf("通道2的AD值%d\n",tab[2]);
//		printf("通道2的温度值%f℃\n",ADC_Value[2]);
//		printf("通道3的AD值%d\n",tab[3]);
//		printf("通道3的温度值%f℃\n",ADC_Value[3]);
//		printf("通道4的AD值%d\n",tab[4]);
//		printf("通道4的温度值%f℃\n",ADC_Value[4]);
//		printf("通道5的AD值%d\n",tab[5]);
//		printf("通道5的温度值%f℃\n",ADC_Value[5]);
//		printf("通道6的AD值%d\n",tab[6]);
//		printf("通道6的温度值%f℃\n",ADC_Value[6]);
//		printf("通道7的AD值%d\n",tab[7]);
//		printf("通道7的温度值%f℃\n\n\n",ADC_Value[7]);

}


void Timer0Init(void)		//1000微秒@22.1184MHz
{
	AUXR &= 0x7F;		//定时器时钟12T模式
	TMOD &= 0xF0;		//设置定时器模式
	TL0 = 0xCD;		//设置定时初值
	TH0 = 0xF8;		//设置定时初值
	TR0 = 0;		//定时器0关闭计时
	ET0 = 1;		//打开定时器0中断
	EA  = 1;        //打开总中断
}



//========================================================================
// 函数: void Timer1Init(void)
// 描述: 定时器1初始化
// 参数: 无
//========================================================================
void Timer1Init(void)		//1000微秒@22.1184MHz
{
	AUXR &= 0xBF;		//定时器时钟12T模式
	TMOD &= 0x0F;		//设置定时器模式
	TL1 = 0xCD;		//设置定时初值
	TH1 = 0xF8;		//设置定时初值
	TF1 = 0;		//清除TF1标志
	TR1 = 0;		//定时器1开始计时
	ET1 = 1;		//打开定时器0中断
	EA  = 1;        //打开总中断
}
//========================================================================
// 函数: void Dis_play(u8 x,u8 y,u8 dat)
// 描述: LCD12864显示数据
// 参数: 无
//========================================================================
void Dis_play(u8 x,u8 y,u8 dat)
{
	 u8 ge=0,shi=0;	  //用于显示个,十位
	 ge = dat%10;	  //取各位
	 shi = dat/10;	  //取十位
	 Single_Data(x,y,shi);//发送十位显示
	 Write_data(ge+'0');  //发送个位显示
	 _nop_();_nop_();
}
//========================================================================
// 函数: display_start()
// 描述: LCD12864显示数据
// 参数: 无
//========================================================================
void display_start()
{
	LCD_PutString(0,1,"ch0:  ℃ch4:  ℃");//温度显示界面
    LCD_PutString(0,2,"ch1:  ℃ch5:  ℃");
    LCD_PutString(0,3,"ch2:  ℃ch6:  ℃");
    LCD_PutString(0,4,"ch3:  ℃ch7:  ℃");
}
//========================================================================
// 函数: empty_inti()
// 描述: LCD12864清空显示数据
// 参数: 无
//========================================================================

void  empty_inti()
{
   	LCD_PutString(0,1,"0:开1:开2:开3:开");//清空LCD12864显示
    LCD_PutString(0,2,"4:开5:开6:开7:开");
    LCD_PutString(0,3,"                ");
    LCD_PutString(0,4,"                ");
}

//========================================================================
// 函数: Control_KEY()
// 描述: 设置温度报警
// 参数: 无
//========================================================================
void Control_KEY()
{
	 static u8 flag_1=0;//用于设置那一路温度标志位
	 if(SW1 == 0)//判断是否有按键按下
	 {
		 DelayMS(1);//延时消抖
		 if(SW1 == 0)//判断是否有按键按下
		 {
		 	  while(!SW1);//松手检测  
			  flag_1++;
			  switch(flag_1)
			  {
		  	      case 1:		  
				  TR1 = 0;
				  TR0 = 1;
				  LCD_PutString(0,1,"0:  --  4:  --  ");
	   			  LCD_PutString(0,2,"1:  --  5:  --  ");
	    		  LCD_PutString(0,3,"2:  --  6:  --  ");
	              LCD_PutString(0,4,"3:  --  7:  --  ");
				        break; //
				 case 2:
				  		LCD_PutString(0,1,"0:  设  4:  --  ");//设置0通道
				        break;
				 case 3:
				  		LCD_PutString(0,1,"0:  --  4:  --  "); //设置1通道
						LCD_PutString(0,2,"1:  设  5:  --  ");
				        break;
				 case 4:
				 		LCD_PutString(0,2,"1:  --  5:  --  ");//设置2通道
						LCD_PutString(0,3,"2:  设  6:  --  ");
				        break;
				 case 5:
				 		LCD_PutString(0,3,"2:  --  6:  --  ");//设置3通道
						LCD_PutString(0,4,"3:  设  7:  --  ");
				        break;
				 case 6:
				 		LCD_PutString(0,4,"3:  --  7:  --  ");//设置4通道
						LCD_PutString(0,1,"0:  --  4:  设  ");
				        break;
				 case 7:
				 		LCD_PutString(0,1,"0:  --  4:  --  ");//设置5通道
						LCD_PutString(0,2,"1:  --  5:  设  ");
				        break;
				 case 8:
				 		LCD_PutString(0,2,"1:  --  5:  --  ");//设置6通道
						LCD_PutString(0,3,"2:  --  6:  设  ");
				        break;
				 case 9:
				 		LCD_PutString(0,3,"2:  --  6:  --  ");//设置7通道
						LCD_PutString(0,4,"3:  --  7:  设  ");
				        break;
				 case 10:
				 		TR0 = 0;	
				 		TR1 = 1;
				        break;
				 default:break;
			  }
		  if(flag_1 == 10) flag_1=0;
		 }

	 }
 ///	  
if((SW2 == 0) && (flag_1 > 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 <STC15F2K60S2.H>
#include "intrins.h"
#include "uart.h"
#include <stdio.h> 	       // 为使用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系列单片机NTC采集程序主要分为以下几个步骤: 1. 初始化:设置ADC采样精、引脚模式和串口通信等相关参数。 2. ADC采样:通过ADC采样NTC的电压值,并将其转换为温值。 3. 温计算:根据采样到的NTC电压值,结合NTC的特性曲线计算出对应的温值。 4. 温输出:将计算出的温值通过串口输出。 下面是一个简单的STC15系列单片机NTC采集程序示例: ``` #include <reg51.h> #define FOSC 11059200L #define BAUD 9600 unsigned char code Table[] = { 0xF9, 0x60, 0xDA, 0xF2, 0x63, 0xB7, 0xBE, 0xE4, 0xFE, 0xF6 }; void InitUART() { TMOD |= 0x20; // 设置定时器1为模式2 TH1 = TL1 = -(FOSC / 12 / 32 / BAUD); // 设置波特率 TR1 = 1; // 启动定时器1 SCON = 0x50; // 串口工作在模式1 } unsigned int GetADCResult(unsigned char ch) { unsigned int value; ADC_CONTR = 0x80 | ch << 3; // 设置ADC转换通道 Delay(2); // 稍作延时 ADC_CONTR |= 0x40; // 启动ADC转换 while (!(ADC_CONTR & 0x20)); // 等待转换完成 value = ADC_RES; // 读取ADC转换结果 value |= ADC_RESL << 8; return value; } unsigned char GetTempValue() { unsigned int adc_value; unsigned char temp_value; adc_value = GetADCResult(0); // 采样NTC电压值 temp_value = (unsigned char)(adc_value / 8.5 - 20); // 计算温值 return temp_value; } void main() { unsigned char temp_value; InitUART(); // 初始化串口 while (1) { temp_value = GetTempValue(); // 获取温值 SBUF = Table[temp_value / 10]; // 发送十位数码管显示数据 while (!TI); // 等待发送完成 TI = 0; SBUF = Table[temp_value % 10]; // 发送个位数码管显示数据 while (!TI); // 等待发送完成 TI = 0; } } ``` 在上述代码中,我们首先通过InitUART()函数初始化串口,然后通过GetADCResult()函数获取NTC电压值,接着通过GetTempValue()函数计算温值,最后通过串口输出温值。在输出温值时,我们将温值拆分为十位和个位,分别发送到数码管进行显示。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值