如图里面所示,无论我是在ID端口输入恒定电压,还是直接在A0端口输入,结果寄存器ADCRESULT0的数一直都在波动,波动值大概有100左右,偶尔还会发生突变,变成接近0或者4095,我用的是12位AD模式,用16位的话波动值更大,用示波器检测电源信号,看到电源只有几毫伏的波动,所以一直不知道是哪出问题了,下面是AD的配置程序,还望各位答疑解惑
void ConfigureADC(void)
{
EALLOW;
//write configurations
AdcaRegs.ADCCTL2.bit.PRESCALE = 6; //set ADCCLK divider to /4
AdcbRegs.ADCCTL2.bit.PRESCALE = 6; //set ADCCLK divider to /4
AdcSetMode(ADC_ADCA, ADC_RESOLUTION_12BIT, ADC_SIGNALMODE_SINGLE);
AdcSetMode(ADC_ADCB, ADC_RESOLUTION_12BIT, ADC_SIGNALMODE_SINGLE);
//Set pulse positions to late
AdcaRegs.ADCCTL1.bit.INTPULSEPOS = 1;
AdcbRegs.ADCCTL1.bit.INTPULSEPOS = 1;
//power up the ADCs
AdcaRegs.ADCCTL1.bit.ADCPWDNZ = 1;
AdcbRegs.ADCCTL1.bit.ADCPWDNZ = 1;
//delay for 1ms to allow ADC time to power up
DELAY_US(1000);
EDIS;
}
void SetupADC(void)
{
Uint16 acqps;
//determine minimum acquisition window (in SYSCLKS) based on resolution
IF(ADC_RESOLUTION_12BIT == AdcaRegs.ADCCTL2.bit.RESOLUTION){
acqps = 14; //75ns
}
else { //resolution is 16-bit
acqps = 63; //320ns
}
//Select the channels to convert and end of conversion flag
//ADCA
EALLOW;
AdcaRegs.ADCSOC0CTL.bit.CHSEL = 0; //SOC0 will convert pin A0
AdcaRegs.ADCSOC0CTL.bit.ACQPS = acqps; //sample window is acqps + 1 SYSCLK cycles
AdcaRegs.ADCSOC0CTL.bit.TRIGSEL = 1; //这里设置1为timer0中断,设置0为软件中断
AdcaRegs.ADCSOC1CTL.bit.CHSEL = 1; //SOC1 will convert pin A1
AdcaRegs.ADCSOC1CTL.bit.ACQPS = acqps; //sample window is acqps + 1 SYSCLK cycles
AdcaRegs.ADCSOC1CTL.bit.TRIGSEL = 1; //这里设置1为timer0中断,设置0为软件中断
AdcaRegs.ADCSOC2CTL.bit.CHSEL = 2; //SOC1 will convert pin A1
AdcaRegs.ADCSOC2CTL.bit.ACQPS = acqps; //sample window is acqps + 1 SYSCLK cycles
AdcaRegs.ADCSOC2CTL.bit.TRIGSEL = 1; //这里设置1为timer0中断,设置0为软件中断
AdcaRegs.ADCSOC3CTL.bit.CHSEL = 3; //SOC1 will convert pin A1
AdcaRegs.ADCSOC3CTL.bit.ACQPS = acqps; //sample window is acqps + 1 SYSCLK cycles
AdcaRegs.ADCSOC3CTL.bit.TRIGSEL = 1; //这里设置1为timer0中断,设置0为软件中断
AdcaRegs.ADCSOC4CTL.bit.CHSEL = 4; //SOC1 will convert pin A1
AdcaRegs.ADCSOC4CTL.bit.ACQPS = acqps; //sample window is acqps + 1 SYSCLK cycles
AdcaRegs.ADCSOC4CTL.bit.TRIGSEL = 1; //这里设置1为timer0中断,设置0为软件中断
AdcaRegs.ADCSOC5CTL.bit.CHSEL = 5; //SOC1 will convert pin A1
AdcaRegs.ADCSOC5CTL.bit.ACQPS = acqps; //sample window is acqps + 1 SYSCLK cycles
AdcaRegs.ADCSOC5CTL.bit.TRIGSEL = 1; //这里设置1为timer0中断,设置0为软件中断
//ADCB
AdcbRegs.ADCSOC0CTL.bit.CHSEL = 0; //SOC0 will convert pin B0
AdcbRegs.ADCSOC0CTL.bit.ACQPS = acqps; //sample window is acqps + 1 SYSCLK cycles
AdcbRegs.ADCSOC0CTL.bit.TRIGSEL = 1; //这里设置1为timer0中断,设置0为软件中断
AdcbRegs.ADCSOC1CTL.bit.CHSEL = 1; //SOC1 will convert pin B1
AdcbRegs.ADCSOC1CTL.bit.ACQPS = acqps; //sample window is acqps + 1 SYSCLK cycles
AdcbRegs.ADCSOC1CTL.bit.TRIGSEL = 1; //这里设置1为timer0中断,设置0为软件中断
AdcbRegs.ADCSOC2CTL.bit.CHSEL = 2; //SOC1 will convert pin B1
AdcbRegs.ADCSOC2CTL.bit.ACQPS = acqps; //sample window is acqps + 1 SYSCLK cycles
AdcbRegs.ADCSOC2CTL.bit.TRIGSEL = 1; //这里设置1为timer0中断,设置0为软件中断
AdcbRegs.ADCSOC3CTL.bit.CHSEL = 3; //SOC1 will convert pin B1
AdcbRegs.ADCSOC3CTL.bit.ACQPS = acqps; //sample window is acqps + 1 SYSCLK cycles
AdcaRegs.ADCSOC3CTL.bit.TRIGSEL = 1; //这里设置1为timer0中断,设置0为软件中断
}
void AdcSetMode(Uint16 adc, Uint16 resolution, Uint16 signalmode)
{
Uint16 adcOffsetTrimOTPIndex; //index into OTP table of ADC offset trims
Uint16 adcOffsetTrim; //temporary ADC offset trim
//re-populate INL trim
CalAdcINL(adc);
if(0xFFFF != *((Uint16*)GetAdcOffsetTrimOTP)){
//offset trim function is programmed into OTP, so call it
//calculate the index into OTP table of offset trims and call
//function to return the correct offset trim
adcOffsetTrimOTPIndex = 4*adc + 2*resolution + 1*signalmode;
adcOffsetTrim = (*GetAdcOffsetTrimOTP)(adcOffsetTrimOTPIndex);
}
else {
//offset trim function is not populated, so set offset trim to 0
adcOffsetTrim = 0;
}
//Apply the resolution and signalmode to the specified ADC.
//Also apply the offset trim and, if needed, linearity trim correction.
switch(adc){
case ADC_ADCA:
AdcaRegs.ADCCTL2.bit.RESOLUTION = resolution;
AdcaRegs.ADCCTL2.bit.SIGNALMODE = signalmode;
AdcaRegs.ADCOFFTRIM.all = adcOffsetTrim;
if(ADC_RESOLUTION_12BIT == resolution){
//12-bit linearity trim workaround
AdcaRegs.ADCINLTRIM1 &= 0xFFFF0000;
AdcaRegs.ADCINLTRIM2 &= 0xFFFF0000;
AdcaRegs.ADCINLTRIM4 &= 0xFFFF0000;
AdcaRegs.ADCINLTRIM5 &= 0xFFFF0000;
}
break;
case ADC_ADCB:
AdcbRegs.ADCCTL2.bit.RESOLUTION = resolution;
AdcbRegs.ADCCTL2.bit.SIGNALMODE = signalmode;
AdcbRegs.ADCOFFTRIM.all = adcOffsetTrim;
if(ADC_RESOLUTION_12BIT == resolution){
//12-bit linearity trim workaround
AdcbRegs.ADCINLTRIM1 &= 0xFFFF0000;
AdcbRegs.ADCINLTRIM2 &= 0xFFFF0000;
AdcbRegs.ADCINLTRIM4 &= 0xFFFF0000;
AdcbRegs.ADCINLTRIM5 &= 0xFFFF0000;
}
break;
case ADC_ADCC:
AdccRegs.ADCCTL2.bit.RESOLUTION = resolution;
AdccRegs.ADCCTL2.bit.SIGNALMODE = signalmode;
AdccRegs.ADCOFFTRIM.all = adcOffsetTrim;
if(ADC_RESOLUTION_12BIT == resolution){
//12-bit linearity trim workaround
AdccRegs.ADCINLTRIM1 &= 0xFFFF0000;
AdccRegs.ADCINLTRIM2 &= 0xFFFF0000;
AdccRegs.ADCINLTRIM4 &= 0xFFFF0000;
AdccRegs.ADCINLTRIM5 &= 0xFFFF0000;
}
break;
case ADC_ADCD:
AdcdRegs.ADCCTL2.bit.RESOLUTION = resolution;
AdcdRegs.ADCCTL2.bit.SIGNALMODE = signalmode;
AdcdRegs.ADCOFFTRIM.all = adcOffsetTrim;
if(ADC_RESOLUTION_12BIT == resolution){
//12-bit linearity trim workaround
AdcdRegs.ADCINLTRIM1 &= 0xFFFF0000;
AdcdRegs.ADCINLTRIM2 &= 0xFFFF0000;
AdcdRegs.ADCINLTRIM4 &= 0xFFFF0000;
AdcdRegs.ADCINLTRIM5 &= 0xFFFF0000;
}
break;
}
}
/*
* Loads INL trim values from OTP into the trim registers of the specified ADC.
* Use only as part of AdcSetMode function, since linearity trim correction
* is needed for some modes.
*/
void CalAdcINL(Uint16 adc)
{
switch(adc){
case ADC_ADCA:
if(0xFFFF != *((Uint16*)CalAdcaINL)){
//trim function is programmed into OTP, so call it
(*CalAdcaINL)();
}
else {
//do nothing, no INL trim function populated
}
break;
case ADC_ADCB:
if(0xFFFF != *((Uint16*)CalAdcbINL)){
//trim function is programmed into OTP, so call it
(*CalAdcbINL)();
}
else {
//do nothing, no INL trim function populated
}
break;
case ADC_ADCC:
if(0xFFFF != *((Uint16*)CalAdccINL)){
//trim function is programmed into OTP, so call it
(*CalAdccINL)();
}
else {
//do nothing, no INL trim function populated
}
break;
case ADC_ADCD:
if(0xFFFF != *((Uint16*)CalAdcdINL)){
//trim function is programmed into OTP, so call it
(*CalAdcdINL)();
}
else {
//do nothing, no INL trim function populated
}
break;
}
}
|