Hi friends!!
After a some period of using the EFM32 boards, I changed my work and moved to another interesting things.
So it’s my last article about the EFM32.
ADC (Analog-to-Digital Converter) converts voltage on the one or more of its input pins and return the corresponding value.
Little explanation:
Lets say, our Vref is 3.3V, and we have 12 bit ADC.
Lets calculate how many values ADC can return: 2 ^ 12 = 4096.
It means, that ADC can return values from 0 to 4095.
Lets calculate what the meaning of the each value: Vref (mV) / 4096 => 3300 / 4096 = 0.806 mV
Each value is corresponding to 0.806 mV.
Here, a real simple code, that you can use if you want to measure something simple.
For this example I’m using for EFM32G890F128 MCU.
File main.c:
#include "autogen_adc0.h"
volatile uint32_t adc_value;
volatile uint8_t adc_measurement_ready=0;
int main(void)
{
/* Initialize chip */
// For quick chip initialization I use for eDesigner from Silicon Labs.
// You can find it in Simplicity Studio (free Silicon Labs Ide)
// Full configuration you'll find below
eADesigner_Init();
while(1) {
ADC_Start(ADC0, adcStartSingle); // Make ADC measure once
while(adc_measurement_ready==0) {__NOP();} // Wait until ADC interrupt
/* !!! here measurement is ready and you can use it !!! */
for(uint32_t i=0; i< 2000000; i++) {__NOP();} // delay
adc_measurement_ready=0; // resets flag
}
return 0;
}
void ADC0_IRQHandler() {
uint32_t flags = ADC_IntGet(ADC0); // get all interrupt flags
if(ADC_IntGet(ADC0) & ADC_IF_SINGLE) { // if interrupt is for single measurement
ADC_IntClear(ADC0, flags); // clear the interrupt
adc_value = ADC_DataSingleGet(ADC0); // get the measured value
adc_measurement_ready=1; // set ready flag
}
}
File autogen_adc0.h:
#include "em_adc.h"
#ifndef ADC0_H
#define ADC0_H
void ADC0_setup(void);
void eADesigner_Init(void);
#endif
File autogen_adc0.c:
#include "em_cmu.h"
#include "autogen_adc0.h"
void ADC0_setup(void)
{
// ADC was initialized in eDesigner from Silicon Labs.
// If will be any questions about the values, please write it into comments and I'll answer you :)
ADC_Init_TypeDef init = ADC_INIT_DEFAULT; //set variable to default values
init.ovsRateSel = adcOvsRateSel2;
init.lpfMode = adcLPFilterBypass;
init.warmUpMode = adcWarmupKeepADCWarm; //keep adc warm - high power consumption
init.timebase = ADC_TimebaseCalc(0);
init.prescale = ADC_PrescaleCalc(7000000, 0);
init.tailgate = 0;
ADC_Init(ADC0, &init);
// !!! Initialize a single sample conversion. !!!
// To start a conversion, use ADC_Start().
// Conversion result can be read with ADC_DataSingleGet().
ADC_InitSingle_TypeDef initSingle = ADC_INITSINGLE_DEFAULT;
initSingle.prsSel = adcPRSSELCh0;
initSingle.acqTime = adcAcqTime8;
initSingle.reference = adcRef1V25;
initSingle.resolution = adcRes12Bit;
initSingle.input = adcSingleInpCh1;
initSingle.diff = 0;
initSingle.prsEnable = 0;
initSingle.leftAdjust = 0;
initSingle.rep = 0;
ADC_InitSingle(ADC0, &initSingle);
ADC_IntEnable(ADC0, ADC_IF_SINGLE); // Enable interrupt for single conversion
NVIC_EnableIRQ(ADC0_IRQn); // Enable ADC0 interrupt
}
void eADesigner_Init(void)
{
/* Using HFRCO at 14MHz as high frequency clock, HFCLK */
CMU_ClockSelectSet(cmuClock_HF, cmuSelect_HFRCO);
/* No low frequency clock source selected */
/* Enable clock for ADC0 */
CMU_ClockEnable(cmuClock_ADC0, true);
/* Custom initialization for ADC0 */
ADC0_setup();
}
That’s all for now!
Bye! 🙂