2017-11-15 01:13 PM
Hello,
I'm trying to trigger an ADC conversion externally from TRGO2 and store it to a buffer through DMA. However, it doesn't appear that anything is being written to that buffer. Could someone please look through my initialization code and let me know if I'm messing something up during the initialization?
void InitADC(void)
{
int i;
ADC_InitTypeDef ADC_InitStructure;
ADC_CommonInitTypeDef ADC_CommonInitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
DMA_InitTypeDef DMA_InitStructure;
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
DMA_DeInit(DMA1_Channel1);
DMA_InitStructure.DMA_BufferSize = 2;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)adcBuffer;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&ADC2->DR;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_Priority = DMA_Priority_High;
DMA_Init(DMA1_Channel1, &DMA_InitStructure);
DMA_Cmd(DMA1_Channel1, ENABLE);
/* Configure the ADC clock */
RCC_ADCCLKConfig(RCC_ADC12PLLCLK_Div2);
/* Enable ADC12 clock */
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_ADC12, ENABLE);
ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent;
ADC_CommonInitStructure.ADC_Clock = ADC_Clock_SynClkModeDiv1;
ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_1;
ADC_CommonInitStructure.ADC_DMAMode = ADC_DMAMode_OneShot;
ADC_CommonInitStructure.ADC_TwoSamplingDelay = 0;
ADC_CommonInit(ADC2, &ADC_CommonInitStructure);
/* GPIOA Periph clock enable */
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);
/* Configure ADC2 Channel1 as analog input */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;
GPIO_Init(GPIOA, &GPIO_InitStructure);
ADC_StructInit(&ADC_InitStructure);
/* Calibration procedure */
ADC_VoltageRegulatorCmd(ADC2, ENABLE);
for(i = 0; i < 1000; i++) {}
ADC_SelectCalibrationMode(ADC2, ADC_CalibrationMode_Single);
ADC_StartCalibration(ADC2);
while(ADC_GetCalibrationStatus(ADC2) != RESET );
ADC_InitStructure.ADC_ContinuousConvMode = ADC_ContinuousConvMode_Disable;
ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;
ADC_InitStructure.ADC_ExternalTrigConvEvent = ADC_ExternalTrigConvEvent_10;
ADC_InitStructure.ADC_ExternalTrigEventEdge = ADC_ExternalTrigEventEdge_RisingEdge;
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
ADC_InitStructure.ADC_OverrunMode = ADC_OverrunMode_Disable;
ADC_InitStructure.ADC_AutoInjMode = ADC_AutoInjec_Disable;
ADC_InitStructure.ADC_NbrOfRegChannel = 2;
ADC_Init(ADC2, &ADC_InitStructure);
/* ADC2 regular channel1 configuration */
ADC_RegularChannelConfig(ADC2, ADC_Channel_1, 1, ADC_SampleTime_7Cycles5);
ADC_RegularChannelConfig(ADC2, ADC_Channel_2, 2, ADC_SampleTime_7Cycles5);
#warning 'Figure out priority'
/* Configure and enable ADC2 interrupt */
NVIC_InitStructure.NVIC_IRQChannel = ADC1_2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
/* Enable EOS interrupt */
ADC_ITConfig(ADC2, ADC_IT_EOS, ENABLE);
/* Enable ADC2 */
ADC_Cmd(ADC2, ENABLE);
ADC_DMACmd(ADC2, ENABLE);
/* wait for ADRDY */
while(!ADC_GetFlagStatus(ADC2, ADC_FLAG_RDY));
/* Start ADC2 Software Conversion */
ADC_StartConversion(ADC2);
}
void ADC1_2_IRQHandler(void)
{
if(ADC_GetFlagStatus(ADC2, ADC_FLAG_EOS) != RESET)
{
/* Clear ADC2 AWD pending interrupt bit */
ADC_ClearITPendingBit(ADC2, ADC_IT_EOS);
adcBuffer[0] = (adcBuffer[0] * ADC_VREF) >> 12;
adcBuffer[1] = (adcBuffer[1] * ADC_VREF) >> 12;
}
}�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?
Question 2: The schematic I'm working with is using ADC peripheral 1 and ADC peripheral 2 as part of the group of signals I'd like to sample during the TRGO2 event. Do I need to set up a different DMA channel to capture the sample from the other peripheral?
Thanks.
#dma-adc #dma-transfer #stm32f3Solved! Go to Solution.
2017-11-17 12:17 PM
I appear to have solved the issue. Looking further in the datasheet I realized that ADC2 was not connected to DMA1 channel 1
The correct DMA connection to ADC2 is DMA2 Channel 1:
2017-11-15 03:46 PM
Which mcu?
Did you verify that your trigger source works and the trigger is set properly in timer?
JW
2017-11-15 10:21 PM
Yes, trigger source works. The ADC interrupt is firing and I can read the value directly from there, however the adcBuffer which is the address the DMA is set to is empty.
I'm using the STM32F303VC.
2017-11-16 01:41 AM
Remove (don't enable) the interrupt. Instead, use the transfer complete interrupt from DMA.
Make sure both DMACFG and DMAEN are set in ADCx_CFGR.
JW
2017-11-16 08:13 AM
You mean by calling
/* Configures the ADC DMA */
ADC_DMAConfig(ADC2, ADC_DMAMode_Circular); /* Enable the ADC DMA */ ADC_DMACmd(ADC2, ENABLE);?
I did that and removed the ADC interrupt, instead added the DMA interrupt using the following function call:
DMA_ITConfig(DMA1_Channel1, DMA1_IT_TC1, ENABLE);
with this handler:
void DMA1_Channel1_IRQHandler(void)
{ if (DMA_GetFlagStatus(DMA1_FLAG_TC1) != RESET) { DMA_ClearITPendingBit(DMA1_FLAG_TC1); adcBuffer[0] = (adcBuffer[0] * ADC_VREF) >> 12;adcBuffer[1] = (adcBuffer[1] * ADC_VREF) >> 12;
// Debug LEDs: GPIO_SetBits( GPIOE, GPIO_Pin_9 ); GPIO_ResetBits( GPIOE, GPIO_Pin_9 ); } }But this interrupt is not firing. The buffer is still empty.
2017-11-16 08:42 AM
Read out and post the relevant ADC and DMA register content.
JW
2017-11-16 09:23 AM
Certainly. Thanks for your help so far!
Here's the register content:
ADC2 CR: 0x10000005
ADC2 CFGR: 0x00000683
DMA1_CH1 CCR: 0x000025A3
DMA1_CH1 CNDTR: 0x00000002
DMA1_CH1 CPAR: 0x50000140
DMA1_CH1 CMAR: 0x2000001C
2017-11-17 12:17 PM
I appear to have solved the issue. Looking further in the datasheet I realized that ADC2 was not connected to DMA1 channel 1
The correct DMA connection to ADC2 is DMA2 Channel 1: