Other Parts Discussed in Thread: SYSCONFIG,
HI
I am currently using a 1.5V battery to test the ADC error of the F28379D EVM board, but the current test results are shown in the figure below. Both the maximum and minimum values of the ADC exceed the ADC error 7 LSB written on the datasheet. How can I set it to achieve the ADC error 7 LSB?
The following program I wrote first discards the first 9000 data of the ADC value, and calculates the maximum and minimum values and the average ADC value of the 3000 ADC values after the ADC module is stable.
//#############################################################################
//
// FILE: adc_ex2_soc_epwm.c
//
// TITLE: ADC ePWM Triggering
//
//! \addtogroup driver_example_list
//! <h1>ADC ePWM Triggering</h1>
//!
//! This example sets up ePWM1 to periodically trigger a conversion on ADCA.
//!
//! \b External \b Connections \n
//! - A0 should be connected to a signal to convert
//!
//! \b Watch \b Variables \n
//! - \b adcAResults - A sequence of analog-to-digital conversion samples from
//! pin A0. The time between samples is determined based on the period
//! of the ePWM timer.
//!
//
//#############################################################################
//
// $Release Date: $
// $Copyright:
// Copyright (C) 2013-2022 Texas Instruments Incorporated - http://www.ti.com/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
// Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//
// Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the
// distribution.
//
// Neither the name of Texas Instruments Incorporated nor the names of
// its contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// $
//#############################################################################
//
//
// Included Files
//
#include "driverlib.h"
#include "device.h"
//
// Defines
//
#define RESULTS_BUFFER_SIZE 3000
#define EX_ADC_RESOLUTION 12
// 12 for 12-bit conversion resolution, which supports (ADC_MODE_SINGLE_ENDED)
// Sample on single pin (VREFLO is the low reference)
// Or 16 for 16-bit conversion resolution, which supports (ADC_MODE_DIFFERENTIAL)
// Sample on pair of pins (difference between pins is converted, subject to
// common mode voltage requirements; see the device data manual)
//
// Globals
//
volatile uint16_t adcAResults[RESULTS_BUFFER_SIZE]; // Buffer for results
uint16_t index; // Index into result buffer
uint16_t i;
volatile uint32_t sum_of_adc_data;
volatile uint32_t avg_adc_value, diff_value;
volatile uint16_t bufferFull; // Flag to indicate buffer is full
volatile uint32_t Max_adc_value = 0x00000000;
volatile uint32_t Min_adc_value = 0xFFFFFFFF;
//
// Function Prototypes
//
void initADC(void);
void initEPWM(void);
void initADCSOC(void);
__interrupt void adcA1ISR(void);
//
// Main
//
void main(void)
{
//
// Initialize device clock and peripherals
//
Device_init();
//
// Disable pin locks and enable internal pullups.
//
Device_initGPIO();
//
// Initialize PIE and clear PIE registers. Disables CPU interrupts.
//
Interrupt_initModule();
//
// Initialize the PIE vector table with pointers to the shell Interrupt
// Service Routines (ISR).
//
Interrupt_initVectorTable();
//
// Interrupts that are used in this example are re-mapped to ISR functions
// found within this file.
//
Interrupt_register(INT_ADCA1, &adcA1ISR);
//
// Set up the ADC and the ePWM and initialize the SOC
//
initADC();
initEPWM();
initADCSOC();
//
// Initialize results buffer
//
for(index = 0; index < RESULTS_BUFFER_SIZE; index++)
{
adcAResults[index] = 0;
}
index = 0;
bufferFull = 0;
//
// Enable ADC interrupt
//
Interrupt_enable(INT_ADCA1);
//
// Enable Global Interrupt (INTM) and realtime interrupt (DBGM)
//
EINT;
ERTM;
//
// Loop indefinitely
//
while(1)
{
//
// Start ePWM1, enabling SOCA and putting the counter in up-count mode
//
EPWM_enableADCTrigger(EPWM1_BASE, EPWM_SOC_A);
EPWM_setTimeBaseCounterMode(EPWM1_BASE, EPWM_COUNTER_MODE_UP);
//
// Wait while ePWM1 causes ADC conversions which then cause interrupts.
// When the results buffer is filled, the bufferFull flag will be set.
//
if(bufferFull == 3){
EPWM_disableADCTrigger(EPWM1_BASE, EPWM_SOC_A);
EPWM_setTimeBaseCounterMode(EPWM1_BASE, EPWM_COUNTER_MODE_STOP_FREEZE);
for(i = 0; i < RESULTS_BUFFER_SIZE; i++){
if(adcAResults[i] > Max_adc_value){
Max_adc_value = adcAResults[i];
}
if(adcAResults[i] < Min_adc_value){
Min_adc_value = adcAResults[i];
}
sum_of_adc_data += adcAResults[i];
}
avg_adc_value = sum_of_adc_data / RESULTS_BUFFER_SIZE;
diff_value = 2121 - avg_adc_value;
ESTOP0;
}
// while(bufferFull == 0)
// {
// }
// bufferFull = 0; // Clear the buffer full flag
//
// //
// // Stop ePWM1, disabling SOCA and freezing the counter
// //
// EPWM_disableADCTrigger(EPWM1_BASE, EPWM_SOC_A);
// EPWM_setTimeBaseCounterMode(EPWM1_BASE, EPWM_COUNTER_MODE_STOP_FREEZE);
//
// Software breakpoint. At this point, conversion results are stored in
// adcAResults.
//
// Hit run again to get updated conversions.
//
//ESTOP0;
}
}
//
// Function to configure and power up ADCA.
//
void initADC(void)
{
//
// Set ADCDLK divider to /4
//
ADC_setPrescaler(ADCA_BASE, ADC_CLK_DIV_2_0);
//
// Set resolution and signal mode (see #defines above) and load
// corresponding trims.
//
#if(EX_ADC_RESOLUTION == 12)
ADC_setMode(ADCA_BASE, ADC_RESOLUTION_12BIT, ADC_MODE_SINGLE_ENDED);
#elif(EX_ADC_RESOLUTION == 16)
ADC_setMode(ADCA_BASE, ADC_RESOLUTION_16BIT, ADC_MODE_DIFFERENTIAL);
#endif
//
// Set pulse positions to late
//
ADC_setInterruptPulseMode(ADCA_BASE, ADC_PULSE_END_OF_CONV);
//
// Power up the ADC and then delay for 1 ms
//
ADC_enableConverter(ADCA_BASE);
DEVICE_DELAY_US(1000);
}
//
// Function to configure ePWM1 to generate the SOC.
//
void initEPWM(void)
{
//
// Disable SOCA
//
EPWM_disableADCTrigger(EPWM1_BASE, EPWM_SOC_A);
//
// Configure the SOC to occur on the first up-count event
//
EPWM_setADCTriggerSource(EPWM1_BASE, EPWM_SOC_A, EPWM_SOC_TBCTR_U_CMPA);
EPWM_setADCTriggerEventPrescale(EPWM1_BASE, EPWM_SOC_A, 1);
//
// Set the compare A value to 1000 and the period to 1999
// Assuming ePWM clock is 100MHz, this would give 50kHz sampling
// 50MHz ePWM clock would give 25kHz sampling, etc.
// The sample rate can also be modulated by changing the ePWM period
// directly (ensure that the compare A value is less than the period).
//
EPWM_setCounterCompareValue(EPWM1_BASE, EPWM_COUNTER_COMPARE_A, 1000);
EPWM_setTimeBasePeriod(EPWM1_BASE, 1999);
//
// Set the local ePWM module clock divider to /1
//
EPWM_setClockPrescaler(EPWM1_BASE,
EPWM_CLOCK_DIVIDER_1,
EPWM_HSCLOCK_DIVIDER_1);
//
// Freeze the counter
//
// EPWM_setTimeBaseCounterMode(EPWM1_BASE, EPWM_COUNTER_MODE_STOP_FREEZE);
}
//
// Function to configure ADCA's SOC0 to be triggered by ePWM1.
//
void initADCSOC(void)
{
//
// Configure SOC0 of ADCA to convert pin A0. The EPWM1SOCA signal will be
// the trigger.
// - For 12-bit resolution, a sampling window of 15 (75 ns at a 200MHz
// SYSCLK rate) will be used. For 16-bit resolution, a sampling window
// of 64 (320 ns at a 200MHz SYSCLK rate) will be used.
// - NOTE: A longer sampling window will be required if the ADC driving
// source is less than ideal (an ideal source would be a high bandwidth
// op-amp with a small series resistance). See TI application report
// SPRACT6 for guidance on ADC driver design.
//
#if(EX_ADC_RESOLUTION == 12)
ADC_setupSOC(ADCA_BASE, ADC_SOC_NUMBER0, ADC_TRIGGER_EPWM1_SOCA,
ADC_CH_ADCIN0, 128);
#elif(EX_ADC_RESOLUTION == 16)
ADC_setupSOC(ADCA_BASE, ADC_SOC_NUMBER0, ADC_TRIGGER_EPWM1_SOCA,
ADC_CH_ADCIN0, 64);
#endif
//
// Set SOC0 to set the interrupt 1 flag. Enable the interrupt and make
// sure its flag is cleared.
//
ADC_setInterruptSource(ADCA_BASE, ADC_INT_NUMBER1, ADC_SOC_NUMBER0);
ADC_enableInterrupt(ADCA_BASE, ADC_INT_NUMBER1);
ADC_clearInterruptStatus(ADCA_BASE, ADC_INT_NUMBER1);
}
//
// ADC A Interrupt 1 ISR
//
__interrupt void adcA1ISR(void)
{
//
// Add the latest result to the buffer
//
adcAResults[index++] = ADC_readResult(ADCARESULT_BASE, ADC_SOC_NUMBER0);
//
// Set the bufferFull flag if the buffer is full
//
if(RESULTS_BUFFER_SIZE <= index)
{
index = 0;
bufferFull += 1;
}
//
// Clear the interrupt flag
//
ADC_clearInterruptStatus(ADCA_BASE, ADC_INT_NUMBER1);
//
// Check if overflow has occurred
//
if(true == ADC_getInterruptOverflowStatus(ADCA_BASE, ADC_INT_NUMBER1))
{
ADC_clearInterruptOverflowStatus(ADCA_BASE, ADC_INT_NUMBER1);
ADC_clearInterruptStatus(ADCA_BASE, ADC_INT_NUMBER1);
}
//
// Acknowledge the interrupt
//
Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP1);
}



