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
#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);
}