Tuesday, December 25, 2018

How to do ADC reading on Silicon Labs EFR32

The following steps show you how to do ADC reading on Silicon Labs EFR32. In this example, I will use BRD4151A radio board with mainboard BRD4001A to do ADC reading from PC9 pin.

1.Use Simplicity Studio to new a Z3Light example and open brd4151a_efr32mg1p232f256gm48.heconf to adjust POS_BX to use PC9 pin.




2. Add the following codes in Z3LightSoc_callbacks.c so we can press PB0/PB1 to do ADC reading from PC9 pin. Here we set ADC reference to internal 2.5V and 12-bit resolution so the max measurement value would be 2.5V which max reading from ADC is 4095.

#include
#include "em_device.h"
#include "em_chip.h"
#include "em_cmu.h"
#include "em_adc.h"

#define adcFreq   16000000

volatile uint32_t sample;
volatile uint32_t millivolts;
 

...

/**************************************************************************//**
 * @brief  Initialize ADC function
 *****************************************************************************/
void initADC (void)
{
  // Enable ADC0 clock
  CMU_ClockEnable(cmuClock_ADC0, true);

  // Declare init structs
  ADC_Init_TypeDef init = ADC_INIT_DEFAULT;
  ADC_InitSingle_TypeDef initSingle = ADC_INITSINGLE_DEFAULT;

  // Modify init structs and initialize
  init.prescale = ADC_PrescaleCalc(adcFreq, 0); // Init to max ADC clock for Series 1

  initSingle.diff       = false;        // single ended
  initSingle.reference  = adcRef2V5;    // internal 2.5V reference
  initSingle.resolution = adcRes12Bit;  // 12-bit resolution
  initSingle.acqTime    = adcAcqTime4;  // set acquisition time to meet minimum requirement

  // Select ADC input.
  initSingle.posSel = adcPosSelAPORT2XCH9;

  ADC_Init(ADC0, &init);
  ADC_InitSingle(ADC0, &initSingle);
}

void emberAfHalButtonIsrCallback(uint8_t button, uint8_t state)
{
  initADC();

  // Start ADC conversion
  ADC_Start(ADC0, adcStartSingle);

  // Wait for conversion to be complete
  while(!(ADC0->STATUS & _ADC_STATUS_SINGLEDV_MASK));

  // Get ADC result
  sample = ADC_DataSingleGet(ADC0);

  // Calculate input voltage in mV
  millivolts = (sample * 2500) / 4096;
}




p.s. Here, we set initSingle.posSel = adcPosSelAPORT2XCH9 since we set POS_BX to use PC9 pin in HW configurator. You can refer to Table 6.9. ADC0 Bus and Pin Mapping in efr32mg1 datasheet.


3. Build and download the code into BRD4151+ BRD4001A.

4. According to Figure 2.1. BRD4151A Radio Board Connector Pin Mapping, PC9 would be mapped to pin 10 on BRD4001A EXP header and we can apply different voltage between 0V-2.5V to test the ADC reading.



2 comments:

  1. Just correcting if I am not wrong, but at step 4 the PC9 is mapped to p7 right? Thank you for the tutorial.

    ReplyDelete
  2. Hi. First, congratulations on the publication.
    Second, if I want to use more than one pin in ADC, how can I do this? How can I read two pins with ADC0?

    ReplyDelete