AnsweredAssumed Answered

Circular DMA does not circle for ADC (STM32L1xx)

Question asked by fisher.burns on Oct 19, 2012
Latest reply on Oct 19, 2012 by fisher.burns
I'm trying to use the ADC on an STM32L1xx to read a single channel with a sample rate based on TIM2.  I plan to use a double-buffering scheme, so I want to set it up to DMA into a buffer with half-complete and fully-complete interrupts.  I think I have this working for the first pass, but it appears not to circle.  In other words, when I enable everything, I get a 1/2 transfer interrupt, and a transfer complete interrupt, but no more.  The buffer appears to have been written to, and while it is a bit hard to tell, I don't think the buffer is being written to more than once.  I see no overflow bits set.  Any ideas?  Here is the initialization code:

      DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&(ADC1->DR);         // Set DMA channel Peripheral base address to ADC Data register
      DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)buffer;  // Set DMA channel Memeory base addr to ADC_ConvertedValueBuff address
      DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;                         // Set DMA channel direction to peripheral to memory
      DMA_InitStructure.DMA_BufferSize = bufLength*2;
      DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;         // Disable DMA channel Peripheral address auto increment
      DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;                    // Enable Memory increment
      DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;// set Peripheral data size to 16bit
      DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;         // set Memeory data size to 16bit
      DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
      DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;
      DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;                               // Disable memory to memory option
      DMA_Init(DMA1_Channel1, &DMA_InitStructure);

      /* Setup NVIC for DMA channel 1 interrupt request */
      NVIC_InitStructure.NVIC_IRQChannel =   DMA1_Channel1_IRQn;
      NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 13;
      NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
      NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

      GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4  ;
      GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
      GPIO_Init( GPIOA, &GPIO_InitStructure);

      /* Enable ADC clock */
      RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);

      ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div1;

      /* Initialize the ADC1 by using its init structure */
      ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;              // Set conversion resolution to 12bit
      ADC_InitStructure.ADC_ScanConvMode = DISABLE;
      ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;              // Disable Continuous conversion
      ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T2_TRGO; // Use same trigger as D/A-timer 2
      ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_Rising;
      ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;                  // Set conversion data alignement to right
      ADC_InitStructure.ADC_NbrOfConversion = 1; // Only one conversion per trigger
      ADC_Init(ADC1, &ADC_InitStructure);
      ADC_RegularChannelConfig(ADC1, ADC_Channel_4, 1, ADC_SampleTime_16Cycles);

    /* Enable DMA1 Channel1 */
    DMA_ITConfig(DMA1_Channel1, DMA_IT_HT | DMA_IT_TC, ENABLE);
    DMA_Cmd(DMA1_Channel1, ENABLE);
    /* Enable DMA for ADC */
    /* Enable ADC Channel2 */
    ADC_Cmd(ADC1, ENABLE);