Question
TIM triggered ADC DMA issue
Posted on May 13, 2016 at 10:53
Hi all,
I am using an STM32F303 to sample PA7 via ADC2 when TIM8 update triggers it, and using DMA to put the samples in a circular buffer. Although I seem to have gotten things basically working in the code below, I am having an issue once the DMA buffer is filled... I seem to be getting regular samples updating in the buffer with each TIM8_UP interrupt, but this stops once the buffer is filled and does not cycle back to the start of the buffer as would be expected from the circular mode on the DMA.Any ideas what I am doing wrong?uint16_t adc[8];void init_adc() { ADC_CommonInitTypeDef ADC_CommonInitStructure; ADC_InitTypeDef ADC_InitStructure; GPIO_InitTypeDef GPIO_InitStructure; TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; // Activate clocks RCC_ADCCLKConfig(RCC_ADC12PLLCLK_Div2); RCC_AHBPeriphClockCmd(RCC_AHBPeriph_ADC12, ENABLE); RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA2, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM8, ENABLE); // Timer TIM_TimeBaseStructInit(&TIM_TimeBaseStructure); TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseStructure.TIM_Period = 1999; TIM_TimeBaseStructure.TIM_Prescaler = 8000; TIM_TimeBaseInit(TIM8, &TIM_TimeBaseStructure); TIM_SelectOutputTrigger(TIM8,TIM_TRGOSource_Update); //TIM_SelectMasterSlaveMode(TIM8, TIM_MasterSlaveMode_Enable); TIM_ITConfig(TIM8, TIM_IT_Update, ENABLE); NVIC_InitTypeDef NVIC_InitStructure; NVIC_InitStructure.NVIC_IRQChannel = TIM8_UP_IRQn; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x0F; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x0F; NVIC_Init(&NVIC_InitStructure); // Analog input PA7 -> ADC2_IN4 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ; GPIO_Init(GPIOA, &GPIO_InitStructure); // Capture DMA DMA_InitTypeDef DMA_InitStructure; DMA_DeInit(DMA2_Channel1); DMA_StructInit(&DMA_InitStructure); DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)(adc); DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)(&(ADC2->DR)); DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; DMA_InitStructure.DMA_BufferSize = 8; 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_Circular; DMA_InitStructure.DMA_Priority = DMA_Priority_High; DMA_Init(DMA2_Channel1, &DMA_InitStructure); DMA_Cmd(DMA2_Channel1, ENABLE); // Init struct ADC_StructInit(&ADC_InitStructure); ADC_CommonStructInit(&ADC_CommonInitStructure); ADC_Cmd(ADC2, DISABLE); ADC_DeInit(ADC2); // Initialize the ADC ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent; ADC_CommonInitStructure.ADC_Clock = ADC_Clock_SynClkModeDiv2;//ADC_Clock_AsynClkMode;// ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled;//ADC_DMAAccessMode_1;// ADC_CommonInitStructure.ADC_TwoSamplingDelay = 0;//0x05;// ADC_TwoSamplingDelay_5Cycles; ADC_CommonInit(ADC2, &ADC_CommonInitStructure); // ADC2 init ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b; ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;//ENABLE;// //ADC_InitStructure.ADC_ScanConvMode = ENABLE; ADC_InitStructure.ADC_ExternalTrigConvEvent = ADC_ExternalTrigConvEvent_7;//TIM8_TRGO ADC_InitStructure.ADC_ExternalTrigEventEdge = ADC_ExternalTrigEventEdge_RisingEdge;//BothEdge;//None;// ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; ADC_InitStructure.ADC_OverrunMode = DISABLE;//ENABLE;// ADC_InitStructure.ADC_AutoInjMode = DISABLE;//ENABLE;// ADC_InitStructure.ADC_NbrOfRegChannel = 1; ADC_Init(ADC2, &ADC_InitStructure); // Configure channel (ADC2_IN4 <- PA7) ADC_RegularChannelConfig(ADC2, ADC_Channel_4, 1, ADC_SampleTime_19Cycles5);//1Cycles5); ADC_DMACmd(ADC2, ENABLE); ADC_Cmd(ADC2, ENABLE); TIM_Cmd(TIM8, ENABLE); ADC_StartConversion(ADC2);}
void show_adc() { //uint32_t w = (uint32_t)adc[0]; USART_word((uint32_t)adc[0]); USART_word((uint32_t)adc[1]); USART_word((uint32_t)adc[2]); USART_word((uint32_t)adc[3]); USART_word((uint32_t)adc[4]); USART_word((uint32_t)adc[5]); USART_word((uint32_t)adc[6]); USART_word((uint32_t)adc[7]); //USART_word(ADC2->DR);}void TIM8_UP_IRQHandler() { TIM_ClearITPendingBit(TIM8, TIM_IT_Update); show_adc();}