This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

CCS/CC2640: Implementing RTOS ADC driver for CC2640

Part Number: CC2640

Tool/software: Code Composer Studio

Hi,

I'm trying to use the TI-RTOS ADC driver to read battery voltage. Analog input DIO07 of the CC2640 is connected to a voltage divider circuit directly from the battery.

I've implemented the ADC definition in the board definition files:

Board Specific header file CC2640_5XD.h:

/*!
 *  @def    CC2650DK_7ID_ADCName
 *  @brief  Enum of ADCs
 */
typedef enum CC2650DK_5XD_ADCName {
    CC2650DK_5XD_ADCVDDS = 0,
    CC2650DK_5XD_ADCCOUNT
} CC2650DK_5XD_ADCName;

Board source file CC2640_5XD.c:

/*
*  ========================== ADC begin =========================================
*/
/* Place into subsections to allow the TI linker to remove items properly */
#if defined(__TI_COMPILER_VERSION__)
#pragma DATA_SECTION(ADC_config, ".const:ADC_config")
#pragma DATA_SECTION(adcCC26xxHWAttrs, ".const:adcCC26xxHWAttrs")
#endif

/* Include drivers */
#include <ti/drivers/ADC.h>
#include <ti/drivers/adc/ADCCC26XX.h>


/* ADC objects */
ADCCC26XX_Object adcCC26xxObjects[CC2650DK_5XD_ADCCOUNT];

const ADCCC26XX_HWAttrs adcCC26xxHWAttrs[CC2650DK_5XD_ADCCOUNT] = {
   {
       .adcDIO = IOID_7,
       .adcCompBInput = ADC_COMPB_IN_VDDS,
       .refSource = ADCCC26XX_FIXED_REFERENCE,
       .samplingDuration = ADCCC26XX_SAMPLING_DURATION_2P7_US,
       .inputScalingEnabled = true,
       .triggerSource = ADCCC26XX_TRIGGER_MANUAL
   }
};

const ADC_Config ADC_config[] = {
   {&ADCCC26XX_fxnTable, &adcCC26xxObjects[0], &adcCC26xxHWAttrs[0]},
   {NULL, NULL, NULL},
};

/*
*  ========================== ADC end =========================================
*/

 

Board.h:

#define     Board_ADC0              CC2650DK_5XD_ADCVDDS
#define     Board_initADC()         ADC_init()

The main application task initialized the ADC driver by calling Board_initADC().

 The ADC CC26XX header file is included in an application as follows:

#include <ti/drivers/ADC.h>
#include <ti/drivers/adc/ADCCC26XX.h>

The following function is called to read the current voltage level on DIO07 analog input:

static void multi_role_readBattVoltage()
{
    ADC_Handle   adc;
    ADC_Params   params;
    int_fast16_t res;

    uint16_t adcValue0;

    ADC_Params_init(&params);

    adc = ADC_open(Board_ADC0, &params);

    if (adc == NULL) {
       return;
    }

    /* Blocking mode conversion */
    res = ADC_convert(adc, &adcValue0);

    if (res == ADC_STATUS_SUCCESS) {
        batteryVoltage     = adcValue0;

        //voltage = ADC_convertRawToMicroVolts(ADC0Handle, temp);
        //voltage = (voltage/1000) * ((R1+R2)/R2);
    }

    ADC_close(adc);
}

An ADC value is read successfully but I'm not sure if it actually is the current input voltage level. 

I'm wondering if the ADC driver is implemented correctly for a CC2640 5XD chip and how the voltage level need to be calculated?

It's using the internal fixed voltage reference (4.3V) with input scaling enabled. In this mode, the output is a function of the input voltage multiplied
by the resolution in alternatives divided by the upper voltage range of the ADC. Output = Input (V) * 2^12 / (ADC range (V)).

Do I need to use this calculation or the ADC_convertRawToMicroVolts() function?

Thanks.

Using:

BLE stack v2.2.2
RTOS v2.21.1.08

  • You can call ADC_convertRawToMicroVolts to convert ADC reading to micro voltage.

  • ADC_convert does not compensate for gain and offset errors in the ADC. Look into the driverlib function as YK suggested, I would also recommend you to look at http://dev.ti.com/tirex/explore/node?a=VLyFKFf__3.6.2&node=AEci1l.IYgauB29UR6LoxQ__krol.2c__LATEST&r=VLyFKFf__LATEST since the exampe in TI-RTOS 2.21 is not up to date.

    I would also look into using CC2640R2F if possible since the software offering for this chip is much better. 

  • OK, yes we're using both. Still having old legacy hardware with CC2640 and new hardware with the CC2652.

    That's why I woud like to know how to implement it on the CC2640? I've already taken a look at the examples of the launchpads (also earlier ones) but these are using other configurations, it seems not exactly apply on the cc2640.

    Thanks.

  • ADC_convertRawToMicroVolts is mapped to the following function:

    /*
     *  ======== ADCCC26XX_convertToMicroVolts ========
     */
    uint32_t ADCCC26XX_convertToMicroVolts(ADC_Handle handle, uint16_t adcValue){
        ADCCC26XX_HWAttrs     const *hwAttrs;
        uint32_t                    adjustedValue;
    
        DebugP_assert(handle);
    
        /* Get the pointer to the hwAttrs */
        hwAttrs = handle->hwAttrs;
    
        /* Only apply trim if specified*/
        if (hwAttrs->returnAdjustedVal) {
            adjustedValue = adcValue;
        }
        else {
            uint32_t gain = AUXADCGetAdjustmentGain(hwAttrs->refSource);
            uint32_t offset = AUXADCGetAdjustmentOffset(hwAttrs->refSource);
            adjustedValue = AUXADCAdjustValueForGainAndOffset(adcValue, gain, offset);
        }
    
        return AUXADCValueToMicrovolts((hwAttrs->inputScalingEnabled ? AUXADC_FIXED_REF_VOLTAGE_NORMAL : AUXADC_FIXED_REF_VOLTAGE_UNSCALED), adjustedValue);
    }

    To get the correct results from the ADC you need to run this function since this adjust for offset and gain errors. The driverlib functions used should be available in your software version too.