/*
* NTC测温,10位AD分辨率0.1度
* 硬件说明:IAP15W4K58S4
* 第一位数码管 位引脚-->P41 *
* 第二位数码管 位引脚-->P42 *
* 第三位数码管 位引脚-->P44 *
* 第四位数码管 位引脚-->P45 *
* 所有的数码管 段引脚-->P2 *
*******************************************************************************/
#define MAIN_Fosc 22118400L //定义主时钟
#include <STC15.H>
#include <intrins.H>
#define Timer0_Reload (65536UL -(MAIN_Fosc / 1000)) //Timer 0 中断频率, 1000次/秒
//#define uchar unsigned char
//#define uint unsigned int
typedef unsigned char u8;
typedef unsigned int u16;
typedef unsigned long u32;
#define DIS_DOT 0x20
#define DIS_BLACK 0x10
#define DIS_ 0x11
u8 code table[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};//共阳数字编码 0.1.2.3.4....9
u8 qian,bai,shi,ge;
bit B_1ms; //1ms标志
u16 msecond;
u8 flag0; //正负温度标志位
u8 flag1; //温度超过100度,千位数正常显示
u16 Get_ADC10bitResult(u8 channel); //AD转换函数声明,channl输入通道选择
u16 get_temperature(u16 adc); //温度转换函数声明
/********************************************************************
* 名称 : Delay()
* 功能 : 延时
* 输入 : i
* 输出 : 无
***********************************************************************/
void delay(u8 i) //延时函数
{
u16 j,k;
for(j=i;j>0;j--)
for(k=500;k>0;k--);
}
/********************************************************************
* 名称 : display()
* 功能 : 数码管显示函数
* 输入 : 无
* 输出 : 无
***********************************************************************/
void display(u8 qian,u8 bai,u8 shi,u8 ge) //显示函数
{
if(flag0) //温度低于0度千位数码管显示-
{
P2=0XBF;
P41 = 0;
delay(5);
P41 = 1;
}
if(flag1) //温度超过100度,千位显示
{
P2=table[qian];
P41 = 0;
delay(5);
P41 = 1;
}
P2=table[bai];
P42 = 0;
delay(5);
P42 = 1;
P2=table[shi]&0X7F; //十位显示小数点
P44 = 0;
delay(5);
P44 = 1;
P2=table[ge];
P45 = 0;
delay(5);
P45 = 1;
}
/********************************************************************
* 名称 : main()
* 功能 : 主函数
* 输入 : 无
* 输出 : 无
***********************************************************************/
void main(void)
{
long int j;
P0M1 = 0; P0M0 = 0; //设置为准双向口
P1M1 = 0; P1M0 = 0; //设置为准双向口
P2M1 = 0; P2M0 = 0; //设置为准双向口
P3M1 = 0; P3M0 = 0; //设置为准双向口
P4M1 = 0; P4M0 = 0; //设置为准双向口
P5M1 = 0; P5M0 = 0; //设置为准双向口
P6M1 = 0; P6M0 = 0; //设置为准双向口
P7M1 = 0; P7M0 = 0; //设置为准双向口
P1ASF = 0xff; //P1口全部做ADC
P1 &= 0x00; //设置P1.0口输出低电平确保能采集到外部电平信号
ADC_CONTR = 0xE0; //90T, ADC power on
AUXR = 0x80; //定时器0,1T ,16位自动重装
TH0 = (u8)(Timer0_Reload / 256);//1ms中断一次
TL0 = (u8)(Timer0_Reload % 256);
ET0 = 1; //开定时器0中断
TR0 = 1; //打开定时器0
EA = 1; //打开总中断
while(1)
{
if(B_1ms) //1ms到
{
B_1ms = 0; //清0标志位
if(++msecond >= 300) //300ms到
{
msecond = 0;
j = Get_ADC10bitResult(2);
j = get_temperature(j); //计算温度值
if(j >= 400) flag0 = 0, j -= 400; //温度 >= 0度
else flag0 = 1, j = 400 - j; //温度 < 0度
if(j>=1000) flag1=1;
else flag1=0;//温度超过100度标志位,千位数正常显示
}
}
qian=j/1000;
bai=j%1000/100;
shi=j%100/10;
ge=j%10;
display(qian,bai,shi,ge);
}
}
//========================================================================
// 函数: u16 Get_ADC10bitResult(u8 channel)
// 描述: 查询法读一次ADC结果.
// 参数: channel: 选择要转换的ADC.
// 返回: 10位ADC结果.
// 版本: V1.0, 2012-10-22
//========================================================================
u16 Get_ADC10bitResult(u8 channel) //channel = 0~7
{
u8 status=0; //判断AD转换结束标志位
u16 AD_dat=0; //转换结果10位ADC值
ADC_RES = 0;
ADC_RESL = 0;
ADC_CONTR|=0x80; ////开启ADC电源
_nop_(); _nop_();
_nop_(); _nop_(); //等待ADC电源稳定
//开启ADC电源,转换速度300k。启动ADC转换。选择转换通道
ADC_CONTR = (ADC_CONTR | 0xe0) | 0x08 | channel;
//while((ADC_CONTR & 0x10) == 0) ; //ADC_CONTR寄存器ADC_FLAG==1
//ADC_CONTR &= ~0x10; //清零ADC结束标志
while(status==0) //等待AD转换结束
{
status=ADC_CONTR & 0X10;//判断ADC_FLAG转换结束标志位,转换结束硬件置1,必须软件清零
}
ADC_CONTR&=0xe7; // 清零ADC_FLAG标志位关闭ADC转换1110 0111
AD_dat = (ADC_RES << 2)|(ADC_RESL&0X03);//高低字节拼接成一个10位结果
return AD_dat;
}
// MF52E 10K at 25, B = 3950, ADC = 12 bits
u16 code temp_table[]=
{
25, //-40 0
27, //-39 1
29, //-38 2
31, //-37 3
33, //-36 4
35, //-35 5
38, //-34 6
40, //-33 7
43, //-32 8
46, //-31 9
49, //-30 10
52, //-29 11
55, //-28 12
59, //-27 13
62, //-26 14
66, //-25 15
70, //-24 16
75, //-23 17
79, //-22 18
84, //-21 19
89, //-20 20
94, //-19 21
99, //-18 22
105, //-17 23
110, //-16 24
116, //-15 25
123, //-14 26
129, //-13 27
136, //-12 28
143, //-11 29
150, //-10 30
157, //-9 31
165, //-8 32
173, //-7 33
181, //-6 34
190, //-5 35
198, //-4 36
207, //-3 37
216, //-2 38
225, //-1 39
235, //0 40
244, //1 41
254, //2 42
264, //3 43
275, //4 44
285, //5 45
296, //6 46
306, //7 47
317, //8 48
328, //9 49
339, //10 50
351, //11 51
362, //12 52
373, //13 53
385, //14 54
396, //15 55
408, //16 56
420, //17 57
431, //18 58
443, //19 59
454, //20 60
466, //21 61
478, //22 62
489, //23 63
501, //24 64
512, //25 65
523, //26 66
535, //27 67
546, //28 68
557, //29 69
568, //30 70
579, //31 71
589, //32 72
600, //33 73
610, //34 74
620, //35 75
630, //36 76
640, //37 77
650, //38 78
660, //39 79
669, //40 80
678, //41 81
688, //42 82
696, //43 83
705, //44 84
714, //45 85
722, //46 86
730, //47 87
738, //48 88
746, //49 89
754, //50 90
761, //51 91
768, //52 92
775, //53 93
782, //54 94
789, //55 95
796, //56 96
802, //57 97
808, //58 98
814, //59 99
820, //60 100
826, //61 101
831, //62 102
837, //63 103
842, //64 104
847, //65 105
852, //66 106
857, //67 107
862, //68 108
866, //69 109
871, //70 110
875, //71 111
879, //72 112
883, //73 113
887, //74 114
891, //75 115
895, //76 116
898, //77 117
902, //78 118
905, //79 119
909, //80 120
912, //81 121
915, //82 122
918, //83 123
921, //84 124
924, //85 125
926, //86 126
929, //87 127
932, //88 128
934, //89 129
937, //90 130
939, //91 131
941, //92 132
943, //93 133
946, //94 134
948, //95 135
950, //96 136
952, //97 137
954, //98 138
955, //99 139
957, //100 140
959, //101 141
961, //102 142
962, //103 143
964, //104 144
965, //105 145
967, //106 146
968, //107 147
970, //108 148
971, //109 149
973, //110 150
974, //111 151
975, //112 152
976, //113 153
978, //114 154
979, //115 155
980, //116 156
981, //117 157
982, //118 158
983, //119 159
984, //120 160
};
/******************** 计算温度 ***********************************************/
// 计算结果: 0对应-40.0度, 400对应0度, 625对应25.0度, 最大1600对应120.0度.
// 为了通用, ADC输入为12bit的ADC值.
// 电路和软件算法设计: Coody
/**********************************************/
/******************** 计算温度 ***********************************************/
// 计算结果: 0对应-40.0度, 400对应0度, 625对应25.0度, 最大1600对应120.0度.
// 为了通用, ADC输入为12bit的ADC值.
// 电路和软件算法设计: Coody
/**********************************************/
#define D_SCALE 10 //结果放大倍数, 放大10倍就是保留一位小数
u16 get_temperature(u16 adc)
{
u16 code *p; //定义指针变量
u16 i;
u8 j,k,min,max; //定义局部变量j,k,min最小值,max最大值;
adc = 1023 - adc; //Rt接地时启用//RT接电源时屏蔽
p = temp_table;
if(adc < p[0]) return (0xfffe);
if(adc > p[160]) return (0xffff);
min = 0; //-40度
max = 160; //120度
for(j=0; j<5; j++) //对分查表
{
k = min / 2 + max / 2;
if(adc <= p[k]) max = k;
else min = k;
}
if(adc == p[min]) i = min * D_SCALE;
else if(adc == p[max]) i = max * D_SCALE;
else // min < temp < max
{
while(min <= max)
{
min++;
if(adc == p[min]) {i = min * D_SCALE; break;}
else if(adc < p[min])
{
min--;
i = p[min]; //min
j = (adc - i) * D_SCALE / (p[min+1] - i);
i = min;
i *= D_SCALE;
i += j;
break;
}
}
}
return i;
}
/********************** Timer0 1ms中断函数 ************************/
void timer0 (void) interrupt 1
{
//DisplayScan(); //1ms扫描显示一位
B_1ms = 1; //1ms标志
}