STC单片机测8路NTC测温度

来源:互联网 发布:javascript实战 pdf 编辑:程序博客网 时间:2024/05/17 21:10
            
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();//初始化LCD12864Timer1Init();//初始化定时器1Timer0Init();//初始化定时器0UART_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);}


 

 

 

 

 

0 0