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 add some init code that uses the STM32F407 and this show's the setup of 4 ADC1 channels handled by DMA transfer.

    #define Num_used_ADC_Channels   5                                                       // how many ADC channels should be handled?                                             // Wieviel ADC-Kanäle sollen ausgelesen werden? !!!
    #define Num_Of_Used_Buffers     Num_used_ADC_Channels                                   // how many memory should be used by DMA ?
    
    volatile uint16_t ADCBuffer[Num_Of_Used_Buffers + 2] = { 0x00AA,0,0,0,0,0,0x00BB };             // DMA-Buffer - 5 words
    enum __ADC_CHAN_BUFF_ORDER__ { CH0 = 1, CH1 = 2, VBAT = 3, TEMP = 4, VREF = 5  };       // Weleche Reihenfolge sollen die ADC Kanöäle gelesen werden?
    
    
    void Init_ADC ( void ) {
    
        // ############## ADC ##########################################################################################################
        // ---------- Configure PB0 and PB1 (ADC Channel1 and ADC Channel2 ) as analog input ------------------
        //
        // GPIOB function block clock enable
    
        RCC_APB2PeriphClockCmd ( RCC_APB2Periph_ADC1,  ENABLE );    // clock to ADC1
        RCC_AHB1PeriphClockCmd ( RCC_AHB1Periph_GPIOB, ENABLE );    // clock to PortB
    
        GPIO_InitStructure.GPIO_Pin  = GPIO_Pin_0 | GPIO_Pin_1;     // Init AIN0 / AIN1
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;                // alternative mode "Analog in"
        GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;
        GPIO_Init ( GPIOB, &GPIO_InitStructure );                                                                       // Init GPIO-PORTA as Analog input
    
    
    
        // DMA2 Stream0 configuration ------------------------------------------------------------------------------------------------
        //
        // Enable DMA2 clock
    
        RCC_AHB1PeriphClockCmd ( RCC_AHB1Periph_DMA2, ENABLE );
        DMA_DeInit ( DMA2_Stream0 );
    
        DMA_InitStructure.DMA_Channel               = DMA_Channel_0;
        DMA_InitStructure.DMA_PeripheralBaseAddr    = (uint32_t) ADC1_DR_Address;           // source
        DMA_InitStructure.DMA_Memory0BaseAddr       = (uint32_t) &ADCBuffer[1];         // destination - start to copy by dma at the second element of the array
        DMA_InitStructure.DMA_DIR                   = DMA_DIR_PeripheralToMemory;           // Transfertype
        DMA_InitStructure.DMA_BufferSize            = Num_used_ADC_Channels;                // Num of ADC register that should transfered
        DMA_InitStructure.DMA_PeripheralInc         = DMA_PeripheralInc_Disable;            // Register address is static - no increment.
        DMA_InitStructure.DMA_MemoryInc             = DMA_MemoryInc_Enable;                 // auto increment the memory at each transfer
        DMA_InitStructure.DMA_PeripheralDataSize    = DMA_PeripheralDataSize_HalfWord;      // transfer size of source register
        DMA_InitStructure.DMA_MemoryDataSize        = DMA_MemoryDataSize_HalfWord;          // transfer size of destinantion (array)
        DMA_InitStructure.DMA_Mode                  = DMA_Mode_Circular;                    // at the end of dma transfer cycle, starts again.
        DMA_InitStructure.DMA_Priority              = DMA_Priority_Low;                     // system load depended - i decide me to low priority.
        DMA_InitStructure.DMA_FIFOMode              = DMA_FIFOMode_Disable;                 //
        DMA_InitStructure.DMA_FIFOThreshold         = DMA_FIFOThreshold_HalfFull;           //
        DMA_InitStructure.DMA_MemoryBurst           = DMA_MemoryBurst_Single;               //
        DMA_InitStructure.DMA_PeripheralBurst       = DMA_PeripheralBurst_Single;           //
    
        DMA_Init ( DMA2_Stream0, &DMA_InitStructure );
        DMA_Cmd  ( DMA2_Stream0, ENABLE );
    
    
        // ------------------ ADC1 configuration -------------------------------------------------------
        //
    
        ADC_DeInit();
    
        ADC_CommonInitStructure.ADC_Mode             = ADC_Mode_Independent;
        ADC_CommonInitStructure.ADC_Prescaler        = ADC_Prescaler_Div8;
        ADC_CommonInitStructure.ADC_DMAAccessMode    = ADC_DMAAccessMode_Disabled;
        ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_20Cycles;
    
        ADC_CommonInit(&ADC_CommonInitStructure);
    
        // ########################### ADC1 Init #########################################
    
        ADC_InitStructure.ADC_Resolution             = RESOLUTION;                                                                                  //  Auflösung definiert in ADC1.h
        ADC_InitStructure.ADC_ScanConvMode           = ENABLE;
        ADC_InitStructure.ADC_ContinuousConvMode     = ENABLE;                                                                                                      // dauerhaft lesen und wandeln
        ADC_InitStructure.ADC_ExternalTrigConvEdge   = ADC_ExternalTrigConvEdge_None;               //
        ADC_InitStructure.ADC_ExternalTrigConv       = 0;                                                                                                   // ohne Trigger
        ADC_InitStructure.ADC_DataAlign              = ADC_DataAlign_Right;                         // Conversions are 12 bit - put them in the lower 12 bits of the result
        ADC_InitStructure.ADC_NbrOfConversion        = Num_used_ADC_Channels;                       // num of adc-channels
    
        ADC_Init (ADC1, &ADC_InitStructure);
        ADC_DMACmd ( ADC1, ENABLE );              // Enable ADC1 DMA
    
    
    
        // ######### ADC1 regular conversation mode  configuration ####################################
        //                         ADC ,  CHANNEL,           DMA MemoryOrder,    SampleTime
        //
    
        ADC_RegularChannelConfig(ADC1, ADC_Channel_8, CH0, ADC_SampleTime_15Cycles);
        ADC_RegularChannelConfig(ADC1, ADC_Channel_9, CH1, ADC_SampleTime_15Cycles);
        ADC_RegularChannelConfig(ADC1, ADC_Channel_Vbat, VBAT, ADC_SampleTime_15Cycles);
        ADC_RegularChannelConfig(ADC1, ADC_Channel_TempSensor, TEMP, ADC_SampleTime_15Cycles);
        ADC_RegularChannelConfig(ADC1, ADC_Channel_Vrefint, VREF, ADC_SampleTime_15Cycles);
    
    
        ADC_VBATCmd ( ENABLE );                                                                                                                     // Enable VBAT at channel 18
        ADC_TempSensorVrefintCmd ( ENABLE );                                                                // Enable TempSensor and Vrefint at channels 16 and 17
    
        ADC_DMARequestAfterLastTransferCmd ( ADC1, ENABLE );  // Enable DMA request after last transfer (Single-ADC mode)
        ADC_Cmd ( ADC1, ENABLE );                                                                                                     // Enable ADC1
    
        ADC_SoftwareStartConv ( ADC1 );                                                                                             // Start ADC1 Software Conversion
    
      return;
    }
    
    

    take care of the volatile declared array variable

    Juppeck

Reply

  • I add some init code that uses the STM32F407 and this show's the setup of 4 ADC1 channels handled by DMA transfer.

    #define Num_used_ADC_Channels   5                                                       // how many ADC channels should be handled?                                             // Wieviel ADC-Kanäle sollen ausgelesen werden? !!!
    #define Num_Of_Used_Buffers     Num_used_ADC_Channels                                   // how many memory should be used by DMA ?
    
    volatile uint16_t ADCBuffer[Num_Of_Used_Buffers + 2] = { 0x00AA,0,0,0,0,0,0x00BB };             // DMA-Buffer - 5 words
    enum __ADC_CHAN_BUFF_ORDER__ { CH0 = 1, CH1 = 2, VBAT = 3, TEMP = 4, VREF = 5  };       // Weleche Reihenfolge sollen die ADC Kanöäle gelesen werden?
    
    
    void Init_ADC ( void ) {
    
        // ############## ADC ##########################################################################################################
        // ---------- Configure PB0 and PB1 (ADC Channel1 and ADC Channel2 ) as analog input ------------------
        //
        // GPIOB function block clock enable
    
        RCC_APB2PeriphClockCmd ( RCC_APB2Periph_ADC1,  ENABLE );    // clock to ADC1
        RCC_AHB1PeriphClockCmd ( RCC_AHB1Periph_GPIOB, ENABLE );    // clock to PortB
    
        GPIO_InitStructure.GPIO_Pin  = GPIO_Pin_0 | GPIO_Pin_1;     // Init AIN0 / AIN1
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;                // alternative mode "Analog in"
        GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;
        GPIO_Init ( GPIOB, &GPIO_InitStructure );                                                                       // Init GPIO-PORTA as Analog input
    
    
    
        // DMA2 Stream0 configuration ------------------------------------------------------------------------------------------------
        //
        // Enable DMA2 clock
    
        RCC_AHB1PeriphClockCmd ( RCC_AHB1Periph_DMA2, ENABLE );
        DMA_DeInit ( DMA2_Stream0 );
    
        DMA_InitStructure.DMA_Channel               = DMA_Channel_0;
        DMA_InitStructure.DMA_PeripheralBaseAddr    = (uint32_t) ADC1_DR_Address;           // source
        DMA_InitStructure.DMA_Memory0BaseAddr       = (uint32_t) &ADCBuffer[1];         // destination - start to copy by dma at the second element of the array
        DMA_InitStructure.DMA_DIR                   = DMA_DIR_PeripheralToMemory;           // Transfertype
        DMA_InitStructure.DMA_BufferSize            = Num_used_ADC_Channels;                // Num of ADC register that should transfered
        DMA_InitStructure.DMA_PeripheralInc         = DMA_PeripheralInc_Disable;            // Register address is static - no increment.
        DMA_InitStructure.DMA_MemoryInc             = DMA_MemoryInc_Enable;                 // auto increment the memory at each transfer
        DMA_InitStructure.DMA_PeripheralDataSize    = DMA_PeripheralDataSize_HalfWord;      // transfer size of source register
        DMA_InitStructure.DMA_MemoryDataSize        = DMA_MemoryDataSize_HalfWord;          // transfer size of destinantion (array)
        DMA_InitStructure.DMA_Mode                  = DMA_Mode_Circular;                    // at the end of dma transfer cycle, starts again.
        DMA_InitStructure.DMA_Priority              = DMA_Priority_Low;                     // system load depended - i decide me to low priority.
        DMA_InitStructure.DMA_FIFOMode              = DMA_FIFOMode_Disable;                 //
        DMA_InitStructure.DMA_FIFOThreshold         = DMA_FIFOThreshold_HalfFull;           //
        DMA_InitStructure.DMA_MemoryBurst           = DMA_MemoryBurst_Single;               //
        DMA_InitStructure.DMA_PeripheralBurst       = DMA_PeripheralBurst_Single;           //
    
        DMA_Init ( DMA2_Stream0, &DMA_InitStructure );
        DMA_Cmd  ( DMA2_Stream0, ENABLE );
    
    
        // ------------------ ADC1 configuration -------------------------------------------------------
        //
    
        ADC_DeInit();
    
        ADC_CommonInitStructure.ADC_Mode             = ADC_Mode_Independent;
        ADC_CommonInitStructure.ADC_Prescaler        = ADC_Prescaler_Div8;
        ADC_CommonInitStructure.ADC_DMAAccessMode    = ADC_DMAAccessMode_Disabled;
        ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_20Cycles;
    
        ADC_CommonInit(&ADC_CommonInitStructure);
    
        // ########################### ADC1 Init #########################################
    
        ADC_InitStructure.ADC_Resolution             = RESOLUTION;                                                                                  //  Auflösung definiert in ADC1.h
        ADC_InitStructure.ADC_ScanConvMode           = ENABLE;
        ADC_InitStructure.ADC_ContinuousConvMode     = ENABLE;                                                                                                      // dauerhaft lesen und wandeln
        ADC_InitStructure.ADC_ExternalTrigConvEdge   = ADC_ExternalTrigConvEdge_None;               //
        ADC_InitStructure.ADC_ExternalTrigConv       = 0;                                                                                                   // ohne Trigger
        ADC_InitStructure.ADC_DataAlign              = ADC_DataAlign_Right;                         // Conversions are 12 bit - put them in the lower 12 bits of the result
        ADC_InitStructure.ADC_NbrOfConversion        = Num_used_ADC_Channels;                       // num of adc-channels
    
        ADC_Init (ADC1, &ADC_InitStructure);
        ADC_DMACmd ( ADC1, ENABLE );              // Enable ADC1 DMA
    
    
    
        // ######### ADC1 regular conversation mode  configuration ####################################
        //                         ADC ,  CHANNEL,           DMA MemoryOrder,    SampleTime
        //
    
        ADC_RegularChannelConfig(ADC1, ADC_Channel_8, CH0, ADC_SampleTime_15Cycles);
        ADC_RegularChannelConfig(ADC1, ADC_Channel_9, CH1, ADC_SampleTime_15Cycles);
        ADC_RegularChannelConfig(ADC1, ADC_Channel_Vbat, VBAT, ADC_SampleTime_15Cycles);
        ADC_RegularChannelConfig(ADC1, ADC_Channel_TempSensor, TEMP, ADC_SampleTime_15Cycles);
        ADC_RegularChannelConfig(ADC1, ADC_Channel_Vrefint, VREF, ADC_SampleTime_15Cycles);
    
    
        ADC_VBATCmd ( ENABLE );                                                                                                                     // Enable VBAT at channel 18
        ADC_TempSensorVrefintCmd ( ENABLE );                                                                // Enable TempSensor and Vrefint at channels 16 and 17
    
        ADC_DMARequestAfterLastTransferCmd ( ADC1, ENABLE );  // Enable DMA request after last transfer (Single-ADC mode)
        ADC_Cmd ( ADC1, ENABLE );                                                                                                     // Enable ADC1
    
        ADC_SoftwareStartConv ( ADC1 );                                                                                             // Start ADC1 Software Conversion
    
      return;
    }
    
    

    take care of the volatile declared array variable

    Juppeck

Children