前言
基于AD7793的温度测量系统和ADI CN0206_cn推荐文档。采用PT100作为冷结补偿,4线SPI接口,支持SPI复用。32倍增益时最高热动势为36.5mV,对应K热电偶分度表为850摄氏度。AD7793适合高精度测量应用的低功耗、低噪声的完整模拟前端,内置一个低噪声、带有三个差分模拟输入的24位Σ-Δ型ADC。还集成了片内低噪声仪表放大器,可直接输入小信号。
一、AD7793简介
AD7793 是一款适合高精度测量应用的低功耗、低噪声、 完整模拟前端, 内置PGA、 基准电压源、时钟和激励电流, 从而大大简化了热电偶系统设计。 系统峰峰值噪声约为0.02°C。AD7793 的最大功耗仅500 μA, 因而适合低功耗应用,例如整个发送器的功耗必须低于4 mA 的智能发送器等。 AD7793还具有关断选项。在这种模式下,整个ADC及其辅助功能均关断,器件的最大功耗降至1 μA。
主要特性:
1. 24位Σ-Δ ADC:高分辨率(24位)的ADC适合高精度、低噪声信号测量。
2. 输入通道:AD7793有3个差分输入通道(或者6个伪差分输入通道),支持多路传感器或信号的采集。
3. 可编程增益放大器(PGA):AD7793内部带有一个可编程增益放大器,增益可以设置为1、2、4、8、16、32、64、128,便于对不同输入信号幅度进行调节。
4. 低噪声特性:AD7793专为低噪声应用设计,噪声水平在一定条件下低至50 nV。
5. 集成滤波器:AD7793内置低通滤波器,可用于抑制50Hz和60Hz工频干扰。
6. 片内偏置电压和偏移校准功能:消除系统误差,提供高精度输出。
7. SPI接口:AD7793通过标准的SPI接口与外部微控制器或处理器进行通信,方便数据采集和控制。
二、AD7793应用领域
- 热电偶测量、热敏电阻测量
- 仪器仪表信号采集
- 压力传感器,电子秤测量等
三、系统框图及通讯时序
四、温度换算
AD7793提供一种集成式热电偶解决方案,可以直接与热电偶接口。冷结补偿由一个热敏电阻和一个精密电阻提供。该电路只需要这些外部元件来执行冷结测量,以及一些简单的R-C滤波器来满足电磁兼容性要求。
热电偶的传递函数不是线性的。在0°C至+60°C的温度范围,其响应非常接近线性。但是,在更宽的温度范围内,必须使用一个线性化程序处理。AD7793采用单电源供电,热电偶产生的信号必须被偏置到地以上,从而处于该ADC支持的范围。对于128倍的增益,模拟输入端的绝对电压必须在GND + 300 mV至AVDD – 1.1 V范围内。
热敏电阻在+25°C时的值为1 kΩ,0°C时的典型值为815 Ω,+30°C时的典型值为1040 Ω。假设0°C至30°C的传递函数为线性,则冷结温度与热敏电阻R之间的关系为:
冷结温度 = 30 × (R – 815)/(1040 – 815)
对热敏电阻通道进行采样时,AD7793以1倍的增益工作。对于+30°C的最大冷结温度,热敏电阻上产生的最大电压为1 mA × 1040 Ω = 1.04 V。
AD7793以16.7 Hz的输出数据速率工作。每读取10个热电偶转换结果,就读取1个热敏电阻转换结果。相应的温度等于:
温度 = 热电偶温度 + 冷结温度
图2显示了T型热电偶上产生的电压与温度的关系。圆圈内的区域是从0°C到+60°C,该区域内的传递函数接近线性。
五、热电偶温度计算
参照上述图2电压与温度的关系,由分度表近似计算热电动势与温度的斜率方式计算,也可以根据国际温标ITS90多项式拟合计算。
通过斜率计算:从0°C到+60°C,电压与温度的传递函数接近线性y=Kx。查看分度表上的对应值,计算温度变化对电压的变化率。当然,函数是接近线性,而不是线性,计算得到的是估算值。
斜率
S
=
E
M
F
60
°
C
−
E
M
F
0
°
C
60
℃
−
0
℃
斜率S=\frac{EMF60°C-EMF0°C}{60℃-0℃}
斜率S=60℃−0℃EMF60°C−EMF0°C
由于公式是根据热电偶的电压求解温度,还需求斜率的倒数1/S得到对应的系数。图下所示K型热电偶分度表:
通过ITS90多项式拟合计算:ITS-90提供了热电偶电压和温度之间的精确近似公式,而ITS90多项式又分为正多项式和逆多项式。正多项式从一个已知温度(˚C)提供热电电压(V),逆多项式从一个已知热电电压(V)提供温度(˚C)。而示例中的系数则根据正多项式计算出:
E
(
T
)
=
a
0
+
a
1
T
+
a
2
T
2
+
.
.
.
+
a
n
T
n
E(T)=a_0+a_1T+a_2T^2+...+a_nT^n
E(T)=a0+a1T+a2T2+...+anTn
其中,E(T)是热电偶在温度T时产生的热电动势(以mV为单位),a0,a1,a2,…,an是热电偶的常数系数。
在0°C到60°C的温度范围内,热电偶电压与温度关系可以被近似为线性。ITS-90标准多项式可以查到,近似在该温度范围内的关系为线性,可以通过正、逆多项式的一阶系数(即线性部分)来计算线性系数。
E
(
T
)
≈
a
0
+
a
1
T
E(T)≈a_0+a_1T
E(T)≈a0+a1T
对于K型热电偶,一次项系数a1对应的正多项式系数为 38.9212 mV/°C。这个系数可以理解为每升高1°C,热电偶产生的电压大约增加 38.9212 μV。为了将热电偶的电压换算成温度,需要求解出从电压 𝐸(𝑇) 到温度 𝑇的转换系数。基于一次项的近似公式:
T
≈
E
(
T
)
a
1
≈
25692.9385
℃
/
V
T≈\frac{E(T)}{a_1}≈25692.9385℃/V
T≈a1E(T)≈25692.9385℃/V
五、AD7793采集示例
1.准备工作
STM32F103ZET6开发板、AD7793温度采集模块、K型热电偶。
2.引脚接线
AD7793 | STM32F103 |
---|---|
3.3V | 3V3 |
GND | GND |
DRDY | PD0 |
SDI | PD2 |
SCLK | PD3 |
nCS | PD4 |
3.示例代码
AD7793.c
#include "ad7793.h"
void RCC_Configurations(void)
{
ErrorStatus HSEStartUpStatus;
RCC_DeInit();
RCC_HSEConfig(RCC_HSE_ON);
HSEStartUpStatus = RCC_WaitForHSEStartUp();
if(HSEStartUpStatus == SUCCESS)
{
FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);
FLASH_SetLatency(FLASH_Latency_2);
RCC_HCLKConfig(RCC_SYSCLK_Div1);
RCC_PCLK2Config(RCC_HCLK_Div1);
RCC_PCLK1Config(RCC_HCLK_Div2);
RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9);
RCC_PLLCmd(ENABLE);
while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET) { }
RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
while(RCC_GetSYSCLKSource() != 0x08) { }
}
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA2, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO | RCC_APB2Periph_GPIOC| RCC_APB2Periph_GPIOD, ENABLE);
}
void GPIO_Configurations(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3|GPIO_Pin_2|GPIO_Pin_4;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOD, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOD, &GPIO_InitStructure);
}
void NVIC_Configurations(void)
{
#ifdef VECT_TAB_RAM
NVIC_SetVectorTable(NVIC_VectTab_RAM, 0x0);
#else
NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0);
#endif
}
void Delay(vu32 nCount)
{
for(; nCount != 0; nCount--);
}
void AD7793Reset(void)
{
uint8_t ResetTime;
ResetTime=50;
AD7793_SCLK_H;
AD7793_CS_L;
AD7793_SDI_H;
while(ResetTime--)
{
AD7793_SCLK_L;
Delay(200);
AD7793_SCLK_H;
Delay(200);
}
}
void AD7793Write(uint8_t Data)
{
uint8_t data;
data=Data;
AD7793_SCLK_H;
AD7793_CS_L;
AD7793_SDI_L;
for(uint8_t i=0;i<8;i++)
{
AD7793_SCLK_L;
if(data&0x80)
AD7793_SDI_H;
else
AD7793_SDI_L;
Delay(100);
AD7793_SCLK_H;
Delay(100);
data=data<<1;
}
//AD7793_CS_H;
}
uint32_t AD7793Read(void)
{
uint32_t DATA;
AD7793_SDI_L;
AD7793_CS_L;
AD7793_SCLK_H;
DATA=0;
for(uint8_t i=0;i<24;i++)
{
DATA<<=1;
AD7793_SCLK_L;
Delay(100);
if(AD7793_DOUT)
DATA|=0x01;
AD7793_SCLK_H;
Delay(100);
}
//AD7793_CS_H;
return DATA;
}
uint8_t AD7793Read_Byte(void)
{
uint8_t DATA;
AD7793_SDI_L;
AD7793_CS_L;
AD7793_SCLK_H;
DATA=0;
for(uint8_t i=0;i<8;i++)
{
DATA<<=1;
AD7793_SCLK_L;
Delay(100);
if(AD7793_DOUT)
DATA|=0x01;
AD7793_SCLK_H;
Delay(100);
}
//AD7793_CS_H;
return DATA;
}
uint8_t Get_AD7793_ID(void)
{
uint8_t ID;
AD7793Write(0x60);//读满刻度校准寄存器的值
ID=AD7793Read_Byte();
return ID;
}
void AD7793_thermocouple_init(void)
{
AD7793Reset();
Delay(20000);
AD7793Write(0x28);//IO register
AD7793Write(0x0A);//Set 420uA Current Source for PT100
AD7793Write(0x10);//configuration register
AD7793Write(0x45);//Gain =32
AD7793Write(0x90);//00010000//10010000
AD7793Write(0x08);//Mode Register
AD7793Write(0x00);//00000000
AD7793Write(0x0B);//00001011 12.5Hz DATA OUT
}
void AD7793_GetPT100_init(void)
{
AD7793Reset();
Delay(20000);
AD7793Write(0x28);//IO register
AD7793Write(0x0A);//Set 420uA Current Source for PT100
AD7793Write(0x10);//configuration register
AD7793Write(0x40);//Gain =1 01000101
AD7793Write(0x11);//10010000//100100001
AD7793Write(0x08);//Mode Register
AD7793Write(0x00);//00000000
AD7793Write(0x0B);//00001011 12.5Hz DATA OUT
}
float Get_PT100(void)//Return the temp of PT100;
{
float PT100_TEMP;
float PT100_R_Value;
uint32_t DATA_T;
while(AD7793_DOUT);
AD7793Write(0x58);
DATA_T=AD7793Read()-0x800000;
PT100_TEMP=DATA_T;
PT100_TEMP/=0x7fffff;
PT100_R_Value=PT100_TEMP*402;
PT100_TEMP=(PT100_R_Value-100)/0.385055;//A gruad
return PT100_TEMP;
}
float Get_thermocouple_Value(void)//Return the Voltage of TC;
{
float Voltage;
uint32_t DATA_T;
int32_t DATA_T1;
while(AD7793_DOUT);
AD7793Write(0x58);
DATA_T=AD7793Read();
DATA_T^=0xFFFFFF;
DATA_T&=0xffffff;
DATA_T1=0x7FFFFF-DATA_T;
Voltage=DATA_T1*1.17; //Vref=1.17V
Voltage/=0x7fffff;
Voltage/=32;//gain = 32
return Voltage;
}
void AD7793init(void)
{
AD7793Reset();
Delay(200);
AD7793Write(0x28);//IO register
AD7793Write(0x06);//AD7793Write(0x02),
AD7793Write(0x10);//configuration register
AD7793Write(0x10);//Gain 1
AD7793Write(0x10);//external Reference
AD7793Write(0x08);//Mode Register
AD7793Write(0x80);//内部零刻度校准
AD7793Write(0x4F);
Delay(800);
while(AD7793_DOUT);
AD7793Write(0x08);//Mode Register
AD7793Write(0xA0);//内部满量程校准
AD7793Write(0x4F);//
Delay(800);
while(AD7793_DOUT);
}
#ifdef DEBUG
void assert_failed(u8* file, u32 line)
{
while (1) { }
}
#endif
main.c
#include "stm32f10x.h"
#include "systemconfig.h"
#include "common.h"
#include "stdio.h"
#include "ad7793.h"
int main(void)
{
float TC_voltage;
float PT100_temp;
float tempsssssssss;
uint32_t TESTSSS;
uint8_t AD7793_ID;
RCC_Configurations();
GPIO_Configurations();
NVIC_Configurations();
AD7793init();
AD7793_ID=Get_AD7793_ID();//Read AD7793 ID(0xXB)
SystemConfiguration(); //系统初始化
USART_Config(USART1,115200); //串口1初始化,波特率 115200
while(1)
{
AD7793_CS_L;
AD7793_thermocouple_init();
Delay_ms(2000);
TC_voltage = Get_thermocouple_Value();
tempsssssssss=TC_voltage*25692.9385+PT100_temp; //读取PT100温度
Delay_ms(2000);
AD7793_GetPT100_init();
Delay_ms(2000);
PT100_temp = Get_PT100();
Delay_ms(2000);
printf(" %.2f℃ ",tempsssssssss);
printf("\r\n");
}
}