cancel
Showing results for 
Search instead for 
Did you mean: 

STM8L1528 ADC, DMA, TImer not working together.

Gopal
Associate

Hi there,

I am developing code for STM8L1528 EVAL board. My goal is to configure adc with dma(peripheral to memory) where adc should collect data for certain period, for example, 2 seconds.

So I configured adc and dma according to examples codes given. but I added TIM4 to stop ADC conversion after 1 seconds. My code stucks in TIM4 ISR. Is there anything I am forgetting?

Also, I configured ADC with 12 bit, fast channel 24, 4 cycles. But I am getting less sampling rate. Why is this happening? Thanks for the great help.

Below are my code snippets:

static void CLK_Config(void)

{

 /* Select HSE as system clock source */

 CLK_SYSCLKSourceSwitchCmd(ENABLE);

 CLK_SYSCLKSourceConfig(CLK_SYSCLKSource_HSE);

 /*High speed external clock prescaler: 1*/

 CLK_SYSCLKDivConfig(CLK_SYSCLKDiv_1);

 while (CLK_GetSYSCLKSource() != CLK_SYSCLKSource_HSE)

 {}

 /* Enable ADC1 clock */

 CLK_PeripheralClockConfig(CLK_Peripheral_ADC1, ENABLE);

 /* Enable DMA1 clock */

 CLK_PeripheralClockConfig(CLK_Peripheral_DMA1, ENABLE);

 /* Enable TIM1 clock */

 //CLK_PeripheralClockConfig(CLK_Peripheral_TIM1, ENABLE);

/* Enable TIM4 CLK */

 CLK_PeripheralClockConfig(CLK_Peripheral_TIM4, ENABLE); //tim4

}

static void ADC_Config(void)

{

 /* Initialize and configure ADC1 */

 ADC_Init(ADC1, ADC_ConversionMode_Single, ADC_Resolution_12Bit, ADC_Prescaler_1);

 ADC_SamplingTimeConfig(ADC1, ADC_Group_FastChannels, ADC_SamplingTime_4Cycles);

 /* Enable ADC1 */

 ADC_Cmd(ADC1, ENABLE);

 ADC_ChannelCmd(ADC1, ADC_Channel_24, ENABLE); /* connected to BNC */

}

static void DMA_Config(void)

{

 /* Connect ADC to DMA channel 0 */

 SYSCFG_REMAPDMAChannelConfig(REMAP_DMA1Channel_ADC1ToChannel0);

 DMA_Init(DMA1_Channel0, BUFFER_ADDRESS,

      ADC1_DR_ADDRESS,

      BUFFER_SIZE,

      DMA_DIR_PeripheralToMemory,

      DMA_Mode_Circular,

      DMA_MemoryIncMode_Inc,

      DMA_Priority_High,

      DMA_MemoryDataSize_HalfWord);

 /* DMA Channel0 enable */

 DMA_Cmd(DMA1_Channel0, ENABLE);

 /* Enable DMA1 channel0 Transfer complete interrupt */

 DMA_ITConfig(DMA1_Channel0, DMA_ITx_TC, ENABLE);

 /* DMA enable */

 DMA_GlobalCmd(ENABLE);

}

static void TIM4_Config(void)

{

 /* TIM4 configuration:

  - TIM4CLK is set to 16 MHz, the TIM4 Prescaler is equal to 128 so the TIM1 counter

  clock used is 16 MHz / 128 = 125 000 Hz

 - With 125 000 Hz we can generate time base:

   max time base is 2.048 ms if TIM4_PERIOD = 255 --> (255 + 1) / 125000 = 2.048 ms

   min time base is 0.016 ms if TIM4_PERIOD = 1  --> ( 1 + 1) / 125000 = 0.016 ms

 - In this example we need to generate a time base equal to 1 ms

  so TIM4_PERIOD = (0.001 * 125000 - 1) = 124 */

 /* Time base configuration */

 TIM4_TimeBaseInit(TIM4_Prescaler_128, TIM4_PERIOD);

 /* Clear TIM4 update flag */

 TIM4_ClearFlag(TIM4_FLAG_Update);

 /* Enable update interrupt */

 TIM4_ITConfig(TIM4_IT_Update, ENABLE);

 /* enable interrupts */

 enableInterrupts();

 /* Enable TIM4 */

 TIM4_Cmd(ENABLE);

}

MAIN()

{

  /* ADC configuration -------------------------------------------*/

 ADC_Config();

  /* DMA configuration -------------------------------------------*/

 DMA_Config();

   

 /* Enable ADC1 DMA requests*/

 ADC_DMACmd(ADC1, ENABLE);

 /* Start ADC1 Conversion using TIM1 TRGO*/

 ADC_ExternalTrigConfig(ADC1, ADC_ExtEventSelection_Trigger2,

            ADC_ExtTRGSensitivity_Rising);

 /* Master Mode selection: Update event */

 TIM1_SelectOutputTrigger(TIM1_TRGOSource_Update);

/* TIM4 configuration -------------------------------------------*/

  TIM4_Config(); //tim4

 /* Enable TIM1 */

 TIM1_Cmd(ENABLE);

 /* Enable Interrupts */

 enableInterrupts();

while(1)

{

//ADCData = ADC_GetConversionValue(ADC1);

   /* Display BNC voltage values on LCD*/

   ShowVoltages(((uint32_t)(ADCData)), BNCVoltage);

}

Thanks for the help. Please let me know how to configure ADC for 1 seconds. I am new in this programming.

Gopal

2 REPLIES 2
Cristian Gyorgy
Senior III

Hello Gopal!

  1. I see you don't enable the clock for TIM1 (it's commented out)
  2. I see you configure ADC1 in single conversion mode - this means, the ADC will stop after every conversion, and you need to trigger the next conversion. I suggest to let it run in continuous running mode.
  3. I don't know the functions you use, but in the DMA initialization you use: DMA_MemoryDataSize_HalfWord; is this 16 bit or 8-bit?
  4. You use TIM1 to trigger every conversion of the ADC, but I don't see how you configured TIM1, than, TIM1 will give you the number of samples/s in your case.

My suggestion: you don't need anything else except ADC1 and DMA1. Leave the timers aside. You can precisely configure the sampling rate of the ADC, let it run in continuous conversion mode and when you have the required number of samples the DMA will shoot the interrupt to process the ADC results.

Thanks @Cristian Gyorgy​  for the instant reply.

I solved that the counting manually by myself. right now I am not using timer. I just count the number of times DMA raises interrupt flags (kept counter in "DMA1 channel0 and channel1 Interrupt routine" )and based on that I manually stop the ADC. For now, that was sufficient for me.

But I have one more question though. When I connect function generator (sine wave source), I get only 120 samples for 1 seconds for 20Hz signals.........Why I am getting such a low sampling rate even it is configured with parameters like ADC_Resolution_12Bit, ADC_SamplingTime_4Cycles, ADC_Prescaler_1.

How do I increase sampling rate? is there anything I am forgetting?

Thanks for the reply.