This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

ADC config with DMA and Timer

Hi,

I want to program STM32F103 in which define an array that is completed with ADC value. I need to trigger the ADC with timer and also use DMA. It means that when the array complete, the DMA_IRQ Handler send this array by USART channel. I wrote this code but it doesn't work.

I would be appreciate if you help me to correct this program.

#include "stm32f10x.h"

#define ADC1_DR_Address    ((uint32_t)0x4001244C)
uint16_t array [32];
DMA_InitTypeDef DMA_InitStructure;

int main(void)
{

  RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_AFIO, ENABLE);
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_USART1,ENABLE);
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC , ENABLE);
  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);

  GPIO_InitTypeDef GPIO_InitStructure;
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_Init(GPIOA, &GPIO_InitStructure);

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_Init(GPIOA, &GPIO_InitStructure);

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
  GPIO_Init(GPIOA, &GPIO_InitStructure);

   NVIC_InitTypeDef sara3;
  sara3.NVIC_IRQChannel = DMA1_Channel1_IRQn;
  sara3.NVIC_IRQChannelPreemptionPriority = 0;
  sara3.NVIC_IRQChannelSubPriority = 0;
  sara3.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&sara3);

  TIM_TimeBaseInitTypeDef Tim_TimeBaseStructure;
  TIM_TimeBaseStructInit(&Tim_TimeBaseStructure);
  Tim_TimeBaseStructure.TIM_Period = 9000;
  Tim_TimeBaseStructure.TIM_Prescaler = 0x0;
  Tim_TimeBaseStructure.TIM_ClockDivision = 0x0;
  Tim_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
  TIM_TimeBaseInit(TIM2, &Tim_TimeBaseStructure);
  TIM_SelectOutputTrigger(TIM2, TIM_TRGOSource_Update);

 TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);

  /*
  TIM_OCInitTypeDef  TIM_OCInitStructure;
  TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
  TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
  TIM_OCInitStructure.TIM_Pulse = 0x7F;
  TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;
  TIM_OC1Init(TIM2, &TIM_OCInitStructure);
  */


  ADC_InitTypeDef ADC_InitStructure;
  ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
  ADC_InitStructure.ADC_ScanConvMode = DISABLE;
  ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
  ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T2_CC2;
  ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
  ADC_InitStructure.ADC_NbrOfChannel = 1;
  ADC_Init(ADC1, &ADC_InitStructure);

  ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 1, ADC_SampleTime_55Cycles5);

  //ADC_SoftwareStartConvCmd(ADC1,ENABLE);







  DMA_DeInit(DMA1_Channel1);
  DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1_DR_Address;
  DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)array;
  DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
  DMA_InitStructure.DMA_BufferSize = 32;
  DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
  DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
  DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
  DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
  DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
  DMA_InitStructure.DMA_Priority = DMA_Priority_High;
  DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
  DMA_Init(DMA1_Channel1, &DMA_InitStructure);

    USART_InitTypeDef USART_InitStructure;
  USART_InitStructure.USART_BaudRate = 115200;
  USART_InitStructure.USART_WordLength = USART_WordLength_8b;
  USART_InitStructure.USART_StopBits = USART_StopBits_1;
  USART_InitStructure.USART_Parity = USART_Parity_No;
  USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
  USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
  USART_Init(USART1, &USART_InitStructure);
  USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
  USART_ITConfig(USART1, USART_IT_TXE, ENABLE);
  USART_ClearFlag(USART1,USART_FLAG_TC);


  DMA_ITConfig (DMA1_Channel1, DMA_IT_TC,ENABLE);
  DMA_Cmd(DMA1_Channel1, ENABLE);


  ADC_Cmd(ADC1, ENABLE);
  ADC_DMACmd(ADC1, ENABLE);
  USART_Cmd(USART1, ENABLE);
  TIM_Cmd(TIM2, ENABLE);


  ADC_ResetCalibration(ADC1);
  while(ADC_GetResetCalibrationStatus(ADC1));
  ADC_StartCalibration(ADC1);
  while(ADC_GetCalibrationStatus(ADC1));



   while (1);

}



void DMA1_Channel1_IRQHandler(void)
{

  uint8_t i = 0;
  if( DMA_GetITStatus(DMA1_FLAG_TC1) )
  {
        for(i = 0;i < 32 ; i++){

      USART_SendData(USART1, (uint8_t) array[i]);
      while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET) {}

      USART_SendData(USART1, (uint8_t) array[i]>> 8);
      while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET) {}
      }


  DMA_DeInit(DMA1_Channel1);
  DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1_DR_Address;
  DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)array;
  DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
  DMA_InitStructure.DMA_BufferSize = 32;
  DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
  DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Disable;
  DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
  DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
  DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
  DMA_InitStructure.DMA_Priority = DMA_Priority_High;
  DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
  DMA_Init(DMA1_Channel1, &DMA_InitStructure);



  ADC_DMACmd(ADC1, ENABLE);
DMA_Cmd(DMA1_Channel1, ENABLE);

    DMA_ClearITPendingBit(DMA1_IT_TC1);
    DMA_ClearITPendingBit(DMA1_IT_GL1);
  }
}

Parents
  • I could'nt find any in tne posted sourcecode that show's C++ Code. It's native C language that
    fill's the init structures of stdLibrary functions to initialize the DMA and other hardware.

    Well, the topic sounds like a problem with the dma usage. I remember that there is a problem
    realated to the DMA usage with the STM32F1xx family. The usage of one DMA should be ok, but
    more than one results in an unexpected state. There is an errata available who describe the details
    around the dma issue.
    I had successfully used the DMA transfer mode to readout the ADC1 on STM32F103VC and STM32F407VG.

    Good luck to solve the problems and don't foget to report the final results or the solution.

    Juppeck

Reply
  • I could'nt find any in tne posted sourcecode that show's C++ Code. It's native C language that
    fill's the init structures of stdLibrary functions to initialize the DMA and other hardware.

    Well, the topic sounds like a problem with the dma usage. I remember that there is a problem
    realated to the DMA usage with the STM32F1xx family. The usage of one DMA should be ok, but
    more than one results in an unexpected state. There is an errata available who describe the details
    around the dma issue.
    I had successfully used the DMA transfer mode to readout the ADC1 on STM32F103VC and STM32F407VG.

    Good luck to solve the problems and don't foget to report the final results or the solution.

    Juppeck

Children
  • Congratulation on digging up a two month old thread, and then missing all the nuances of the problem. There's a least a dozen problems with the original code, and your solution is to post an example for a different processor which doesn't really address any of the core issues. Nor does it do what the OP wanted on your chosen target.

    Sure I could have wasted a bunch of my time correcting and fixing this, but I'd learn nothing, and the OP would miss a learning moment that you can't just cut and paste a bunch of random code together without any thought, or bothering to read the reference manuals.

  • I guess that nobody want to do the work for you, so you must solve them instead.

  • Where is the DMA channel declaration?

    like:
    DMA_InitStructure.DMA_Channel = DMA_Channel_0;

    DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)array; <--- this don't works.
    DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)&array;<-- This works - see my example

    DMA_InitStructure.DMA_BufferSize = 32; 32 half-word are used as Buffer?
    ADC_InitStructure.ADC_NbrOfChannel = 1; and just one CHannel should be aquire????

    ADC_InitStructure.ADC_NbrOfChannel = 1; one channel needs just
    DMA_InitStructure.DMA_BufferSize = 1; one memory sized of a half-word buffer

    DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; <-- not required to fill - you do P2M

    // This should used to trigger the conversation by the timer.
    //
    ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None; //
    ADC_InitStructure.ADC_ExternalTrigConv = 0;

    I don't had looked your code longer because the structure is mystic.