N76E003之ADC带隙电压(Band-gap)

首先让我们来探究下,什么是带隙电压。
1、我们需要了解ADC测量的影响因素,举个简单的例子。
我们给单片机供电是2.8V,此时用ADC去测量一个1.3V,ADCRH最后得到的值,可能就是142.
如果单片供电是3.3V,这时候再去测量1.3V,ADCRH最后得到的值可能就不再是142了.
如果是5V,得到的数据可能更低。

以上这个简单的例子,相信已经能说明一个简单的问题,ADC得到的数据,会随着供电电压的改变而改变。为了解决这个问题,人们想出了使用外部基准的办法,大致的方法就是使用两个ADC通道,一个通道测量外部基准(如TI431),一个通道进行对目标的测量。知道了基准值,就可以得到一个相对准确的测量值。但这种方法需要占用两个ADC通道,并且需要外部器件,成本较高。这时候就可以使用单片机内置的带隙电压了~

2、带隙电压的构成。
大概如下图所示。R3/R4使用正负温度系数材料,是为了避免温度对分压电阻造成的影响,这样温差造成的影响可以进行互补,避免带隙电压不稳。
N76E003之ADC带隙电压(Band-gap)_第1张图片

3、N76E003的带隙电压。

常温下,所有N76E003的Band-gap电压值会校准在1.17V ~ 1.27 V内。如果想要知道每颗N76E003的
Band-gap实际电压值,可以通过读取UID地址后的2个bytes值来确认。 UID 后的2个bytes储存Band-gap
的实际值,总共12个有效bit。第一个byte是高8位,第二个byte的低4位为12 bit的低4位。

由上所知,我们知道了N76间隙电压大致范围,以及UID中存储着实际数据,接下来我们将在程序中看下,如何得到间隙电压。(以下程序源自新唐官方例程修改)
需要注意的是:

对于N76E003,为了得到更准确的内部带隙电压(band-gap)输入ADC转换值,建议在读取时,放弃模块使能
后的头三笔资料。而后,只要不关闭ADC模块, ADC转换结果都是如规格所列。提醒:程序中如果关闭
了ADC模块,请记得下次打开时,需要再次丢弃3笔。

计算ADC时,通常使用以下公式
实际电压X=测量值Y(VDD/4096)
根据上式,计算带隙电压与测量到的带隙电压的比值,然后12bit深度4096,就可以得到当前的VDD电压,如下式
VDD=4096(UID中的带隙电压/ADC测量得到的带隙电压)
故有
VDD/4096=(UID中的带隙电压/ADC测量得到的带隙电压)
令(UID中的带隙电压/ADC测量得到的带隙电压)=Coe
实际电压X=测量值Y * Coe
用上式的比例系数,在普通测量时,就可以用修来正测量值,当然你也可以用带隙电压来推算VDD值。

程序的大概流程,先使用 READ_BANDGAP();函数,得到UID中的带隙电压,再通过ADC测量一次带隙电压,最终得到Coe(系数),后使能相关ADC通道,在中断中,测量值*Coe得到修正的数据。

#include "N76E003.h"
#include "Common.h"
#include "Delay.h"
#include "SFR_Macro.h"
#include "Function_define.h"

double  Bandgap_Voltage,ADC_Voltage;			//please always use "double" mode for this
unsigned  char xdata ADCdataH[5], ADCdataL[5];
int ADCsumH=0, ADCsumL=0;
unsigned char ADCavgH,ADCavgL;

		UINT8 BandgapHigh,BandgapLow,BandgapMark;
		double Bandgap_Value,Bandgap_Voltage_Temp;
		double Coe,bgvalue,RC_value;//比例系数,测量带隙电压
		

/*
程序功能:读取UID中带隙电压值;通过ADC,测量实际的带隙电压;得到比例系数COE;
本程序需要放在ADC正常测量前。
*/
void READ_BANDGAP()
{
		unsigned int i;
		set_IAPEN;
		IAPCN = READ_UID;
		IAPAL = 0x0d;
    IAPAH = 0x00;
    set_IAPGO;
		BandgapLow = IAPFD;
		BandgapMark = BandgapLow&0xF0;
			
		if (BandgapMark==0x80)
		{
				BandgapLow = BandgapLow&0x0F;
				IAPAL = 0x0C;
				IAPAH = 0x00;
				set_IAPGO;
				BandgapHigh = IAPFD;
				Bandgap_Value = (BandgapHigh<<4)+BandgapLow;
				Bandgap_Voltage_Temp = Bandgap_Value*3/4;
				Bandgap_Voltage = Bandgap_Voltage_Temp - 33;			//the actually banggap voltage value is similar this value.
		}
		if (BandgapMark==0x00)
		{
				BandgapLow = BandgapLow&0x0F;
				IAPAL = 0x0C;
				IAPAH = 0x00;
				set_IAPGO;
				BandgapHigh = IAPFD;
				Bandgap_Value = (BandgapHigh<<4)+BandgapLow;
				Bandgap_Voltage= Bandgap_Value*3/4;
		}
		if (BandgapMark==0x90)
		{
				IAPAL = 0x0E;
				IAPAH = 0x00;
				set_IAPGO;
				BandgapHigh = IAPFD;
				IAPAL = 0x0F;
				IAPAH = 0x00;
				set_IAPGO;
				BandgapLow = IAPFD;
				BandgapLow = BandgapLow&0x0F;
				Bandgap_Value = (BandgapHigh<<4)+BandgapLow;
				Bandgap_Voltage= Bandgap_Value*3/4;
		}
		clr_IAPEN;
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------		
				Enable_ADC_BandGap;	//使能ADC带隙电压											
				CKDIV = 0x02;				// IMPORTANT!! Modify system clock to 4MHz ,then add the ADC sampling clock base to add the sampling timing.
				for(i=0;i<5;i++)		//采样5次,不要前面三次
				{																					
						clr_ADCF;
						set_ADCS;																
						while(ADCF == 0);
						ADCdataH[i] = ADCRH;
						ADCdataL[i] = ADCRL;
				}		
				CKDIV = 0x00;
//--------均值滤波--------------------------------------------
				for(i=2;i<5;i++)													// use the last 3 times data to make average 
				{
					ADCsumH = ADCsumH + ADCdataH[i];
					ADCsumL = ADCsumL + ADCdataL[i];
				}				
				ADCavgH = ADCsumH/3;
				ADCavgL = ADCsumL/3;
				bgvalue = (ADCavgH<<4) + ADCavgL;
				Coe=(Bandgap_Voltage/bgvalue);
				ADCsumH = 0;
				ADCsumL = 0;	
}



void ADC_ISR (void) interrupt 11
{
	if(ADCF)
	{
		clr_ADCF;//清除ADC转化完成标志,进行下一次转换
		set_ADCS;//当单次转换完成后,ADCS会硬件置0,需要重新使能
		RC_value= (ADCRH<<4) + ADCRL;//得到ADC转换值
		ADC_Voltage=RC_value*Coe;
	}
}


void main (void) 
{
  Set_All_GPIO_Quasi_Mode;
	READ_BANDGAP();
	Enable_ADC_AIN6;//配置使能P03,作为AIN6。
	//P04_FALLINGEDGE_TRIG_ADC;// 使用P04下降沿触发中断,使			    用外部触发时,可以不使能ADCS。
  set_EADC;//使能ADC中断
	EA = 1;
	set_ADCS;//使能ADCS,启动ADC测量
	while(1);
}

你可能感兴趣的:(N76E003,N76E003,单片机,学习)