STM32: ADC with DMA
Options
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
2015-07-06 08:05 AM
Posted on July 06, 2015 at 17:05
Hi everyone,
I'm trying to get a timer triggered (TIM2_UPDATE) AD-conversion of 8 regular channels working. The System is running with 168 MHz. AD-conversion is done in scan mode with a frequency of 2 kHz. For data handling a circular-mode DMA is used. After starting Timer 2 the CPU is running into MemManage Error Interrupt. Thats why I think the problem lies in the DMA configuration. Can everyone help? I have to use the HAL library with the following code:#define NUMCHANNELS 8
ADC_HandleTypeDef ADC_Handle;
ADC_ChannelConfTypeDef ADC_ChannelConf[NUM_CHANNELS];
DMA_HandleTypeDef DMA_Handle;
TIM_MasterConfigTypeDef sMasterConfig;
uint16_t DmaBuffer[NUM_CHANNELS];
__DMA2_CLK_ENABLE();
DMA_Handle.Instance = DMA2_Stream0;
HAL_DMA_DeInit( &DMA_Handle );
DMA_Handle.Init.Channel = DMA_CHANNEL_0;
DMA_Handle.Init.Direction = DMA_PERIPH_TO_MEMORY;
DMA_Handle.Init.PeriphInc = DMA_PINC_DISABLE;
DMA_Handle.Init.MemInc = DMA_MINC_ENABLE;
DMA_Handle.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
DMA_Handle.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
DMA_Handle.Init.Mode = DMA_CIRCULAR;
DMA_Handle.Init.Priority = DMA2_PRIO_ADC12;
DMA_Handle.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
DMA_Handle.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_HALFFULL;
DMA_Handle.Init.MemBurst = DMA_MBURST_SINGLE;
DMA_Handle.Init.PeriphBurst = DMA_PBURST_SINGLE;
DMA_Handle.XferCpltCallback = TransferError;
DMA_Handle.XferErrorCallback = TransferError;
DMA_Handle.XferHalfCpltCallback = TransferError;
DMA_Handle.XferM1CpltCallback = TransferError;
HAL_DMA_Init( &DMA_Handle );
HAL_NVIC_SetPriority(DMA2_Stream0_IRQn, 11, 0);
HAL_NVIC_EnableIRQ(DMA2_Stream0_IRQn);
// Enable TIM2 clock
__TIM2_CLK_ENABLE();
// TIM2 configuration
// TIM2CLK = 2*PCLK1 = 84 MHz, Prescaler = 84, TIM2 counter clock = 1 MHz
TimHandle.Instance = TIM2;
TimHandle.Init.Prescaler = (PM_Rcc_t::PCLK1 * 2 / 100000) - 1;
TimHandle.Init.Period = 10000;
TimHandle.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
TimHandle.Init.CounterMode = TIM_COUNTERMODE_UP;
TimHandle.Init.RepetitionCounter = 0;
if(HAL_TIM_Base_Init( &TimHandle ) != HAL_OK)
TRACE(1, (TRACE_ERR, ''Timer 2 Init failed''));
sMasterConfig.MasterOutputTrigger = TIM_TRGO_UPDATE;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
if(HAL_TIMEx_MasterConfigSynchronization(&TimHandle, &sMasterConfig) != HAL_OK)
TRACE(1, (TRACE_ERR, ''Timer 2 Init failed''));
// Enable ADC clock
__ADC1_CLK_ENABLE();
// ADC configuration
// AHB2CLK = 84 MHz, PRESCALER = 4, ADCCLK = 21 MHz
// 12 bit conversion needs 12 cycles + 3
// ADC is triggered externally by TIM2 UPDATE
ADC_Handle.Instance = ADC1;
ADC_Handle.Init.ClockPrescaler = ADC_CLOCKPRESCALER_PCLK_DIV4;
ADC_Handle.Init.Resolution = ADC_RESOLUTION12b;
ADC_Handle.Init.ScanConvMode = ENABLE;
ADC_Handle.Init.ContinuousConvMode = DISABLE;
ADC_Handle.Init.DiscontinuousConvMode = DISABLE;
ADC_Handle.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_RISING;
ADC_Handle.Init.ExternalTrigConv = ADC_EXTERNALTRIGCONV_T2_TRGO;
ADC_Handle.Init.DataAlign = ADC_DATAALIGN_RIGHT;
ADC_Handle.Init.NbrOfConversion = NUM_CHANNELS;
ADC_Handle.Init.NbrOfDiscConversion = 0;
ADC_Handle.Init.EOCSelection = EOC_SINGLE_CONV; // EOC_SEQ_CONV;
ADC_Handle.Init.DMAContinuousRequests = ENABLE;
if(HAL_ADC_Init( &ADC_Handle ) != HAL_OK)
TRACE(1, (TRACE_ERR, ''ADC Init failed''));
__HAL_LINKDMA(&ADC_Handle, DMA_Handle, DMA_Handle);
ADC_ChannelConf[LOAD_12].Channel = ADC_CHANNEL_0;
ADC_ChannelConf[LOAD_12].Rank = 1;
ADC_ChannelConf[LOAD_12].SamplingTime = ADC_SAMPLETIME_3CYCLES;
ADC_ChannelConf[LOAD_12].Offset = 0;
HAL_ADC_ConfigChannel(&ADC_Handle, &ADC_ChannelConf[LOAD_12]);
ADC_ChannelConf[LOAD_3].Channel = ADC_CHANNEL_2;
ADC_ChannelConf[LOAD_3].Rank = 2;
ADC_ChannelConf[LOAD_3].SamplingTime = ADC_SAMPLETIME_3CYCLES;
ADC_ChannelConf[LOAD_3].Offset = 0;
HAL_ADC_ConfigChannel(&ADC_Handle, &ADC_ChannelConf[LOAD_3]);
ADC_ChannelConf[LOAD_4].Channel = ADC_CHANNEL_3;
ADC_ChannelConf[LOAD_4].Rank = 3;
ADC_ChannelConf[LOAD_4].SamplingTime = ADC_SAMPLETIME_3CYCLES;
ADC_ChannelConf[LOAD_4].Offset = 0;
HAL_ADC_ConfigChannel(&ADC_Handle, &ADC_ChannelConf[LOAD_4]);
ADC_ChannelConf[LOAD_5].Channel = ADC_CHANNEL_8;
ADC_ChannelConf[LOAD_5].Rank = 4;
ADC_ChannelConf[LOAD_5].SamplingTime = ADC_SAMPLETIME_3CYCLES;
ADC_ChannelConf[LOAD_5].Offset = 0;
HAL_ADC_ConfigChannel(&ADC_Handle, &ADC_ChannelConf[LOAD_5]);
ADC_ChannelConf[LOAD_6].Channel = ADC_CHANNEL_9;
ADC_ChannelConf[LOAD_6].Rank = 5;
ADC_ChannelConf[LOAD_6].SamplingTime = ADC_SAMPLETIME_3CYCLES;
ADC_ChannelConf[LOAD_6].Offset = 0;
HAL_ADC_ConfigChannel(&ADC_Handle, &ADC_ChannelConf[LOAD_6]);
ADC_ChannelConf[GRID_VOLTAGE].Channel = ADC_CHANNEL_10;
ADC_ChannelConf[GRID_VOLTAGE].Rank = 6;
ADC_ChannelConf[GRID_VOLTAGE].SamplingTime = ADC_SAMPLETIME_3CYCLES;
ADC_ChannelConf[GRID_VOLTAGE].Offset = 0;
HAL_ADC_ConfigChannel(&ADC_Handle, &ADC_ChannelConf[GRID_VOLTAGE]);
ADC_ChannelConf[TEMP_HEATSINK].Channel = ADC_CHANNEL_11;
ADC_ChannelConf[TEMP_HEATSINK].Rank = 7;
ADC_ChannelConf[TEMP_HEATSINK].SamplingTime = ADC_SAMPLETIME_3CYCLES;
ADC_ChannelConf[TEMP_HEATSINK].Offset = 0;
HAL_ADC_ConfigChannel(&ADC_Handle, &ADC_ChannelConf[TEMP_HEATSINK]);
ADC_ChannelConf[VCC12V_A].Channel = ADC_CHANNEL_12;
ADC_ChannelConf[VCC12V_A].Rank = 8;
ADC_ChannelConf[VCC12V_A].SamplingTime = ADC_SAMPLETIME_3CYCLES;
ADC_ChannelConf[VCC12V_A].Offset = 0;
HAL_ADC_ConfigChannel(&ADC_Handle, &ADC_ChannelConf[VCC12V_A]);
if(HAL_ADC_Start_DMA( &ADC_Handle, (uint32_t*)DmaBuffer, NUM_CHANNELS) != HAL_OK)
TRACE(1, (TRACE_ERR, ''ADC Init failed''));
/* Diable the Half transfer complete interrupt */
__HAL_DMA_DISABLE_IT(ADC_Handle.DMA_Handle, DMA_IT_HT);
/* Diable the transfer Error interrupt */
//__HAL_DMA_DISABLE_IT(ADC_Handle.DMA_Handle, DMA_IT_TE);
/* Diable the FIFO Error interrupt */
//__HAL_DMA_DISABLE_IT(ADC_Handle.DMA_Handle, DMA_IT_FE);
/* Diable the direct mode Error interrupt */
//__HAL_DMA_DISABLE_IT(ADC_Handle.DMA_Handle, DMA_IT_DME);
__HAL_ADC_DISABLE_IT(&ADC_Handle, ADC_IT_OVR);
__HAL_ADC_DISABLE_IT(&ADC_Handle, ADC_IT_EOC);
__HAL_ADC_DISABLE_IT(&ADC_Handle, ADC_IT_AWD);
__HAL_ADC_DISABLE_IT(&ADC_Handle, ADC_IT_JEOC);
if(HAL_TIM_Base_Start(&TimHandle) != HAL_OK)
TRACE(1, (TRACE_ERR, ''Timer 2 Init failed''));
1 REPLY 1
Options
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
2015-07-06 08:12 AM
Posted on July 06, 2015 at 17:12
I forgot to mention the DMA IRQ Handler i used:
void DMA2_Stream0_IRQHandler( void )
{
HAL_DMA_IRQHandler( ADC_Handle.DMA_Handle );
}