123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275 |
- //###########################################################################
- //
- // FILE: DSP2803x_Adc.c
- //
- // TITLE: DSP2803x ADC Initialization & Support Functions.
- //
- //###########################################################################
- // $TI Release: F2803x C/C++ Header Files and Peripheral Examples V130 $
- // $Release Date: May 8, 2015 $
- // $Copyright: Copyright (C) 2009-2015 Texas Instruments Incorporated -
- // http://www.ti.com/ ALL RIGHTS RESERVED $
- //###########################################################################
- #include "DSP2803x_Device.h" // DSP2803x Headerfile Include File
- #include "DSP2803x_Examples.h" // DSP2803x Examples Include File
- #define ADC_usDELAY 1000L
- //---------------------------------------------------------------------------
- // InitAdc:
- //---------------------------------------------------------------------------
- // This function initializes ADC to a known state.
- //
- // NOTE: ADC INIT IS DIFFERENT ON 2803x DEVICES COMPARED TO OTHER 28X DEVICES
- //
- // *IMPORTANT*
- // IF RUNNING FROM FLASH, PLEASE COPY OVER THE SECTION "ramfuncs" FROM FLASH
- // TO RAM PRIOR TO CALLING InitSysCtrl(). THIS PREVENTS THE MCU FROM THROWING
- // AN EXCEPTION WHEN A CALL TO DELAY_US() IS MADE.
- //
- void InitAdc(void)
- {
- extern void DSP28x_usDelay(Uint32 Count);
- // *IMPORTANT*
- // The Device_cal function, which copies the ADC calibration values from TI reserved
- // OTP into the ADCREFSEL and ADCOFFTRIM registers, occurs automatically in the
- // Boot ROM. If the boot ROM code is bypassed during the debug process, the
- // following function MUST be called for the ADC to function according
- // to specification. The clocks to the ADC MUST be enabled before calling this
- // function.
- // See the device data manual and/or the ADC Reference
- // Manual for more information.
- EALLOW;
- SysCtrlRegs.PCLKCR0.bit.ADCENCLK = 1;
- (*Device_cal)();
- EDIS;
- // To powerup the ADC the ADCENCLK bit should be set first to enable
- // clocks, followed by powering up the bandgap, reference circuitry, and ADC core.
- // Before the first conversion is performed a 5ms delay must be observed
- // after power up to give all analog circuits time to power up and settle
- // Please note that for the delay function below to operate correctly the
- // CPU_RATE define statement in the DSP2803x_Examples.h file must
- // contain the correct CPU clock period in nanoseconds.
- EALLOW;
- AdcRegs.ADCCTL1.bit.ADCBGPWD = 1; // Power ADC BG
- AdcRegs.ADCCTL1.bit.ADCREFPWD = 1; // Power reference
- AdcRegs.ADCCTL1.bit.ADCPWDN = 1; // Power ADC
- AdcRegs.ADCCTL1.bit.ADCENABLE = 1; // Enable ADC
- AdcRegs.ADCCTL1.bit.ADCREFSEL = 0; // Select interal BG
- EDIS;
- DELAY_US(ADC_usDELAY); // Delay before converting ADC channels
- }
- void InitAdcAio()
- {
- EALLOW;
- /* Configure ADC pins using AIO regs*/
- // This specifies which of the possible AIO pins will be Analog input pins.
- // NOTE: AIO1,3,5,7-9,11,13,15 are analog inputs in all AIOMUX1 configurations.
- // Comment out other unwanted lines.
- GpioCtrlRegs.AIOMUX1.bit.AIO2 = 2; // Configure AIO2 for A2 (analog input) operation
- GpioCtrlRegs.AIOMUX1.bit.AIO4 = 2; // Configure AIO4 for A4 (analog input) operation
- GpioCtrlRegs.AIOMUX1.bit.AIO6 = 2; // Configure AIO6 for A6 (analog input) operation
- GpioCtrlRegs.AIOMUX1.bit.AIO10 = 2; // Configure AIO10 for B2 (analog input) operation
- GpioCtrlRegs.AIOMUX1.bit.AIO12 = 2; // Configure AIO12 for B4 (analog input) operation
- GpioCtrlRegs.AIOMUX1.bit.AIO14 = 2; // Configure AIO14 for B6 (analog input) operation
- EDIS;
- }
- /* AdcoffsetSelfCal-
- This function re-calibrates the ADC zero offset error by converting the VREFLO reference with
- the ADC and modifying the ADCOFFTRIM register. VREFLO is sampled by the ADC using an internal
- MUX select which connects VREFLO to A5 without sacrificing an external ADC pin. This
- function calls two other functions:
- - AdcChanSelect(channel) – selects the ADC channel to convert
- - AdcConversion() – initiates several ADC conversions and returns the average
- */
- void AdcOffsetSelfCal()
- {
- Uint16 AdcConvMean;
- EALLOW;
- AdcRegs.ADCCTL1.bit.ADCREFSEL = 0; //Select internal reference mode
- AdcRegs.ADCCTL1.bit.VREFLOCONV = 1; //Select VREFLO internal connection on B5
- AdcChanSelect(13); //Select channel B5 for all SOC
- AdcRegs.ADCOFFTRIM.bit.OFFTRIM = 80; //Apply artificial offset (+80) to account for a negative offset that may reside in the ADC core
- AdcConvMean = AdcConversion(); //Capture ADC conversion on VREFLO
- AdcRegs.ADCOFFTRIM.bit.OFFTRIM = 80 - AdcConvMean; //Set offtrim register with new value (i.e remove artical offset (+80) and create a two's compliment of the offset error)
- AdcRegs.ADCCTL1.bit.VREFLOCONV = 0; //Select external ADCIN5 input pin on B5
- EDIS;
- }
- /* AdcChanSelect-
- This function selects the ADC channel to convert by setting all SOC channel selects to a single channel.
- * IMPORTANT * This function will overwrite previous SOC channel select settings. Recommend saving
- the previous settings.
- */
- void AdcChanSelect(Uint16 ch_no)
- {
- AdcRegs.ADCSOC0CTL.bit.CHSEL= ch_no;
- AdcRegs.ADCSOC1CTL.bit.CHSEL= ch_no;
- AdcRegs.ADCSOC2CTL.bit.CHSEL= ch_no;
- AdcRegs.ADCSOC3CTL.bit.CHSEL= ch_no;
- AdcRegs.ADCSOC4CTL.bit.CHSEL= ch_no;
- AdcRegs.ADCSOC5CTL.bit.CHSEL= ch_no;
- AdcRegs.ADCSOC6CTL.bit.CHSEL= ch_no;
- AdcRegs.ADCSOC7CTL.bit.CHSEL= ch_no;
- AdcRegs.ADCSOC8CTL.bit.CHSEL= ch_no;
- AdcRegs.ADCSOC9CTL.bit.CHSEL= ch_no;
- AdcRegs.ADCSOC10CTL.bit.CHSEL= ch_no;
- AdcRegs.ADCSOC11CTL.bit.CHSEL= ch_no;
- AdcRegs.ADCSOC12CTL.bit.CHSEL= ch_no;
- AdcRegs.ADCSOC13CTL.bit.CHSEL= ch_no;
- AdcRegs.ADCSOC14CTL.bit.CHSEL= ch_no;
- AdcRegs.ADCSOC15CTL.bit.CHSEL= ch_no;
- } //end AdcChanSelect
- /* AdcConversion -
- This function initiates several ADC conversions and returns the average. It uses ADCINT1 and ADCINT2
- to "ping-pong" between SOC0-7 and SOC8-15 and is referred to as "ping-pong" sampling.
- * IMPORTANT * This function will overwrite previous ADC settings. Recommend saving previous settings.
- */
- Uint16 AdcConversion(void)
- {
- Uint16 index, SampleSize, Mean, ACQPS_Value;
- Uint32 Sum;
- index = 0; //initialize index to 0
- SampleSize = 256; //set sample size to 256 (**NOTE: Sample size must be multiples of 2^x where is an integer >= 4)
- Sum = 0; //set sum to 0
- Mean = 999; //initialize mean to known value
- //Set the ADC sample window to the desired value (Sample window = ACQPS + 1)
- ACQPS_Value = 8;
- AdcRegs.ADCSOC0CTL.bit.ACQPS = ACQPS_Value;
- AdcRegs.ADCSOC1CTL.bit.ACQPS = ACQPS_Value;
- AdcRegs.ADCSOC2CTL.bit.ACQPS = ACQPS_Value;
- AdcRegs.ADCSOC3CTL.bit.ACQPS = ACQPS_Value;
- AdcRegs.ADCSOC4CTL.bit.ACQPS = ACQPS_Value;
- AdcRegs.ADCSOC5CTL.bit.ACQPS = ACQPS_Value;
- AdcRegs.ADCSOC6CTL.bit.ACQPS = ACQPS_Value;
- AdcRegs.ADCSOC7CTL.bit.ACQPS = ACQPS_Value;
- AdcRegs.ADCSOC8CTL.bit.ACQPS = ACQPS_Value;
- AdcRegs.ADCSOC9CTL.bit.ACQPS = ACQPS_Value;
- AdcRegs.ADCSOC10CTL.bit.ACQPS = ACQPS_Value;
- AdcRegs.ADCSOC11CTL.bit.ACQPS = ACQPS_Value;
- AdcRegs.ADCSOC12CTL.bit.ACQPS = ACQPS_Value;
- AdcRegs.ADCSOC13CTL.bit.ACQPS = ACQPS_Value;
- AdcRegs.ADCSOC14CTL.bit.ACQPS = ACQPS_Value;
- AdcRegs.ADCSOC15CTL.bit.ACQPS = ACQPS_Value;
- //Enable ping-pong sampling
- // Enabled ADCINT1 and ADCINT2
- AdcRegs.INTSEL1N2.bit.INT1E = 1;
- AdcRegs.INTSEL1N2.bit.INT2E = 1;
- // Disable continuous sampling for ADCINT1 and ADCINT2
- AdcRegs.INTSEL1N2.bit.INT1CONT = 0;
- AdcRegs.INTSEL1N2.bit.INT2CONT = 0;
- AdcRegs.ADCCTL1.bit.INTPULSEPOS = 1; //ADCINTs trigger at end of conversion
- // Setup ADCINT1 and ADCINT2 trigger source
- AdcRegs.INTSEL1N2.bit.INT1SEL = 6; //EOC6 triggers ADCINT1
- AdcRegs.INTSEL1N2.bit.INT2SEL = 14; //EOC14 triggers ADCINT2
- // Setup each SOC's ADCINT trigger source
- AdcRegs.ADCINTSOCSEL1.bit.SOC0 = 2; //ADCINT2 starts SOC0-7
- AdcRegs.ADCINTSOCSEL1.bit.SOC1 = 2;
- AdcRegs.ADCINTSOCSEL1.bit.SOC2 = 2;
- AdcRegs.ADCINTSOCSEL1.bit.SOC3 = 2;
- AdcRegs.ADCINTSOCSEL1.bit.SOC4 = 2;
- AdcRegs.ADCINTSOCSEL1.bit.SOC5 = 2;
- AdcRegs.ADCINTSOCSEL1.bit.SOC6 = 2;
- AdcRegs.ADCINTSOCSEL1.bit.SOC7 = 2;
- AdcRegs.ADCINTSOCSEL2.bit.SOC8 = 1; //ADCINT1 starts SOC8-15
- AdcRegs.ADCINTSOCSEL2.bit.SOC9 = 1;
- AdcRegs.ADCINTSOCSEL2.bit.SOC10 = 1;
- AdcRegs.ADCINTSOCSEL2.bit.SOC11 = 1;
- AdcRegs.ADCINTSOCSEL2.bit.SOC12 = 1;
- AdcRegs.ADCINTSOCSEL2.bit.SOC13 = 1;
- AdcRegs.ADCINTSOCSEL2.bit.SOC14 = 1;
- AdcRegs.ADCINTSOCSEL2.bit.SOC15 = 1;
- DELAY_US(ADC_usDELAY); // Delay before converting ADC channels
- //ADC Conversion
- AdcRegs.ADCSOCFRC1.all = 0x00FF; // Force Start SOC0-7 to begin ping-pong sampling
- while( index < SampleSize ){
- //Wait for ADCINT1 to trigger, then add ADCRESULT0-7 registers to sum
- while (AdcRegs.ADCINTFLG.bit.ADCINT1 == 0){}
- AdcRegs.ADCINTFLGCLR.bit.ADCINT1 = 1; //Must clear ADCINT1 flag since INT1CONT = 0
- Sum += AdcResult.ADCRESULT0;
- Sum += AdcResult.ADCRESULT1;
- Sum += AdcResult.ADCRESULT2;
- Sum += AdcResult.ADCRESULT3;
- Sum += AdcResult.ADCRESULT4;
- Sum += AdcResult.ADCRESULT5;
- Sum += AdcResult.ADCRESULT6;
- // Wait for SOC9 conversion to start, which gives time for SOC7 conversion result
- while( AdcRegs.ADCSOCFLG1.bit.SOC9 == 1 ){}
- Sum += AdcResult.ADCRESULT7;
- //Wait for ADCINT2 to trigger, then add ADCRESULT8-15 registers to sum
- while (AdcRegs.ADCINTFLG.bit.ADCINT2 == 0){}
- AdcRegs.ADCINTFLGCLR.bit.ADCINT2 = 1; //Must clear ADCINT2 flag since INT2CONT = 0
- Sum += AdcResult.ADCRESULT8;
- Sum += AdcResult.ADCRESULT9;
- Sum += AdcResult.ADCRESULT10;
- Sum += AdcResult.ADCRESULT11;
- Sum += AdcResult.ADCRESULT12;
- Sum += AdcResult.ADCRESULT13;
- Sum += AdcResult.ADCRESULT14;
- // Wait for SOC1 conversion to start, which gives time for SOC15 conversion result
- while( AdcRegs.ADCSOCFLG1.bit.SOC1 == 1 ){}
- Sum += AdcResult.ADCRESULT15;
- index+=16;
- } // end data collection
- //Disable ADCINT1 and ADCINT2 to STOP the ping-pong sampling
- AdcRegs.INTSEL1N2.bit.INT1E = 0;
- AdcRegs.INTSEL1N2.bit.INT2E = 0;
- while(AdcRegs.ADCSOCFLG1.all != 0){} // Wait for any pending SOCs to complete
- // Clear any pending interrupts
- AdcRegs.ADCINTFLGCLR.bit.ADCINT1 = 1;
- AdcRegs.ADCINTFLGCLR.bit.ADCINT2 = 1;
- AdcRegs.ADCINTOVFCLR.bit.ADCINT1 = 1;
- AdcRegs.ADCINTOVFCLR.bit.ADCINT2 = 1;
- //reset RR pointer to 32, so that next SOC is SOC0
- AdcRegs.SOCPRICTL.bit.SOCPRIORITY = 1;
- while( AdcRegs.SOCPRICTL.bit.SOCPRIORITY != 1 );
- AdcRegs.SOCPRICTL.bit.SOCPRIORITY = 0;
- while( AdcRegs.SOCPRICTL.bit.SOCPRIORITY != 0 );
- Mean = Sum / SampleSize; //Calculate average ADC sample value
- return Mean; //return the average
- }//end AdcConversion
- //===========================================================================
- // End of file.
- //===========================================================================
|