Introduction ================================== C2000 devices supports multiple analog-to-digital converters (ADC) in 12-bit mode and/or 16-bit mode. Each ADC module has a single sample-and-hold (S/H) circuit and using multiple ADC modules enables simultaneous sampling or independent operation (sequential sampling). The ADC module is implemented using a successive approximation (SAR) type ADC. For the various ADC modes refer to the table below. [[+g ADC Modes Across Devices An 'X' indicates that the corresponding device has that mode available Device | 12-bit Single Ended | 16-bit Differential | 16-bit Single-Ended ---------------|------------------------------------------------------------------ F28x7x | X | X | F28004x | X | | F2838x | X | X | X F28002x | X | | F28003x | X | | +]] **Differential Signal Mode** In this mode, a pair of pins (positive input ADCINxP and negative input ADCINxN) is sampled and the input applied to the converter is the difference between the two pins (ADCINxP – ADCINxN). A benefit of differential signaling mode is the ability to cancel noise that may be introduced common to both inputs. **Single-Ended Signal Mode** In single-ended mode, a single pin (ADCINx) is sampled and applied to the input of the converter. Start of Conversion (SOC) ---------------------------- The ADC triggering and conversion sequencing is managed by a series of start-of-conversion (SOCx) configuration registers. Each SOCx register configures a single channel conversion, where the SOCx register specifies the trigger source that starts the conversion, the channel to convert, and the acquisition sample window duration. Multiple SOCx registers can be configured for the same trigger, channel, and/or acquisition window. Configuring multiple SOCx registers to use the same trigger will cause that trigger to perform a sequence of conversions, and configuring multiple SOCx registers for the same trigger and channel can oversample the signal. The various trigger sources that can be used to start an ADC conversion include the General Purpose Timers, the ePWM modules, an external pin, and by software. Also, the flag setting of either ADCINT1 or ADCINT2 can be configured as a trigger source which can be used for continuous conversion operation. The ADC interrupt logic can generate up to four interrupts. The results for SOC 0 through 15 appear in result registers 0 through 15, respectively. <figure class='figure' id ="ADC SOCx Functional Diagram"> <img src="adc_resources/adc_soc_functional_diagram.png"/> <figcaption class='figcaption'>ADC SOCx Functional Diagram</figcaption> </figure> <br> [[b Note: The diagram above is for the F28004x, other devices might have different trigger sources. Please refer to the 'ADC Triggering' section of this module for more information.]] The figure above is a conceptual view highlighting a single ADC start-of-conversion functional flow from triggering to interrupt generation. This figure is replicated 16 times and the Driverlib functions highlight the sections that they modify. **ADC SOC Driverlib Function** Configure a start-of-conversion (SOC): ```c // Function inputs: // base is the ADC base address: ADCx_BASE (x = A etc.) // socNumber values are: // ADC_SOC_NUMBERx (x = 0 to 15) // channel values are: // ADC_CH_ADCINx (x = 0 to 15) // sampleWindow parameter is the acquisition window duration in SYSCLK // cycles: value between 1 and 512 cycles inclusive ADC_setupSOC(base, socNumber, trigger, channel, sampleWindow); ``` Configure an interrupt start-of-conversion trigger: ```c // Function inputs: // base is the ADC base address: ADCx_BASE (x = A etc.) // socNumber is: ADC_SOC_NUMBERx (x = 0 to 15) // Trigger value is: // ADC_INT_SOC_TRIGGER_NONE // ADC_INT_SOC_TRIGGER_ADCINTx (x = 1 or 2) ADC_setInterruptSOCTrigger(base, socNumber, trigger); ``` Set EOC source for an ADC interrupt: ```c // Function inputs: // base is the ADC base address: ADCx_BASE (x = A etc.) // adcIntNum value is: ADC_INT_NUMBERx (x = 1 etc.) // socNumber is: ADC_SOC_NUMBERx (x = 0 to 15) ADC_setInterruptSource(base, adcIntNum, socNumber); ADC_[enable|disable]Interrupt(base, adcIntNum); ``` Force an ADC conversion (software trigger): ```c // Function inputs: // base is the ADC base address: ADCx_BASE (x = A etc.) // socNumber is: ADC_SOC_NUMBERx (x = 0 to 15) ADC_forceSOC(base, socNumber); ``` Configure ADC EOC interrupt pulse generation: ```c // Function inputs: // base is the ADC base address: ADCx_BASE (x = A etc.) // pulseMode value is: ADC_PULSE_END_OF_x (x = ACQ_WIN or CONV) ADC_setInterruptPulseMode(base, pulseMode); ``` Read ADC result register: ```c // Function inputs: // resultBase value is: ADCxRESULT_BASE (x = A etc.) // socNumber is: ADC_SOC_NUMBERx (x = 0 to 15) ADC_readResult(resultBase, socNumber); ``` ADC Triggering ------------------------------------------------- As discussed previously, each ADC module has multiple trigger sources that can be used to initiate an ADC conversion. For a complete list of trigger sources please reference the 'ADC Features' section of the TRM. Point about triggering: * There is fine granularity and coupling for when the ADC conversion can be sampled vs the control loop (especially with an EPWM-trigger + EPWM-actuation scheme), which is convenient for avoiding noise and optimizing response times (phase margin) * Parallel ADCs allow for true simultaneous sampling, which is good for correlated signals (like Voltage + Current for a power supply) * The sampling rate is software configurable, so the ADC sampling can be adjusted on-the-fly to match the input signal ** Triggering Examples** The top example in <a href="#ADC Triggering"><span id="ADC TriggeringID"></span></a> shows channels A1, A3, and A5 being converted with a trigger from EPWM1. After A5 is converted, ADCINT1 is generated. The bottom example shows channels A2, A4, and A6 being converted initially by a software trigger. Then, after A6 is converted, ADCINT2 is generated and also fed back as a trigger to start the process again. <figure class='figure' id ="ADC Triggering"> <img src="adc_resources/adc_triggers.png"/> <figcaption class='figcaption'>ADC Triggering</figcaption> </figure> <br> The ADC ping-pong triggering example in <a href="#ADC Ping-Pong Triggering"><span id="ADC Ping-Pong TriggeringID"></span></a> shows channels B0 through B5 being converted, triggered initially by software. After channel B2 is converted, ADCINT1 is generated, which also triggers channel B3. After channel B5 is converted, ADCINT2 is generated and is also fed back to start the process again from the beginning. Additionally, ADCINT1 and ADCINT2 are being used to manage the ping-pong interrupts for the interrupt service routines. <figure class='figure' id ="ADC Ping-Pong Triggering"> <img src="adc_resources/adc_ping_pong_triggering.png"/> <figcaption class='figcaption'>ADC Ping-Pong Triggering</figcaption> </figure> <br> ADC Conversion Priority ------------------------------------------------- When multiple triggers are received at the same time, the ADC conversion priority determines the order in which they are converted. Three different priority modes are supported. **Round Robin Priority (default)** * No SOC has an inherent higher priority than another * Priority depends on the round robin pointer which operates in a circular buffer **High Priority** * High priority SOC will interrupt the round robin wheel after current conversion completes and insert itself as the next conversion * One or more than one SOC can be assigned as 'high priority' * High priority mode is assigned first to the lower number start-of-conversion and then in increasing numerical order. * If two high priority start-of-conversion triggers occur at the same time, the lower number will take precedence. * After its conversion completes, the round robin wheel will continue where it was interrupted **Round Robin Burst Mode** * Allows a single trigger to convert one or more SOCs in the round robin wheel * Uses BURSTTRIG instead of TRIGSEL for all round robin SOCs (not high priority) to select the burst size and trigger source <figure class='figure' id ="ADC Conversion Priority Functional Diagram"> <img src="adc_resources/adc_conversion_priority.png"/> <figcaption class='figcaption'>ADC Conversion Priority Functional Diagram</figcaption> </figure> <br> In <a href="#ADC Conversion Priority Functional Diagram"><span id="ADC Conversion Priority Functional DiagramID"></span></a>, the Start-of-Conversion Priority Control Register contains two bit fields. The Start-of-Conversion Priority bit fields determine the cutoff point between high priority and round robin mode, whereas the Round-Robin Pointer bit fields contains the last converted round robin start-of-conversion which determines the order of conversions. <figure class='figure' id ="ADC Round Robin Priority Example"> <img src="adc_resources/adc_round_robin_priority_example.png"/> <figcaption class='figcaption'>ADC Round Robin Priority Example</figcaption> </figure> <br> <figure class='figure' id ="ADC High Priority Example"> <img src="adc_resources/adc_high_priority_example.png"/> <figcaption class='figcaption'>ADC High Priority Example</figcaption> </figure> <br> <figure class='figure' id ="ADC Round Robin Burst Mode Diagram"> <img src="adc_resources/adc_round_robin_burst_mode.png"/> <figcaption class='figcaption'>ADC Round Robin Burst Mode Diagram</figcaption> </figure> <br> The Round-Robin Burst mode utilizes an ADC Burst Control Register to enable the burst mode, determine the burst size, and select the burst trigger source. Post Processing Block ------------------------------------------------- To further enhance the capabilities of the ADC, each ADC module incorporates four post processing blocks (PPB), and each PPB can be linked to any of the ADC result registers (ADCRESULTx). The PPBs can be used for offset correction, calculating an error from a set-point, detecting a limit and zero-crossing, and capturing a trigger-to-sample delay. 1. **Offset Correction** * Simultaneously remove an offset associated with an ADCIN channel possibly caused by external sensors and signal sources (zero-overhead; saving cycles) * **Error from Set-point Calculation** * Subtract out a reference value which can be used to automatically calculate an error from a set-point or expected value (reduces the sample to output latency and software overhead) * **Limit and Zero-Crossing Detection** * Automatically perform a check against a high/low limit or zero- crossing and can generate a trip to the ePWM and/or an interrupt (decreases the sample to ePWM latency and reduces software overhead; trip the ePWM based on an out of range ADC conversion without CPU intervention) which is useful for safety cautious applications. * **Trigger-to-Sample Delay Capture** * Capable of recording the delay between when the SOC is triggered and when it begins to be sampled (allows software techniques to reduce the delay error) **Post Processing Block Interrupt Event** * Each ADC module contains four Post Processing Blocks * Each Post Processing Block can be associated with any of the 16 ADCRESULTx registers <figure class='figure' id ="ADC Post Processing Interrupt Event"> <img src="adc_resources/adc_post_processing_interrupt.png"/> <figcaption class='figcaption'>ADC Post Processing Interrupt Event</figcaption> </figure> <br> ADC Clocking Flow ------------------------------------------------- In order to configure the clock for the ADC module, first the SYSCLK needs to be generated. This clock is the CPU frequency and is configured through the `SysCtl_setClock()` function. This function lets you choose the input clock source and configure the PLL settings. Once the SYSCLK is setup, the clock to each ADC module used must be enabled using the `SysCtl_enablePeripheral()` function. Upon enabling the clock, a prescalar value can be selected through the `ADC_setPrescaler()` function that will scale down the SYSCLK frequency to go to the ADC core. Make sure to check the datasheet for the MAX ADC frequency, this is lower than SYSCLK. **Example of configuring the clock settings for a device** [[b! Note: The values in this example may not apply to all devices but the flow will be the same]] <figure class='figure' id ="ADC Clocking Flow"> <img src="adc_resources/adc_clocking_flow.png"/> <figcaption class='figcaption'>ADC Clocking Flow</figcaption> </figure> <br> ADC Timing ------------------------------------------------- Below is an example of how to calculate the maximum sampling rate. For this example, `SYSCLK` is 100MHz (10ns period) and `ADCCLK` is 50MHz (20ns period) Sample + Hold (sampling window) time: 8 * 10 ns = 80 ns Conversion time: 21 * 10 ns = 210 ns Sampling Rate: 80 ns + 210 ns = 290 ns -> **3.45 MSPS (Mega samples per second)** <figure class='figure' id ="ADC Timing Example"> <img src="adc_resources/adc_timings.png"/> <figcaption class='figcaption'>ADC Timing Example</figcaption> </figure> <br> ADC Conversion Result Registers ------------------------------------------------- The ADC conversion results are stored within the ADCRESULTx register. The `ADC_readResult()` function can be utilized to read the result given an ADC module and SOC number. • Selectable internal reference of 2.5 V or 3.3 V (Not available on multi-core devices) • Ratiometric external reference set by VREFHI/VREFLO <figure class='figure' id ="ADC Conversion Register"> <img src="adc_resources/adc_conversion_register.png"/> <figcaption class='figcaption'>ADC Conversion Register</figcaption> </figure> <br> [[b Note: The table in <a href="#ADC Conversion Register"><span id="ADC Conversion RegisterID"></span></a> is based on internal reference of 3.3 V; for external reference VREFHI is VDDA maximum, however VREFHI is typically selected as 2.5 V or 3.0 V]] ```c // Function Inputs: // resultBase value is: ADCxRESULT_BASE (x = A etc.) // socNumber is: ADC_SOC_NUMBERx (x = 0 to 15) ADC_readResult(resultBase, socNumber); ``` Signed Input Voltages ------------------------------------------------- How can we handle signed input voltages? Lets take a look at an example: -1.65V <= Vin <= +1.65 V <figure class='figure' id ="ADC Signed Input Voltages Example"> <img src="adc_resources/adc_signed_input_voltages.png"/> <figcaption class='figcaption'>ADC Signed Input Voltages Example</figcaption> </figure> <br> 1) Add 1.65 volts to the analog input 2) Subract 1.65 from the digital result ```c #define offset 0x07FF //2047 is the digital value for 1.65V void main (void) { uint16_t value; //signed value = ADC_readResult(resultBase, socNumber) - offset; } ``` ADC Calibration and Reference ------------------------------------------------- **Built-In Calibration** TI reserved OTP contains device specific calibration data for the ADC, internal oscillators and buffered DAC * The Boot ROM contains a Device_cal() routine that copies the calibration data to their respective registers * Device_cal() must be run to meet the specifications in the datasheet * The Bootloader automatically calls Device_cal() such that no action is normally required by the user * If the Bootloader is bypassed (e.g. during development) Device_cal () should be called by the application: The `Device_cal()` function is called by the `SysCtl_deviceCal()` function within the sysctl.h file which is called by the `Device_init()` function. The Device_init() function is found within device.c. This is what C2000Ware examples utilize to initialize the device. **Manual ADC Calibration** If the offset and gain errors in the datasheet are unacceptable for your application, or you want to also compensate for board level errors (e.g. sensor or amplifier offset), you can manually calibrate * Offset error (12-bit mode) * Compensated in analog with the ADCOFFTRIM register * No reduction in full-scale range * Configure input to VREFLO, set ADCOFFTRIM to maximum offset error, and take a reading * Re-adjust ADCOFFTRIM to make result zero * Gain error * Compensated in software * Some loss in full-scale range * Requires use of a second ADC input pin and an upper-range reference voltage on that pin <figure class='figure' id ="ADC Manual Calibration"> <img src="adc_resources/adc_manual_calibration.png"/> <figcaption class='figcaption'>ADC Manual Calibration</figcaption> </figure> <br> **Analog Subsystem External Reference** For an example of how to setup an external reference refer to the 'Designing an External Reference Circuit' within the device's Technical Reference Manual (TRM). <a href="#ADC Subsystem External Reference"><span id="ADC Subsystem External ReferenceID"></span></a> shows an example of the reference generation scheme for the F28004x device: <figure class='figure' id ="ADC Subsystem External Reference"> <img src="adc_resources/adc_external_reference.png"/> <figcaption class='figcaption'>ADC Subsystem External Reference</figcaption> </figure> <br> ADC Related Collateral ==================================== **Foundational** - <a href="https://ti.com/lit/SPRACT6" target="_blank">ADC Input Circuit Evaluation for C2000 MCUs (TINA-TI) Application Report</a> - <a href="https://www.ti.com/tool/PSPICE-FOR-TI" target="_blank">PSpice for TI design and simulation tool</a> - <a href="https://www.ti.com/lit/eb/slyy211/slyy211.pdf" target="_blank">Real-Time Control Reference Guide</a> - <a href="https://training.ti.com/ti-precision-labs-adcs" target="_blank">TI Precision Labs - ADCs</a> - <a href="https://www.ti.com/tool/TINA-TI" target="_blank">TI Precision Labs - ADCs</a> - <a href="https://training.ti.com/node/1139107" target="_blank">TI Precision Labs: Driving the reference input on a SAR ADC</a> - <a href="https://training.ti.com/introduction-analog-digital-converters-adcs" target="_blank">TI Precision Labs: Introduction to analog-to-digital converters (ADCs)</a> - <a href="https://training.ti.com/node/1139106" target="_blank">TI Precision Labs: SAR ADC input driver design</a> - <a href="https://e2e.ti.com/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/967811/tms320f28388d-connecting-both-vdda-and-vrefhi-to-3-3v/3575387?tisearch=e2e-sitesearch&amp;keymatch=ADC%252520VREFHI%252520driver#3575387" target="_blank">TI e2e: Connecting VDDA to VREFHI </a> - <a href="https://e2e.ti.com/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/1065493/tms320f280049-q1-opamp-powered-by-5v-to-buffer-gpio" target="_blank">TI e2e: Topologies for ADC Input Protection</a> - <a href="https://e2e.ti.com/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/1024667/tms320f280049c-why-does-the-adc-input-voltage-drop-with-sampling/3787995?tisearch=e2e-sitesearch&amp;keymatch=ADC%25252525252520voltage%25252525252520divider#3787995" target="_blank">TI e2e: Why does the ADC Input Voltage drop with sampling?</a> - <a href="https://www.ti.com/lit/SLAA013" target="_blank">Understanding Data Converters Application Report</a> **Getting Started** - <a href="https://www.mathworks.com/help/supportpkg/texasinstrumentsc2000/ug/adc-pwm-synchronization-via-adc-interrupt.html" target="_blank">ADC-PWM Synchronization Using ADC Interrupt</a> - <a href="https://training.ti.com/analog-digital-converter-adc-training-c2000-mcus" target="_blank">Analog-to-Digital Converter (ADC) Training for C2000 MCUs</a> - Only applicable to: F280013x, F28002x, F28003x, F28004x, F2837x, F2838x - <a href="https://www.ti.com/lit/spracz9" target="_blank">Hardware Design Guide for F2800x C2000 Real-Time MCU Series</a> **Expert** - <a href="https://www.ti.com/tool/ANALOG-ENGINEER-CALC" target="_blank">Analog Engineer's Calculator</a> - <a href="https://www.ti.com/seclit/eb/slyw038c/slyw038c.pdf" target="_blank">Analog Engineer's Pocket Reference</a> - <a href="https://ti.com/lit/SPRACZ0" target="_blank">Charge-Sharing Driving Circuits for C2000 ADCs (using PSPICE-FOR-TI) Application Report</a> - Only applicable to: F280013x, F28002x, F28003x, F28004x, F2807x, F2837xD, F2837xS, F2838x - <a href="https://ti.com/lit/SPRACV0" target="_blank">Charge-Sharing Driving Circuits for C2000 ADCs (using TINA-TI) Application Report</a> - Only applicable to: F280013x, F28002x, F28003x, F28004x, F2807x, F2837xD, F2837xS, F2838x - <a href="https://e2e.ti.com/blogs_/b/analogwire/archive/2017/08/17/debugging-an-integrated-adc-in-a-microcontroller-using-an-oscilloscope" target="_blank">Debugging an integrated ADC in a microcontroller using an oscilloscope</a> - <a href="https://ti.com/lit/SPRACW9" target="_blank">Methods for Mitigating ADC Memory Cross-Talk Application Report</a> - Only applicable to: F280013x, F28002x, F28003x, F28004x, F2807x, F2837xD, F2837xS, F2838x - <a href="https://training.ti.com/node/1139105" target="_blank">TI Precision Labs: ADC AC specifications</a> - <a href="https://training.ti.com/node/1139104" target="_blank">TI Precision Labs: ADC Error sources</a> - <a href="https://training.ti.com/adc-noise" target="_blank">TI Precision Labs: ADC Noise</a> - <a href="https://training.ti.com/node/1139103" target="_blank">TI Precision Labs: Analog-to-digital converter (ADC) drive topologies</a> - <a href="https://training.ti.com/node/1139109" target="_blank">TI Precision Labs: Electrical overstress on data converters</a> - <a href="https://training.ti.com/node/1139110" target="_blank">TI Precision Labs: High-speed ADC fundamentals</a> - <a href="https://training.ti.com/sar-delta-sigma-understanding-difference" target="_blank">TI Precision Labs: SAR &amp; Delta-Sigma: Understanding the Difference</a> - <a href="https://e2e.ti.com/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/902366/tms320f28377d-ep-adc-bandwidth-clarification/3335570?tisearch=e2e-sitesearch&amp;keymatch=aperture%20jitter#3335570" target="_blank">TI e2e: ADC Bandwidth Clarification</a> - <a href="https://e2e.ti.com/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/587441/faq-tms320f28035-adc-calibration-and-total-unadjusted-error" target="_blank">TI e2e: ADC Calibration and Total Unadjusted Error</a> - <a href="https://e2e.ti.com/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/477506/faq-adc-reference-in-tms320f28377dzwt" target="_blank">TI e2e: ADC Reference Driver Options</a> - <a href="https://e2e.ti.com/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/815285/tms320f280049-about-the-actual-adc-resolution/3017272#3017272" target="_blank">TI e2e: ADC Resolution with Oversampling</a> - <a href="https://e2e.ti.com/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/757435/tms320f28379d-adc-configuration-for-interleaved-mode/2799102?tisearch=e2e-sitesearch&amp;keymatch=aperture%2525252520jitter#2799102" target="_blank">TI e2e: ADC configuration for interleaved mode</a> - <a href="https://e2e.ti.com/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/930245/tms320f280049-simultaneous-sampling-with-single-adc/3437033?tisearch=e2e-sitesearch&amp;keymatch=burst%2520mode#3437033" target="_blank">TI e2e: Simultaneous Sampling with Single ADC</a> ---------------------------------------------------------------- [[d! Feedback Please provide any feedback you may have about the content within C2000 Academy to: <c2000_academy_feedback@list.ti.com> ]] <div align="center" style="margin-top: 4em; font-size: smaller;"> <a rel="license" href="http://creativecommons.org/licenses/by-nc-nd/4.0/"><img alt="Creative Commons License" style="border-width:0" src="../../web_support/cc_license_icon.png" /></a><br />This work is licensed under a <a rel="license" href="http://creativecommons.org/licenses/by-nc-nd/4.0/">Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International License</a>.</div>