Skip to main content
Balasubramanian vaidhyanathan
Associate III
October 20, 2017
Question

Timer2 channel 3+ADC+DMA

  • October 20, 2017
  • 2 replies
  • 736 views
Posted on October 20, 2017 at 22:51

Hi

    I am using STM32L431xx Timer3 and CC3 (compare mode ) on channel 3 and i want to trigger (ADC1  channel 1) and (DMA 1 and channel 1 ) to do collection of samples triggered on the timer edge. The timer works perfectly fine for the period I have set it work on. But I am not able to get the ADC->DMA chain working with the timer. Below are the ADC settings :

LL_ADC_SetCommonPathInternalCh(ADC1_COMMON,LL_ADC_PATH_INTERNAL_VREFINT);

LL_ADC_SetCommonClock(ADC1_COMMON,LL_ADC_CLOCK_SYNC_PCLK_DIV4);

LL_ADC_SetResolution(ADC1, LL_ADC_RESOLUTION_12B);

LL_ADC_SetOffset(ADC1, LL_ADC_OFFSET_1, LL_ADC_CHANNEL_1, 0x000);

LL_ADC_SetOffsetState(ADC1, LL_ADC_OFFSET_1,LL_ADC_OFFSET_DISABLE);

LL_ADC_SetChannelSamplingTime(ADC1,LL_ADC_CHANNEL_1, LL_ADC_SAMPLINGTIME_12CYCLES_5);

LL_ADC_REG_SetDMATransfer(ADC1,LL_ADC_REG_DMA_TRANSFER_UNLIMITED);

LL_ADC_REG_SetContinuousMode(ADC1, LL_ADC_REG_CONV_CONTINUOUS);

LL_ADC_REG_SetTriggerSource(ADC1,LL_ADC_REG_TRIG_EXT_TIM2_TRGO);

LL_ADC_Enable(ADC1);

DMA settings

LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_DMA1);

DMA_cfg.CPAR = (uint32_t)&ADC1->DR;

DMA_cfg.CMAR = (uint32_t)destAddress;//destinatoin address

DMA_cfg.CNDTR = numData;//number of bytes to be trasnferred

DMA1_Channel1->CCR = ( DMA_CCR_TCIE | DMA_CCR_TEIE | DMA_CCR_CIRC | DMA_CCR_HTIE| DMA_CCR_MINC | DMA_CCR_PSIZE_32BIT | DMA_CCR_MSIZE_32BIT | DMA_CCR_PL_VERY_HIGH ) 

DMA1_CSELR->CSELR = DMA1_CFG_CSELR; \\this value is '0'

NVIC_SetPriority(DMA1_Channel1_IRQn, 0);

NVIC_EnableIRQ(DMA1_Channel1_IRQn);

LL_DMA_EnableChannel(DMA1,LL_DMA_CHANNEL_1);

I dont see that I am able to get the ADC to trigger so that transfer happens!!!

Please help!

Regards

Bala

    This topic has been closed for replies.

    2 replies

    Tesla DeLorean
    Guru
    October 20, 2017
    Posted on October 20, 2017 at 23:38

    >>Please help!

    Look at how I post working examples, and ask yourself how to format/present code to be worked on.

    The count length for DMA is units, not bytes. The ADC->DR is 16-bit wide. I'd tinker, but see point #1

    Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
    Balasubramanian vaidhyanathan
    Associate III
    October 23, 2017
    Posted on October 23, 2017 at 21:46

    Hi Clive

       Thanks for the suggestion:

    This is what I did in the sequence below to get the TIM2 (CC on Channel 3) and that will trigger an event to start ADC1 channel 1 and I am hooking up the DMA1 channel 1 to the ADC channel

    /*This function is called from main() after setting the Timer2 channel 3 to generate TRG event */

    void Init_ADCwDMA( uint16_t *destAddress, uint16_t numData ){

    DMA_Channel_TypeDef DMA_cfg;

    DMA_cfg.CPAR = (uint32_t)&ADC1->DR;

    DMA_cfg.CMAR = (uint32_t)destAddress;

    DMA_cfg.CNDTR = numData;

    Init_ADC();

    Init_DMA();

    setDMAChannel(DMA1_Channel1, &DMA_cfg);

    }

    void Init_DMA()

    {

    /* (1) Enable the clock of DMA1 and DMA1 */

    LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_DMA1);

    DMA_Channel_TypeDef DMA1_CH1_cfg = DMA1_CH1_CFG;

    DMA1_Channel1->CCR = 0x3aae;//( DMA_CCR_TCIE | DMA_CCR_TEIE | DMA_CCR_CIRC | DMA_CCR_HTIE|                                                                 //DMA_CCR_MINC | DMA_CCR_PSIZE_32BIT | DMA_CCR_MSIZE_32BIT |                                                                      //DMA_CCR_PL_VERY_HIGH )

    DMA1_CSELR->CSELR = 0x0;

    NVIC_SetPriority(DMA1_Channel1_IRQn, 0);

    NVIC_EnableIRQ(DMA1_Channel1_IRQn);

    LL_DMA_EnableChannel(DMA1,LL_DMA_CHANNEL_1);

    }

    /* setting DMA1 channel 1 with a config of DMA1*/

    void setDMAChannel(DMA_Channel_TypeDef* channel, DMA_Channel_TypeDef *DMA_CONFIG){

    channel->CCR &= ~DMA_CCR_EN;

    channel->CNDTR = DMA_CONFIG->CNDTR;

    channel->CPAR = DMA_CONFIG->CPAR;

    channel->CMAR = DMA_CONFIG->CMAR;

    channel->CCR |= DMA_CCR_EN;

    }

    void Init_ADC( void )

    {

    uint8_t timeout;

    LL_ADC_SetCommonPathInternalCh(ADC1_COMMON,LL_ADC_PATH_INTERNAL_VREFINT);//Set an internal reference voltage for ADC

    LL_ADC_SetCommonClock(ADC1_COMMON,LL_ADC_CLOCK_SYNC_PCLK_DIV4);//Set ADC clock to SYSCLK/.4

    LL_ADC_SetResolution(ADC1, LL_ADC_RESOLUTION_12B);//12 Bit resolution

    LL_ADC_SetOffset(ADC1, LL_ADC_OFFSET_1, LL_ADC_CHANNEL_1, 0x000);//ADC1 channel 1 

    LL_ADC_SetOffsetState(ADC1, LL_ADC_OFFSET_1,LL_ADC_OFFSET_DISABLE);//Disable ADC offset 

    LL_ADC_SetChannelSamplingTime(ADC1,LL_ADC_CHANNEL_1, LL_ADC_SAMPLINGTIME_12CYCLES_5);//set conversion time

    LL_ADC_REG_SetDMATransfer(ADC1,LL_ADC_REG_DMA_TRANSFER_UNLIMITED); unlimited DMA transfer

    LL_ADC_REG_SetContinuousMode(ADC1, LL_ADC_REG_CONV_CONTINUOUS);//continous conversion

    LL_ADC_REG_SetTriggerSource(ADC1,LL_ADC_REG_TRIG_EXT_TIM2_TRGO);//Generate Timer2 trigger

    LL_ADC_Enable(ADC1);//Enable ADC1

    }

    void main()

    {

         Init_ADCwDMA( &aRcvBuf[0],160);

    / * below was  timer code and the timer does work as expected as a PWM*/

    /*The timer2 channel 3 is set in CC mode and it works good and it is tested*/

    /*The code was not put out to avoid cluttering*/

    /* Force update generation */

    LL_TIM_GenerateEvent_UPDATE(TIM2);

    /* Enable output channel 3 */

    LL_TIM_CC_EnableChannel(TIM2, LL_TIM_CHANNEL_CH3);

    LL_ADC_REG_StartConversion(ADC1);

    }