1. 程式人生 > >PT100恆流源測溫電路【一】

PT100恆流源測溫電路【一】

自從想要做一個PT100的測溫電路,實驗了很多方法,包括恆流源,電橋。最後決定使用恆流源,而恆流源採用壓控恆流源,電壓基準採用LM285,輸出電壓1.235V。


此恆流源的輸出電流取決於LM285的輸出電壓,和R1的阻值,為了得到精確的輸出電流,R1最好採用高精度,低溫漂的電阻。如果需要更高的精度,則需要使用更高的電壓基準晶片,比如REF5025,LM399等。

PT100採用四線制接法,通過J2輸入,放大器採用AD623儀表放大器,當然使用普通運放構成差分放大器也是可以的,只是使用現成的儀表放大器比較方便,只需要一個外部電阻R15即可設定放大增益,公式為G=100KΩ/R15+1,這個電路設定的放大增益G=11。另外U8、C7、C8、R17、R18構成二階有源低通濾波器,這裡設定的截止頻率f≈5Hz。濾波後的訊號接ADC到微控制器的模數轉換引腳,當然也可以通過跳線JP1接到專用16位AD轉換晶片ADS1110,將電壓轉換為數字訊號然後交由微控制器處理。

本電路因為採用單電源供電,而AD623需要使用一個負電壓,所以使用了一個電壓反轉晶片MAX660,但也可以使用LM2662替代,而事實上在實際的電路中,我使用的就是LM2662

這是微控制器電路的原理圖,使用的是 STC的STC12C5A16S2,LQFP44封裝。其中KEY,DATA,CLK,CS是用來控制數碼管,用於顯示測量溫度,在這個環節中,使用了一片HD7279晶片,用於動態顯示數碼管,為什麼使用這個晶片而不是使用微控制器直接驅動數碼管呢。這個是出於節省CPU資源的考慮,因為程式中使用了一些濾波演算法比較耗費CPU,而且考慮到可能需要使用485通訊,萬一等待時間過長,擔心因此造成數碼管閃爍,所以使用了一片HD7279。

這個是核心板輸出介面電路
 

關於這個晶片的使用方法就不多說了,datasheet上寫的非常清楚了。

 



當然,顯示部分的電路是和核心電路分開的,在另外一塊PCB上。下面是核心板的PCB

 

以下是標定資料,“溫度計”項代表使用標準水銀溫度計的測量值;“PT100“代表以上裝置測量得出的值;”誤差“為”PT100“-”溫度計“的值;”多項式“是採用多項式擬合後的到的值;”擬合後誤差”為”多項式“-”溫度計“的值;

 溫度計 PT100 誤差              
多項式         擬合後誤差
2 6 -4 2.3 0.3
2.7 6.7 -4 3.1 0.4
3 7 -4 3.5 0.5
4 8 -4 4.7 0.7
7 10 -3 7.2 0.2
8.9 11.1 -2.2 8.5 -0.4
9 12 -3 9.6 0.6
9.2 11.3 -2.1 8.8 -0.4
9.2 12.4 -3.2 10.1 0.9
9.5 11.4 -1.9 8.9 -0.6
10 11.7 -1.7 9.3 -0.7
10 12.8 -2.8 10.6 0.6
10.2 12.2 -2 9.9 -0.3
11.2 12.8 -1.6 10.6 -0.6
11.5 14.2 -2.7 12.3 0.8
12 13 -1 10.8 -1.2
12 14 -2 12.0 0.0
12.2 13.9 -1.7 11.9 -0.3
13 15 -2 13.2 0.2
13.5 15.2 -1.7 13.5 0.0
14 16 -2 14.4 0.4
14 15.6 -1.6 14.0 0.0
14.2 15.1 -0.9 13.4 -0.8
22.5 22.3 0.2 21.9 -0.6
23 22.7 0.3 22.3 -0.7
23.5 22.9 0.6 22.6 -0.9
24 23.3 0.7 23.0 -1.0
24.5 24.9 -0.4 24.9 0.4
24.5 23.8 0.7 23.6 -0.9
25 25.2 -0.2 25.2 0.2
25 24.3 0.7 24.2 -0.8
25.5 25.7 -0.2 25.8 0.3
26 26.2 -0.2 26.4 0.4
26.5 26.6 -0.1 26.9 0.4
27 27.1 -0.1 27.4 0.4
27.5 27.4 0.1 27.8 0.3
28 27.8 0.2 28.2 0.2
28.5 28.2 0.3 28.7 0.2
29 28.7 0.3 29.3 0.3
29.5 29 0.5 29.6 0.1
30 29.5 0.5 30.2 0.2
30.7 30 0.7 30.7 0.0
31 30.3 0.7 31.1 0.1
31.5 30.7 0.8 31.5 0.0
32 31 1 31.9 -0.1
32 31.2 0.8 32.1 0.1
32.5 32.6 -0.1 33.7 1.2
32.5 31.6 0.9 32.5 0.0
33 32.1 0.9 33.1 0.1
34 33 1 34.1 0.1
34.5 33.4 1.1 34.5 0.0
38 36.2 1.8 37.7 -0.3
39 37 2 38.5 -0.5
40 38 2 39.6 -0.4
41 39 2 40.7 -0.3
42 40.5 1.5 42.4 0.4
44 41.7 2.3 43.6 -0.4
45 42.6 2.4 44.6 -0.4
46 43.5 2.5 45.6 -0.4
47 44.6 2.4 46.8 -0.2
48 45.6 2.4 47.8 -0.2
49 46.5 2.5 48.8 -0.2
50 47.6 2.4 49.9 -0.1
51 48.5 2.5 50.9 -0.1
54 51.5 2.5 54.0 0.0
55 52.5 2.5 55.0 0.0
56 53.5 2.5 56.0 0.0
58 55.5 2.5 58.1 0.1
59.2 56.5 2.7 59.1 -0.1
60 57.5 2.5 60.1 0.1
61 58.3 2.7 60.9 -0.1
62 59.4 2.6 62.0 0.0
63 60.5 2.5 63.1 0.1
64 61.5 2.5 64.1 0.1
65.2 62.5 2.7 65.1 -0.1
66 63.5 2.5 66.0 0.0
67.2 64.5 2.7 67.0 -0.2
68 65.5 2.5 68.0 0.0
70 67.6 2.4 70.0 0.0
71 68.2 2.8 70.6 -0.4
72 69.4 2.6 71.7 -0.3
73 70.5 2.5 72.8 -0.2
74 71.5 2.5 73.7 -0.3
75 72 3 74.2 -0.8
76 74 2 76.0 0.0
77.5 74.9 2.6 76.9 -0.6
78 76 2 77.9

-0.1

 

上圖中X軸為PT100的值,Y軸為溫度計的值,可以看出多項式擬合的效果更好一些

以下是實物效果:

下面是程式程式碼:

#include <intrins.h>
#include <STC12C5A60S2.H>

typedef unsigned int  uint;
typedef unsigned char uchar;
typedef unsigned short WORD;

float code RTD_TAB_PT100[151] =   // 表格是以1度為一步,即-20, -19, -18..... 
{ 
   	88.22, 88.62 ,88.62, 89.40, 89.80, 90.19, 90.59, 90.98, 91.37, 91.77,       //  -30 ~ -21
    92.16, 92.55, 92.95, 93.34, 93.73, 94.12, 94.52, 94.91, 95.30, 95.69,       //  -20 ~ -11
    96.09, 96.48, 96.87, 97.26, 97.65, 98.04, 98.44, 98.83, 99.22, 99.61,       //  -10 ~ -1 
   100.00,100.39,100.78,101.17,101.56,101.95,102.34,102.73,103.13,103.51,       //   0  ~ 9
   103.90,104.29,104.68,105.07,105.46,105.85,106.24,106.63,107.02,107.49,       //  10  ~ 19
   107.79,108.18,108.57,108.96,109.35,109.73,110.12,110.51,110.90,111.28,       //  20  ~ 29
   111.67,112.06,112.45,112.83,113.22,113.61,113.99,114.38,114.77,115.15,       //  30  ~ 39
   115.54,115.93,116.31,116.70,117.08,117.47,117.86,118.24,118.62,119.01,       //  40  ~ 49
   119.40,119.78,120.16,120.55,120.93,121.32,121.70,122.09,122.47,122.86,       //  50  ~ 59
   123.24,123.62,124.01,124.39,124.77,125.16,125.54,125.92,126.31,126.69,       //  60  ~ 69
   127.07,127.45,127.84,128.22,128.60,128.98,129.37,129.75,130.13,130.51,       //  70  ~ 79
   130.89,131.27,131.66,132.04,132.42,132.80,133.18,133.56,133.94,134.32,       //  80  ~ 89
   134.70,135.08,135.46,135.84,136.22,136.60,136.98,137.36,137.74,138.12,       //  90  ~ 99
   138.50,138.88,139.26,139.64,140.02,140.39,140.77,141.15,141.53,141.91,       // 100  ~ 109
   142.29,142.66,143.04,143.42,143.80,144.17,144.55,144.93,145.31,145.68,       // 110  ~ 119
   146.06                                                              // 120
}; 

sbit beep = P3^5;

//----------------ADS1110地址、配置字-----------------//     
#define      ADS1110_WR_ADDRESS   0x92        // 1001 001 0 寫    
#define      ADS1110_RD_ADDRESS   0x93        // 1001 001 1 讀      
#define      ADS1110_CONFIG_REG   0x8C        // 連續轉換模式,16bit精度,PGA=1     
   
sbit  ADS1110_SDA = P1^5;    // 模擬I2C資料傳輸位    
sbit  ADS1110_CLK = P1^6;    // 模擬I2C時鐘控制位

//uchar TMR_H, TMR_L;			 // AD轉換高8位,和低8位
uint  AD_Result[25];
unsigned long nTmp;

//*** HD7279 函式定義 ***
void long_delay(void);							// 長延時
void short_delay(void);							// 短暫延時
void delay10ms(unsigned char);					// 延時10MS
void write7279(uchar, uchar);	// 寫入到HD7279
uchar read7279(uchar);			// 從HD7279讀出
void send_byte(uchar);					// 傳送一個位元組
uchar receive_byte(void);				// 接收一個位元組

sbit cs =P0^7;					// cs at P1.4
sbit clk=P0^6;					// clk 連線於 P1.5
sbit dat=P0^5;					// dat 連線於 P1.2
sbit key=P0^4;					// key 連線於 P1.3
sbit Hight_LED = P4^6;
sbit Low_LED   = P4^1;

//****** HD7279A 指令 ******
#define CMD_RESET 0xa4
#define CMD_TEST  0xbf
#define DECODE0   0x80
#define DECODE1   0xc8
#define CMD_READ  0x15
#define UNDECODE  0x90
#define RTL_CYCLE 0xa3
#define RTR_CYCLE 0xa2
#define RTL_UNCYL 0xa1
#define RTR_UNCYL 0xa0
#define ACTCTL    0x98
#define SEGON     0xe0
#define SEGOFF    0xc0
#define BLINKCTL  0x88


//-------- AT24C04 變數宣告 ---------
sbit _24C02_SCL = P2^6;                //AT24C04的時鐘
sbit _24C02_SDA = P2^5;                //AT24C04的資料

uchar BUF[16];                   //資料快取區

uint code nDefaultDATA[] =
{// nLowTMP	  nHightTMP	 nTMPAdj
      480,       650,       0      // 預設設定
};
uint nSettingDATA[3] = {0, 0, 0};  // 當前設定

void Delay5us();
void AT24C04_Start();
void AT24C04_Stop();
void AT24C04_SendACK(bit ack);
bit AT24C04_RecvACK();
void AT24C04_SendByte(uchar dat);
uchar AT24C04_RecvByte();
void AT24C04_ReadPage();
void AT24C04_WritePage();


//****** 紅外接收 ******
sbit IRIN = P3^3;         //紅外接收器資料線
uchar IRCOM[7];
uchar nFlag = 0;
uchar nMode = 1;   // nMode    0       1          2         3   
			       // mean   NULL	nLowTMP	  nHightTMP	  nTMPAdj

uint nLowTMP   = 480;	  // 最低溫度設定
uint nHightTMP = 650;	  // 最高溫度設定
char nTMPAdj   = 0;		  // 溫度修正

void send_ad_result(uchar temp);

/***********************************************************************************
************************************************************************************
////////////////////////////////HD 7279 函式////////////////////////////////////////
************************************************************************************
************************************************************************************/
void write7279(uchar cmd, uchar dta)
{
	cs = 0;
	send_byte (cmd);
	send_byte (dta);
	cs = 1;
}	

uchar read7279(uchar command)
{
	cs = 0;
	send_byte(command);
	return(receive_byte());
	cs = 1;
}

void send_byte(	uchar out_byte)
{
	uchar i;
	cs=0;
	long_delay();
	for (i=0;i<8;i++)
	{
		if (out_byte&0x80)
		{	
			dat=1;
		}
		else
		{
			dat=0;
		}
		clk=1;
		short_delay();
		clk=0;
		short_delay();
		out_byte=out_byte*2;
	}
	dat=0;
}

uchar receive_byte(void)
{
	uchar i, in_byte;
	dat=1;				// set to input mode
	long_delay();
	for (i=0;i<8;i++)
	{
		clk=1;
		short_delay();
		in_byte=in_byte*2;
		if (dat)
		{
			in_byte=in_byte|0x01;
		}
		clk=0;
		short_delay();
	}
	dat=0;
	return (in_byte);
}

void delay10ms(uint time)   //誤差 -0.000000000001us
{
    uchar a,b,c;
	uint i;
	for (i=0;i<time;i++)
	{
	    for(c=7;c>0;c--)
	        for(b=168;b>0;b--)
	            for(a=24;a>0;a--);
	}
}

void long_delay(void)
{
	unsigned char i;
	for (i=0;i<0x30;i++);
}

void short_delay(void)
{
	unsigned char i;
	for (i=0;i<8;i++);
}

/***********************************************************************************
************************************************************************************
////////////////////////////////HD 7279 函式 END////////////////////////////////////////
************************************************************************************
************************************************************************************/

//--------------------- 模組延時程式_1ms ------------------------- 
void delay1ms(uint delay1ms) //STC11F60XE,延時1ms
{
    uchar a,b;
	// 12M
//    for(;delay1ms>0;delay1ms--)
//        for(b=222;b>0;b--)
//            for(a=12;a>0;a--);

	// 11.0592M
	for( ; delay1ms > 0; delay1ms--)
	    for(b = 21; b > 0; b--)
	        for(a = 130; a > 0; a--);
}

void Delay5us()   // 晶振11.0592M 誤差 -0.026765046296us
{
    uchar a;
    for(a=12;a>0;a--);
    _nop_();  
}

void delay(uint delay) //STC11F60XE,12M,延時170us
{	
    uchar a,b;
	// 12M
//	for(;delay>0;delay--)
//	    for(b=78;b>0;b--)
//	        for(a=5;a>0;a--);

	// 11.0592M
	for( ; delay > 0; delay--)
		for( b = 2; b > 0; b--)
		    for( a = 232; a > 0; a--);
}

//--------------------- 數碼管顯示函式 ------------------------- 
void Display_TMP(uint nTmp1)
{
		//send_byte(CMD_RESET);
		write7279(DECODE0,nTmp1/100%100);
		delay1ms(2);
		write7279(DECODE0+1,nTmp1/10%10);
		delay1ms(2);
		write7279(SEGON,15);
		delay1ms(2);
		write7279(DECODE0+2,nTmp1%10);
		delay1ms(2);
		write7279(SEGON,63);
		delay1ms(2);
		write7279(SEGON,62);
		delay1ms(2);
		write7279(SEGON,61);
		delay1ms(2);
		write7279(SEGON,60);
		delay1ms(2);
		write7279(SEGON,59);
		delay1ms(2);

		//delay10ms(1000); 
		//send_byte(CMD_RESET);
}

void Display_SETTMP(uint nTmp2)
{
		//send_byte(CMD_RESET);

		write7279(DECODE0+4,nTmp2/100%100);
		delay1ms(2);
		write7279(DECODE0+5,nTmp2/10%10);
		delay1ms(2);
		write7279(SEGON,47);
		delay1ms(2);
		write7279(DECODE0+6,nTmp2%10);
		delay1ms(2);
		write7279(SEGON,31);
		delay1ms(2);
		write7279(SEGON,30);
		delay1ms(2);
		write7279(SEGON,29);
		delay1ms(2);
		write7279(SEGON,28);
		delay1ms(2);
		write7279(SEGON,27);
		delay1ms(2);
		//delay10ms(1000); 
		//send_byte(CMD_RESET);
}

void Display_SET()
{
	send_byte(CMD_RESET);

	if (nMode == 1)	 // set nLowTMP
	{
		write7279(SEGON,1);
		delay1ms(2);
		write7279(SEGON,2);
		delay1ms(2);
		write7279(SEGON,3);
		delay1ms(2);
	
		write7279(DECODE0+4,nLowTMP/100%100);
		delay1ms(2);
		write7279(DECODE0+5,nLowTMP/10%10);
		delay1ms(2);
		write7279(SEGON,47);
		delay1ms(2);
		write7279(DECODE0+6,nLowTMP%10);
	}
	if (nMode == 2)	 // set nHightTMP
	{
		write7279(SEGON,0);
		delay1ms(2);
		write7279(SEGON,1);
		delay1ms(2);
		write7279(SEGON,2);
		delay1ms(2);
		write7279(SEGON,4);
		delay1ms(2);
		write7279(SEGON,5);
		delay1ms(2);
	
		write7279(DECODE0+4,nHightTMP/100%100);
		delay1ms(2);
		write7279(DECODE0+5,nHightTMP/10%10);
		delay1ms(2);
		write7279(SEGON,47);
		delay1ms(2);
		write7279(DECODE0+6,nHightTMP%10);
	}
	if (nMode == 2)	 // set nTMPAdj
	{
		write7279(SEGON,0);
		delay1ms(2);
		write7279(SEGON,1);
		delay1ms(2);
		write7279(SEGON,2);
		delay1ms(2);
		write7279(SEGON,4);
		delay1ms(2);
		write7279(SEGON,5);
		delay1ms(2);
		write7279(SEGON,6);
		delay1ms(2);
	
		if (nTMPAdj < 0)
		{
			write7279(SEGON,32);
			delay1ms(2);
			write7279(DECODE0+5,(0-nTMPAdj)/10%10);
			delay1ms(2);
			write7279(DECODE0+6,(0-nTMPAdj)%10);
		}
		if (nTMPAdj > 0)
		{
			write7279(DECODE0+5,nTMPAdj/10%10);
			delay1ms(2);
			write7279(DECODE0+6,nTMPAdj%10);
		}
	}
}
/***********************************************************************************
************************************************************************************
////////////////////////////////紅外解碼 函式-BEGIN/////////////////////////////////
************************************************************************************
************************************************************************************/
void IR_IN() interrupt 2 using 0
{
	return ;
} 
/***********************************************************************************
////////////////////////////////紅外解碼 函式 END////////////////////////////////////
************************************************************************************/


/***********************************************************************************
************************************************************************************
////////////////////////////////AD1110 轉換 -BEGIN/////////////////////////////////
************************************************************************************
************************************************************************************/

/******************************************************************************* 
名稱:ads1110Start(void)  
功能:ADS1110 I2C Start  
********************************************************************************/   
void ads1110Start(void)    
{    
	ADS1110_SDA = 1;

	_nop_(); _nop_(); _nop_();_nop_(); _nop_(); 
	 
	ADS1110_CLK = 1; 
	   
	_nop_(); _nop_();   
	_nop_();  _nop_(); _nop_();  _nop_();
	  
	ADS1110_SDA = 0; 
	  
	_nop_();  _nop_();  
	_nop_();  _nop_(); _nop_();  _nop_();  
} 
     
/*******************************************************************************  
名稱:ads1110Stop(void)  
功能:ADS1110 I2C Stop  
********************************************************************************/   
void ads1110Stop(void)    
{    
	ADS1110_SDA = 0;
	    
	_nop_();  _nop_();_nop_();  _nop_();_nop_();  _nop_(); 
	 
	ADS1110_CLK = 1;                // -----------結束I2C匯流排.
	    
	_nop_();  _nop_();  
	_nop_();  _nop_(); _nop_();  _nop_();_nop_();  _nop_();   

	ADS1110_SDA = 1;

	_nop_(); _nop_(); _nop_();         
}   
/*******************************************************************************  
名稱:waitAck(void)  
功能:ADS1110 I2C 等待ack  
********************************************************************************/    
uchar waitAck(void)    
{      
	uint i = 0;
	ADS1110_CLK = 1;

	_nop_(); _nop_(); _nop_(); _nop_(); _nop_(); 

	while((ADS1110_SDA==1)&&(i<500))
		i++;
	ADS1110_CLK = 0;

	_nop_(); _nop_(); _nop_(); _nop_(); _nop_();
	 
	return 0x00;    
}
   
/*******************************************************************************
名稱:void sendAck(void)  
功能:向ADS1110 I2C 傳送 ack  
********************************************************************************/    
void sendAck(void)    
{        
	ADS1110_SDA=0; 
	  
	_nop_();   
	_nop_();    
	_nop_();   
	_nop_();   

	ADS1110_CLK=1;
	      
	_nop_();   
	_nop_();    
	_nop_();   
	_nop_();  
	 
	ADS1110_CLK=0;   
}   
/*******************************************************************************  
名稱:void sendNotAck(void)  
功能:向ADS1110 I2C 不傳送 ack  
********************************************************************************/   
void sendNotAck(void)    
{     
	ADS1110_SDA=1; 
	  
	_nop_();   
	_nop_();    
	_nop_();   
	_nop_();
	   
	ADS1110_CLK=1;
	      
	_nop_();   
	_nop_();    
	_nop_();   
	_nop_();  
	 
	ADS1110_CLK=0;   
} 
  
/*******************************************************************************  
名稱:void ads1110SendByte(uchar sendData)  
功能:向ADS1110 I2C 傳送1個位元組  
********************************************************************************/     
void ads1110SendByte(uchar sendData)    
{    
	uchar i,temp;
	temp = sendData;
	for(i=0;i<8;i++)
	{
		temp = temp << 1;
		ADS1110_CLK = 0; 

		_nop_(); _nop_(); _nop_(); _nop_(); _nop_();_nop_();  _nop_(); 

		ADS1110_SDA = CY;

		_nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_();  _nop_();

		ADS1110_CLK = 1;

		_nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_();  _nop_();
	}
	ADS1110_CLK = 0; 

	_nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_();  _nop_();
	ADS1110_SDA = 1;

	_nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_();  _nop_();          
} 
  
/*******************************************************************************   
名稱:uchar ads1110ReceiveByte(void)  
功能:ADS1110 I2C 接收1個位元組  
********************************************************************************/    
uchar ads1110ReceiveByte(void)    
{          
	uchar i,k;
	ADS1110_CLK = 0;

	_nop_(); _nop_(); _nop_(); _nop_(); _nop_();_nop_();  _nop_();

	ADS1110_SDA = 1;

	_nop_();  _nop_();_nop_();  _nop_();_nop_();  _nop_();

	for(i=0;i<8;i++)
	{
		ADS1110_CLK = 1;

		_nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_();  _nop_();

		k= (k << 1)| ADS1110_SDA;
		ADS1110_CLK = 0;

		_nop_(); _nop_(); _nop_(); _nop_(); _nop_();  _nop_();  _nop_();        
	}

	_nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_();  _nop_();

	return k;
          
}  
  
/*******************************************************************************   
名稱:ads1110Config(void)  
功能:對ADS1110進行配置      
********************************************************************************/   
void ads1110Config(void)    
{    
	ads1110Start();    
	ads1110SendByte(ADS1110_WR_ADDRESS);    
	waitAck();    
	ads1110SendByte(ADS1110_CONFIG_REG);    
	waitAck();    
	ads1110Stop();    
}     
/*******************************************************************************   
名稱:讀取ADS1100資料子程式  
功能:  
********************************************************************************/   
uint RD_ADS()   
{
	uchar temp;
	uint  W_B1byte_high, W_B1byte_low, W_B1_word;   

	ads1110Start();                               	
	ads1110SendByte(ADS1110_RD_ADDRESS);    
	temp = waitAck();                            
	
	if(!temp)                              
	{   
		W_B1byte_high /*= TMR_H*/ = ads1110ReceiveByte();      
		
		sendAck();                
		           
		W_B1byte_low /*= TMR_L*/ = ads1110ReceiveByte();         
		sendAck();                   
		
		temp = ads1110ReceiveByte();            
		ads1110Stop();   
		W_B1_word = (W_B1byte_high << 8)+ W_B1byte_low;   
		if (W_B1_word > 0x7fff)               
			W_B1_word = 0;   
		
		return W_B1_word;       
	}    
	else      
		return 0x0000;   
}

/*******************************************************************************   
名稱: 取AD結果函式  
功能: 它是16位AD轉換,連續去制25次,去掉3最大值和3個最小值,剩下19個取平均值
返回: 平均取值
********************************************************************************/  
uint get_ad_result() 
{ 
	uchar i,j;
	uint temp;

	nTmp = 0;

	for(i = 0; i < 25; i++)	 // 連續取值25次
	{
		AD_Result[i] = RD_ADS();
		delay1ms(10);
	}

	for(i = 1;  i< 25; i++)	 // 插入法對取的25個值進行排序
	{
		temp = AD_Result[i];                          //store the original sorted array in temp
		for(j=i ; j>0 && temp < AD_Result[j-1] ; j--) //compare the new array with temp   
		{
			AD_Result[j] = AD_Result[j-1];              //all larger elements are moved one pot to the right   
		}
		AD_Result[j] = temp;
	}

//	for(i = 3; i < 22; i++)	 // 去掉3最大值和3個最小值,餘下19個值求和
//	{
//		nTmp = nTmp + AD_Result[i];
//	}
	
	return AD_Result[12]; //nTmp / 19;		 // 取剩下19個數平均值
	//ad_average_result=ad_average_result*4*5000/1024;
}

/*******************************************************************************   
名稱: 串列埠傳送函式  
功能: 取AD結果函式傳送到串列埠,方便除錯
返回: 無
********************************************************************************/  
void send_ad_result(uchar temp)
{               
	SBUF = temp;
	while(TI == 0) ;
	TI = 0;
	delay1ms(100);
	//SBUF=R>>4;
}

/*******************************************************************************   
名稱: 初始化函式  
功能: 設定串列埠相關暫存器值,波特率取9600, 12T模式
返回: 無
********************************************************************************/
void _initiate() //初始化函式
{ 
	EA = 1;
	ES = 0;
	TMOD = 0x20;  // 定時計數器方式控制暫存器,"自動重灌,16位計數器".
	SCON = 0x50;  // 序列控制暫存器,方便在串列埠助手那觀察

	// 12M
//	TH1 = 0xF3;	  // 定時器初值高8位設定
//	TL1 = 0xF3;	  // 定時器初值低8位設定

	// 11.0592M	   波特率 9600
	TH1 = 0xFD;	  // 定時器初值高8位設定
    TL1 = TH1;	  // 定時器初值低8位設定
	PCON = 0x00;
	TR1 = 1;

//	IE = 0x84;      // 允許總中斷中斷,使能 INT1 外部中斷
	EX1 = 1;
//	TCON = 0x10;    // 觸發方式為脈衝負邊沿觸發
}

/*******************************************************************************   
名稱: 蜂鳴器函式  
功能: 設定蜂鳴器鳴響
返回: 無
********************************************************************************/
void Beep(uchar nSet)
{
}

/****************************************/
/****************************************/
//------------ AT24C04 驅動函式  --------------

/**************************************
向AT24C04寫1頁(16位元組)資料
將TESTDATA開始的16個測試資料寫如裝置的00~0F地址中
**************************************/
void AT24C04_WritePage()
{
    uchar i;

    AT24C04_Start();            //起始訊號
    AT24C04_SendByte(0xa0);     //傳送裝置地址+寫訊號
    AT24C04_SendByte(0x00);     //傳送儲存單元地址
    for (i=0; i<3; i++)
    {
        AT24C04_SendByte(nSettingDATA[i]);
    }
    AT24C04_Stop();             //停止訊號
}

/**************************************
從AT24C04讀取1頁(16位元組)資料
將裝置的00~0F地址中的資料讀出存放在DATA區的BUF中
**************************************/
void AT24C04_ReadPage()
{
    uchar i;

    AT24C04_Start();            //起始訊號
    AT24C04_SendByte(0xa0);     //傳送裝置地址+寫訊號
    AT24C04_SendByte(0x00);     //傳送儲存單元地址
    AT24C04_Start();            //起始訊號
    AT24C04_SendByte(0xa1);     //傳送裝置地址+讀訊號
    for (i=0; i<16; i++)
    {
        BUF[i] = AT24C04_RecvByte();
        if (i == 15)
        {
            AT24C04_SendACK(1); //最後一個數據需要會NAK
        }
        else
        {
            AT24C04_SendACK(0); //迴應ACK
        }
    }
    AT24C04_Stop();             //停止訊號
}

/**************************************
起始訊號
**************************************/
void AT24C04_Start()
{
    _24C02_SDA = 1;                    //拉高資料線
    _24C02_SCL = 1;                    //拉高時鐘線
    Delay5us();                 //延時
    _24C02_SDA = 0;                    //產生下降沿
    Delay5us();                 //延時
    _24C02_SCL = 0;                    //拉低時鐘線
}

/**************************************
停止訊號
**************************************/
void AT24C04_Stop()
{
    _24C02_SDA = 0;                    //拉低資料線
    _24C02_SCL = 1;                    //拉高時鐘線
    Delay5us();                 //延時
    _24C02_SDA = 1;                    //產生上升沿
    Delay5us();                 //延時
}

/**************************************
傳送應答訊號
入口引數:ack (0:ACK 1:NAK)
**************************************/
void AT24C04_SendACK(bit ack)
{
    _24C02_SDA = ack;                  //寫應答訊號
    _24C02_SCL = 1;                    //拉高時鐘線
    Delay5us();                 //延時
    _24C02_SCL = 0;                    //拉低時鐘線
    Delay5us();                 //延時
}

/**************************************
接收應答訊號
**************************************/
bit AT24C04_RecvACK()
{
    _24C02_SCL = 1;                    //拉高時鐘線
    Delay5us();                 //延時
    CY = _24C02_SDA;                   //讀應答訊號
    _24C02_SCL = 0;                    //拉低時鐘線
    Delay5us();                 //延時

    return CY;
}

/**************************************
向IIC匯流排傳送一個位元組資料
**************************************/
void AT24C04_SendByte(uchar dat)
{
    uchar i;

    for (i=0; i<8; i++)         //8位計數器
    {
        dat <<= 1;              //移出資料的最高位
        _24C02_SDA = CY;               //送資料口
        _24C02_SCL = 1;                //拉高時鐘線
        Delay5us();             //延時
        _24C02_SCL = 0;                //拉低時鐘線
        Delay5us();             //延時
    }
    AT24C04_RecvACK();
}

/**************************************
從IIC匯流排接收一個位元組資料
**************************************/
uchar AT24C04_RecvByte()
{
    uchar i;
    uchar dat = 0;

    _24C02_SDA = 1;                    //使能內部上拉,準備讀取資料
    for (i=0; i<8; i++)         //8位計數器
    {
        dat <<= 1;
        _24C02_SCL = 1;                //拉高時鐘線
        Delay5us();             //延時
        dat |= _24C02_SDA;             //讀資料
        _24C02_SCL = 0;                //拉低時鐘線
        Delay5us();             //延時
    }

    return dat;
}

/*********************************************************************** 
*FunName: float CalculateTemperature(float fR) 
* 
*In: fR -> PT100的電阻值。 
* 
*Out: fTem -> 測得的溫度值。         
* 
*Discription: 將電阻值查表算出溫度值。 
* 
*Notes:  採用2分查詢法。    
* 
************************************************************************/ 
float CalculateTemperature(float fR) 
{ 
	float fTem; 
	float fLowRValue; 
	float fHighRValue; 
	int   iTem; 
	uchar i; 
	
	uchar cBottom, cTop; 
	
	if (fR < RTD_TAB_PT100[0]) // 電阻值小於表格最小值,低於量程下限。 
	{ 
		return 210; 
	} 
	
	if (fR > RTD_TAB_PT100[150]) // 電阻值大於表格最大值,超出量程上限。 
	{ 
		return 211; 
	} 
	
	cBottom = 0;  
	cTop    = 150; 
	
	for (i=75; (cTop-cBottom)!=1; ) // 2分法查表。 
	{ 
		if (fR < RTD_TAB_PT100[i]) 
		{ 
			cTop = i; 
			i = (cTop + cBottom) / 2; 
		} 
		else if (fR > RTD_TAB_PT100[i]) 
		{ 
			cBottom = i; 
			i = (cTop + cBottom) / 2; 
		} 
		else 
		{ 
			iTem = (uint)i - 30;  
			fTem = (float)iTem; 
			
			return fTem; 
		} 
	} 
	
	iTem = (uint)i - 30;
	  
	send_ad_result(0x00);
	fLowRValue  = RTD_TAB_PT100[cBottom]; 
	fHighRValue = RTD_TAB_PT100[cTop];
	
	send_ad_result(cBottom);
	send_ad_result(cTop); 
	
	fTem = ( (fR - fLowRValue) / (fHighRValue - fLowRValue) ) + iTem; // 表格是以5度為一步的。 
	// 兩點內插進行運算。 
	
	return fTem; 
} 


/*******************************************************************************   
名稱: main  
功能: 主函式
返回: 無
********************************************************************************/
void main()   
{  
	uint result,tmr,nResult_TMP;
	uchar TMR_H, TMR_L, nTemp_1,nTemp_2,nTemp_3;
	float fTMP;

	nTemp_1 = 2;
	nTemp_2 = 3;
	nTemp_3	= 0;
	// 設定看門狗 EN_WDT = 1,CLR_WDT = 1,IDLE_WDT = 1, PS2 = 1,PS1 = 1,PS0 = 1
	WDT_CONTR = 0x3f;

	IRIN=1;
	_initiate();      // 初始化      
	ads1110Config();  // 配置ADS1110,採用連續轉換模式,16bit精度,PGA=1
					  // 則取樣電壓值為 V = (OutCode * 2.048) / 32768

	P1M0 |= 0x00;     // 設P1_7為高阻模式 如: P1_0= #00000000B
	P1M1 |= 0x80;

	//AT24C04_ReadPage();

	delay(10);
	for (tmr=0; tmr<0x2000; tmr++);	// 上電延時
	send_byte(CMD_RESET);			// 復位HD7279A
	delay1ms(5);
	Display_TMP(230);	  // 設定初始值23.0℃
	delay1ms(5);
	Display_SETTMP(550);  // 設定初始值55.0℃

	while(1)
	{
		result = get_ad_result();	   // ADC取樣,25次,中值濾波法
		TMR_H = (result >> 8) & 0xff;  // 取高八位
		TMR_L = result & 0xff;		   // 取低八位
		//send_ad_result(TMR_H);
		//send_ad_result(TMR_L);
		//lTmp = result
		fTMP = ((result*2.048)/32768 + 0.0029) / 11 / 0.001021;	  // 用ADC轉換的電壓值計算電阻

		//send_ad_result(0x00);

		delay1ms(10);
		fTMP = CalculateTemperature(fTMP);	 // 查表法轉換溫度值

		// 根據實際標定結果進行資料擬合,得到公式-----實際溫度 = -0.0023*測量溫度*測量溫度 + 1.2692*測量溫度 - 5.2778
		nResult_TMP = (uint)(10*(-0.0023*fTMP*fTMP + 1.2692*fTMP - 5.2778)) + nTMPAdj;	
		 
		if (nTemp_1 != (nResult_TMP/100%100))
		{
			write7279(DECODE0,nResult_TMP/100%100);
			nTemp_1 = nResult_TMP/100%100;
		}
		if (nTemp_2 != (nResult_TMP/10%10))
		{
			write7279(DECODE0+1,(nResult_TMP/10%10)|0x80);
			nTemp_2 = nResult_TMP/10%10;
		}
		if (nTemp_3 != (nResult_TMP%100))
		{
			write7279(DECODE0+2,nResult_TMP%10);
			nTemp_3 = nResult_TMP%10;
		}

		TMR_H = (nResult_TMP >> 8) & 0xff;  // 取高八位
		TMR_L = nResult_TMP & 0xff;		    // 取低八位
		send_ad_result(TMR_H);
		send_ad_result(TMR_L);

		WDT_CONTR = 0x3f;	  // 喂狗 間隔9.1022s
	}
}

執行視訊可以到以下地址觀看:

https://v.youku.com/v_show/id_XMTc0OTg0NjUyOA==.html?spm=a2hzp.8244740.0.0