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.

CC2540 sequence reading of ADC.

Other Parts Discussed in Thread: CC2540

Hi guys,

I am attempting to do a single ended sequence reading of the  first 2 ADC  channels without DMA. I have my ADCCON1 [5:4] set to 11.   I have an event set to 10sec where i read the latest ADC value from the channels. I get the correct reading for the second channel but not the first channel. i keep on getting a constant value  for the first channel even with changing input. Can someone help me out.  below is my code.

uint8 i = 0;
uint16 Tempsensor;
uint16 sensorRH;
uint16 TrueRH;
uint16 Tempsensorsend;
uint8 Vsupply = 33;


static uint16 adc_data[3];
APCFG = 0x03; // set first four channels as analog input

/*
* ADC configuration :
* - Continous mode
* - Single-ended sequence conversion
* - Reference Voltage is the internal reference voltage
* - 12 bit resolution (512 dec rate)
*/
ADCCON2 = 0x33; // internal reference,first four channels and 12 bits(512 ENOB)
// Set [ADCCON1.STSEL] to continues conversion.

ADCCON1 = 0x73;


/* ADC conversion :
* The ADC will run in continous mode until disabled.
// Stop continuous mode.
*/
//ADCCON1 |= ADCCON1_ST;

for ( i=0; i<3; i++)
{
adc_data[i]= (int16) (ADCL);
adc_data[i] |= (int16) (ADCH << 8);

// normalize the result
if(adc_data[i] < 0) adc_data[i] = 0;

// The results are in two's complement form and the value is not converted to signed.
adc_data[i] = (adc_data[i] >> 4) & 0x0FFF;

//processing sensor data from both sensors

sensorRH = ((CONSTANT * adc_data[0])/(0.00636 * Vsupply/10)) - 23.8208 ; // commerial humidity sensor in percentage
TrueRH = (sensorRH)/(1.0546 - (0.00216 * Tempsensor));
Tempsensor = (((CONSTANT * adc_data[1]) - 500)/10); // commercial temperature sensor in degrees celcius
Tempsensorsend = Tempsensor * 100; // commercial temperature sensor in degrees celcius

}
AT_DBG("ADC_0(hum) = %d",adc_data[0]);
AT_DBG("ADC_1(temp) = %d",adc_data[1]);
AT_DBG("Tempsensor = %d", Tempsensor);
AT_DBG("sensorRH = %d", sensorRH);
AT_DBG("TrueRH = %d", TrueRH);


if (channel == 1)
{
return (Tempsensor);
}
else if (channel ==2)
{
return (sensorRH);
}
return 0;
}

if (events & ADC_READ_EVT)
{

get1_adc_value(channel);
}

Thank You.

  • Hi,

    You can directly use ADC functions provided by TI to achieve this functionality.

    Lets say if you want to read from channel 0 and 1 my code would be as follow:

    // Set ADC reference voltage = 1.24 V
    HalAdcSetReference( HAL_ADC_REF_125V);
    
    //Read data from ADC channel 0 using 14-bit resolution 
    adc = HalAdcRead(0, HAL_ADC_RESOLUTION_14 );
    
    //Read data from ADC channel 1 using 14-bit resolution 
    adc = HalAdcRead(1, HAL_ADC_RESOLUTION_14 );

    Try code above and check. It should work.

    Note: I am not sure but may be you need to change ADCCONF to APCFG in hal_adc.c file in HalAdcRead API where they are setting pin as analog input pin.

  • Hi Maulik,

    I know about the code above. It did not work for me.  I am using the blueradios module of the CC2540. And also I am trying to do sequential reading of several channels not  a single channel

    Thank you

  • Hi, 

    Ok. Did you try to change which I suggested ? Replacing ADCCONF with APCONF? 

    Another thing from your code regarding sequence conversion. 

    1. You are making bit ADCCON1.st =1  and in for loop you are directly reading results. You should actually check that if ADCCON1.EOC bit is 1 or not, if bit is 1 then and then read data. Once you read data EOC bit will be cleared automatically.

    2. When you read result, read ADCCON2.SCH , which indicates on which channel conversion is going on and result you read will be of previous channel. If ADCCON2.SCH = 2 then results are if channel 1. For last channel value of SCH = last channel + 1. 

    Try to implement this in your code. this should also work. 

  • Hi Maulik,

    1. I am using the cc2540 so i think the ADCCON is good. 
    2.  With the ADCCON.st = 1 you something like below?

      for ( i=0; i<3; i++)
      {
      if (ADCCON1 & 0x80 == 0x80 )
      {
      adc_data[i]= (int16) (ADCL);
      adc_data[i] |= (int16) (ADCH << 8);

    3. You mean i should check  if  ADCCON2.SCH == 0x31 and then read channel 1?. Can you explain a little bit what you mean ??
  • Hi Joseph, 

    Answers:

    1. Ok. No problem.

    2. Yes, that's correct. 

    3.  From CC254x user guide for ADC results:

    "When the ADCCON2.SCH bits are read, they indicate the channel on which conversion is ongoing. The results in ADCL and ADCH normally apply to the previous conversion. If the conversion sequence has ended, ADCCON2.SCH has a value of one more than the last channel number, but if the channel number last written to ADCCON2.SCH was 12 or more, the same value is read back."

    So for your question, you should modify your code from question 2 as follow:

    for ( i=0; i<3; i++)
    {
    if (ADCCON1 & 0x80 == 0x80 )
    {

    uint8 channel = ADCCON2.SCH; 

    if(channel < 3)    // 3 is last channel or simply check array boundry condition.

    adc_data[channel - 1]= (int16) (ADCL);
    adc_data[channel - 1] |= (int16) (ADCH << 8);

    After this for loop you should have result of respective channel in array.

    I have not tried above code practically but please let me know your findings. :)

    Maulik.

  • Hi Maulik,

    Thanks for the answer i will try  and let you know my findings.

    I have a another question. 

     I  also tried the continues conversion by setting  ADCCON1.STSEL [5:4]  to 01. The readings kept on been swapped between the channels back and forth.  Do think the value of  ADCCON2.SCH will help in getting the correct reading from the appropriate channel??

     

    Thank you. 

    Joseph

  • Hi Joseph, 

    Yes, You can implement as per code that I had suggested.

    The readings keep swapping because once you read ADCH and ADCL , adc will start sampling next channel. so readings will keep swapping. But by checking SCH bit, we are making sure that on which channel conversion is going on. So yes reading SCH will definitely help. 

    Maulik.

  • The Problem with your code is APCFG = 0x03 //it will make first two channels as analog input not first four.However, replacing ADCCONF to APCFG in hal_adc.c will make your life lot easier by using simple HAL APIs.