Efm32-chip peripherals-multi-channel ADC sampling + timer + PRs trigger + DMA

Source: Internet
Author: User

In application note, ADC already has many examples, but it lacks a multi-channel scheduled scanning routine. Theoretically, the ADC is configured as a multi-channel ADC conversion, which is used with DMA for data transmission and is automatically triggered using timer + PRs. This function should be completely OK. However, there is only a lack of routines and self-research processes.

Configure the ADC first.

Configure the ADC as multi-channel sampling, and set the ADC as Channel 2 in the routine ~ The only difference between the four inputs is that you need to enable the PRS, because the PRS needs to connect the timer with the ADC, so that the timer can trigger the ADC scan through the PRS.

Adc_init_typedef init = adc_init_default;

Adc_initscan_typedef scaninit = adc_initscan_default;

...................

Scaninit. prsenable = true;

 

Configure timer.

Timer determines how often the ADC performs a multi-channel Scan. In the routine, timer is configured as a simple overflow counter, with the overflow cycle of about 32 kHz.

Configure DMA.

Since the ADC scan result register has only one, you must use DMA to convert the ADC results to ram. The configuration refers to the ADC scan routine. The triggered signal of DMA data transfer is configured as dmareq_adc0_scan. In addition, you need to enable DMA interruption and set the DMA transfer completion function. In the transfer completion function, refresh the DMA.

Void transfercomplete (unsigned int channel, bool primary, void * User)
{
DMA_ActivateBasic (DMA_CHANNEL,
True,
False,
Samples,
(Void *) (uint32_t) & (ADC0-> SCANDATA )),
NUM_SAMPLES-1 );

Printf ("% d, % d, % d \ r \ n", samples [0], samples [1], samples [2]);

Gpio_pinouttoggle (gpioportd, 7 );
}

 

Configure PRS.

Connect timer to ADC and use the PRS channel 0

 

Workflow:

System initialization, including PRS initialization and configuration.

1. initialize the ADC

2. initialize the DMA and initialize a DMA transmission dma_activatebasic (). Wait for the timer to trigger the ADC for scanning.

3. initialize Timer

4. Timer timed overflow. ADC scan is triggered through PRS. dmareq_adc0_scan is transmitted to ram through DMA every time the ADC scan has data.

5. When the DMA transmission is complete, call the DMA callback function to complete the DMA refresh and wait for the next timer to trigger. Go back to step 4.

6. Added test conditions such as SWO output and ADC scan overflow interruption to the routine.

 

The routine is as follows. There may be more cases. Please be patient.

 

# Include <stdio. h>
# Include "efm32.h"
# Include "em_chip.h"
# Include "em_emu.h"
# Include "em_cmu.h"
# Include "em_adc.h"
# Include "em_prs.h"
# Include "em_timer.h"
# Include "em_dma.h"
# Include "em_gpio.h"
# Include "stdio. H"

/** DMA control block, requires proper alignment .*/
# If defined (_ iccarm __)
# Pragma data_alignment = 256
Dma_descriptor_typedef dmacontrolblock [dma_chan_count * 2];
# Elif defined (_ cc_arm)
Dma_descriptor_typedef dmacontrolblock [dma_chan_count * 2] _ attribute _ (aligned (256 )));
# Elif defined (_ gnuc __)
Dma_descriptor_typedef dmacontrolblock [dma_chan_count * 2] _ attribute _ (aligned (256 )));
# Else
# Error undefined toolkit, need to define alignment
# Endif

/* DMA callback structure */
Dma_cb_typedef CB;

/** DMA channel used for scan sequence sampling ADC Channel 2, 3 and 4 .*/
# Define DMA_CHANNEL 0
# Define NUM_SAMPLES 3

Uint32_t samples [NUM_SAMPLES];

Void setupSWO (void)
{
Uint32_t * dwt_ctrl = (uint32_t *) 0xE0001000;
Uint32_t * tpiu_prescaler = (uint32_t *) 0xE0040010;
Uint32_t * tpiu_protocol = (uint32_t *) 0xE00400F0;

CMU-> HFPERCLKEN0 | = CMU_HFPERCLKEN0_GPIO;
/* Enable Serial wire output pin */
GPIO-> ROUTE | = GPIO_ROUTE_SWOPEN;
# If defined (_ EFM32_GIANT_FAMILY)
/* Set location 0 */
GPIO-> ROUTE = (GPIO-> ROUTE &~ (_ GPIO_ROUTE_SWLOCATION_MASK) | GPIO_ROUTE_SWLOCATION_LOC0;

/* Enable output on pin-GPIO Port F, Pin 2 */
GPIO-> P [5]. MODEL & = ~ (_ GPIO_P_MODEL_MODE2_MASK );
GPIO-> P [5]. MODEL | = GPIO_P_MODEL_MODE2_PUSHPULL;
# Else
/* Set location 1 */
GPIO-> ROUTE = (GPIO-> ROUTE &~ (_ GPIO_ROUTE_SWLOCATION_MASK) | GPIO_ROUTE_SWLOCATION_LOC1;
/* Enable output on pin */
GPIO-> P [2]. MODEH & = ~ (_ GPIO_P_MODEH_MODE15_MASK );
GPIO-> P [2]. MODEH | = GPIO_P_MODEH_MODE15_PUSHPULL;
# Endif
/* Enable debug clock AUXHFRCO */
CMU-> OSCENCMD = cmu_oscen1__auxhfrcoen;

While (! (CMU-> STATUS & CMU_STATUS_AUXHFRCORDY ));

/* Enable trace in core debug */
CoreDebug-> DHCSR | = 1;
CoreDebug-> DEMCR | = CoreDebug_DEMCR_TRCENA_Msk;

/* Enable PC and IRQ sampling output */
* Dwt_ctrl = 0x400113FF;
/* Set TPIU prescaler to 16 .*/
* Tpiu_prescaler = 0xf;
/* Set protocol to NRZ */
* Tpiu_protocol = 2;
/* Unlock ITM and output data */
ITM-> LAR = 0xC5ACCE55;
ITM-> Cr = 0x10009;
}

/*************************************** ***********************************//**
* @ Brief Call-back called when transfer is complete
**************************************** *************************************/
Void transferComplete (unsigned int channel, bool primary, void * user)
{
DMA_ActivateBasic (DMA_CHANNEL,
True,
False,
Samples,
(Void *) (uint32_t) & (adc0-> scandata )),
Num_samples-1 );

Printf ("% d, % d, % d \ r \ n", samples [0], samples [1], samples [2]); // print log information

Gpio_pinouttoggle (gpioportd, 7); // used to test whether the ADC scan works properly
}

/*************************************** ***********************************//**
* @ Brief adc0_irqhandler
* Interrupt service routine for ADC
**************************************** *************************************/
Void adc0_irqhandler (void)
{
/* Clear ADC0 interrupt flag */
ADC0-> IFC = ADC_IFC_SCANOF;

Printf ("ADC Scan overflow"); // used to determine whether the ADC Scan result overflows.

}

/*************************************** ************************************//**
* @ Brief
* Configure ADC usage for this application.
**************************************** ***************************************/
Static void ADCConfig (void)
{
ADC_Init_TypeDef init = ADC_INIT_DEFAULT;
ADC_InitScan_TypeDef scanInit = ADC_INITSCAN_DEFAULT;

/* Init common issues for both single conversion and scan mode */
Init. timebase = adc_timebasec1c (0 );
Init. prescale = adc_prescalec1c (7000000, 0 );
ADC_Init (ADC0, & init );

/* Init for scan sequence use (for dvk: accelerometer X, Y and Z axis ).*/
ScanInit. reference = adcRefVDD;
ScanInit. input = ADC_SCANCTRL_INPUTMASK_CH2 | ADC_SCANCTRL_INPUTMASK_CH3 | adc_scanctrl_inputmask_methane;
ScanInit. prsEnable = true;
ADC_InitScan (ADC0, & scanInit );

/* Enable ADC Interrupt when Single Conversion Complete */
Adc0-> ien = adc_ien_scanof;

/* Enable ADC interrupt vector in nvic */
Nvic_enableirq (adc0_irqn );
}

/*************************************** ************************************//**
* @ Brief
* Configure timer for this application.
**************************************** ***************************************/
Static void timerconfig (void)
{
/* Use default timer settings */
Timer_init_typedef timerinit = timer_init_default;

/* Change prescaler to 64, gives roughly 3 overflows per
* Second at 14 MHz with 0 xFFFF as top value */
Timerinit. prescale = timerprescale1;

Timer_topset (timer0, 440 );

Timer_init (timer0, & timerinit );
}

/*************************************** ************************************//**
* @ Brief
* Configure DMA usage for this application.
**************************************** ***************************************/
Static void dmaconfig (void)
{
Dma_init_typedef dmainit;
Dma_includescr_typedef descrcfg;
Dma_cfgchannel_typedef chnlcfg;

/* Configure general DMA issues */
DmaInit. hprot = 0;
DmaInit. controlBlock = dmaControlBlock;
DMA_Init (& dmaInit );

/* Setting up call-back function */
Cb. cbFunc = transferComplete;
Cb. userPtr = NULL;

/* Configure DMA channel used */
ChnlCfg. highPri = false;
ChnlCfg. enableInt = true;
ChnlCfg. select = DMAREQ_ADC0_SCAN;
ChnlCfg. cb = & cb;
Dma_domainchannel (DMA_CHANNEL, & chnlCfg );

DescrCfg. dstInc = dmaDataInc4;
DescrCfg. srcInc = dmaDataIncNone;
DescrCfg. size = dmaDataSize4;
DescrCfg. arbRate = dmaArbitrate1;
DescrCfg. hprot = 0;
Dma_includescr (DMA_CHANNEL, true, & descrCfg );

DMA_ActivateBasic (DMA_CHANNEL,
True,
False,
Samples,
(Void *) (uint32_t) & (adc0-> scandata )),
Num_samples-1 );
}

/*************************************** ***************************************
* @ Brief Main Function
* The main file starts a timer and uses PRS to trigger an ADC conversion.
* It waits in Em1 until the ADC conversion is complete, then prints
* Result on the LCD.
**************************************** *************************************/
Int main (void)
{
/* Initialize chip */
CHIP_Init ();
SetupSWO ();

CMU_ClockEnable (cmuClock_HFPER, true );
/* Enable clocks required */
CMU_ClockEnable (cmuClock_ADC0, true );
CMU_ClockEnable (cmuClock_PRS, true );
CMU_ClockEnable (cmuClock_TIMER0, true );
CMU_ClockEnable (cmuClock_DMA, true );
CMU_ClockEnable (cmuClock_GPIO, true );

GPIO_PinModeSet (gpioPortD, 7, gpioModePushPull, 1 );

/* Select TIMER0 as source and TIMER0OF (Timer0 overflow) as signal (rising edge )*/
PRS_SourceSignalSet (0, PRS_CH_CTRL_SOURCESEL_TIMER0, PRS_CH_CTRL_SIGSEL_TIMER0OF, prsEdgePos );


ADCConfig ();
DMAConfig ();
TimerConfig ();

/* Stay in this loop forever */
While (1)
{

}
}

 

Project Link:

Http://download.csdn.net/download/efm32/4753643

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.