最近设计了一台仪器,改动比较大,PCB板面积所限,又需要对热电偶采样读取温度,并对高温炉进行控温,想到了采用NUC120内置AD去读取温度,
发现分辨率略有点小
为什么分辨率会小呢,各位看官听我分析如下
S分度热电偶 温度升限位 1200度 此时热电偶电压为11.952mV,按12mV计算.外围运放电源的电压为5V,由于运放输出到最大值时线性是有问题
的,于是扣除大概1V,手头的精密电阻只有1K 1% 和10K 1% 经过组合选定一个了一个241倍的增益,单级运放,增益已经太大.无法往上再加了(会
造成噪声变大) 于是满程电压为12mV X 241 = 2.9V 要控温精度为1度的话,分辨率要高于控温精度,选定在0.1度的分辨率. 0.1度的分辨率在忽
略热电偶线性的情况下大概为0.01mV ,放大241倍的话为2.4mV NUC120 内置12位AD最小的分辨电压为VREF/4096 = 5/4096 = 1.2mV ,
也就是说这个AD在加上运放的情况下分辨率为0.05度 . 当是认为已经满足了我的要求,结果发现温度跳动比较大,没有原来用CS1242那么稳定.
仔细一看 只有10位精度的保证....这下麻烦大了,难道又要改版,哪又得延期了,怎么办?天无绝人之路,想起了以前看过的一篇帖子,里面提到了高速
ADC可以通过过采样提高分辨率,降低噪声,里面说每增加一位分辨率,需要以4倍的速率过采样,正好AD的速率够高.拿来采用一下.
现在贴出部分代码
#define MAXPRESTOVECNT 256 //炉温滤波缓冲区长度 (为4的4次方,也就是说有效位数增加了4位)
struct ADVALUE
{
long lPreTemp ;
long lTemp;
}AD;
AD AdValue ;
long ADPreStove[MAXPRESTOVECNT];
long ADStovePtr;
void ADCIntRout(uint32_t u32UserData)
{
int tempValue = 0;
AdValue.lPreTemp = AdValue.lTemp ;
AdValue.lTemp -= ADPreStove[ADStovePtr];
ADPreStove[ADStovePtr] = DrvADC_GetConversionData(ADCHANNEL_VSTOVE);
AdValue.lTemp += ADPreStove[ADStovePtr];
ADStovePtr=(++ADStovePtr)%MAXPRESTOVECNT;
}
void InitAD(void)
{
uint32_t i;
DrvADC_Close();
// default setting: single end input, single operation mode, all channel disable, ADC clock frequency = 12MHz/(3+1)
DrvADC_Open(ADC_SINGLE_END, ADC_SINGLE_OP, 0, INTERNAL_RC22MHZ, 0xFF);
DrvADC_SetADCOperationMode(ADC_CONTINUOUS_OP);
DrvADC_SetADCInputMode(ADC_SINGLE_END);
// Select the ADC channels
DrvADC_SetADCChannel(0xE0);
// Set the ADC channel
DrvADC_ConfigADCChannel7(EXTERNAL_INPUT_SIGNAL)
;
//DrvADC_ConfigADCChannel7(INTERNAL_BANDGAP);
//
DrvGPIO_InitFunction(E_FUNC_ADC5);
DrvGPIO_InitFunction(E_FUNC_ADC6);
DrvGPIO_InitFunction(E_FUNC_ADC7);
//
DrvADC_EnableADCInt(ADCIntRout,u32ADCUserData);
i=DrvADC_GetConversionRate();
//
DrvADC_EnableSelfCalibration();
while(!DrvADC_IsCalibrationDone()); //等待自校准完成
// start A/D conversion
//
DrvADC_StartConvert();
}
//AD读取任务
|