2016-10-27 08:02 AM
Hello,
i have a small problem with the ADC4 and the DMA. The code following below works with the ADC1 fine. But the ADC4 makes problems. The ADC4 works, this i could see in the debug window. But the DMA request did not work. What is my mistake?void ADC_VoltageInit(){
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA2,ENABLE);
RCC_AHBPeriphClockCmd(RCC_AHBENR_ADC34EN,ENABLE);
RCC_AHBPeriphClockCmd(RCC_AHBENR_GPIOBEN,ENABLE);
GPIO_InitADC.GPIO_Mode = GPIO_Mode_AN;
GPIO_InitADC.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_InitADC.GPIO_Pin = GPIO_Pin_12;
GPIO_Init(GPIOB,&GPIO_InitADC);
RCC_ADCCLKConfig(RCC_ADC34PLLCLK_Div1);
ADC_Init(ADC4,&ADC_Struct);
ADC_VoltageRegulatorCmd(ADC4,ENABLE);
Delay(10);//Warte auf den Regulator;
ADC_SelectCalibrationMode(ADC4,ADC_CalibrationMode_Single);
ADC_StartCalibration(ADC4);
while(ADC_GetCalibrationStatus(ADC4) != RESET);
nvicADC.NVIC_IRQChannelCmd = ENABLE;
nvicADC.NVIC_IRQChannelPreemptionPriority = 1;
nvicADC.NVIC_IRQChannelSubPriority = 1;
nvicADC.NVIC_IRQChannel = DMA2_Channel4_IRQn;
NVIC_Init(&nvicADC);
SYSCFG_DMAChannelRemapConfig(SYSCFG_DMARemap_ADC2ADC4,ENABLE);
ADC_Def.ADC_Clock = ADC_Clock_AsynClkMode;
ADC_Def.ADC_Mode = ADC_Mode_Independent;
ADC_Def.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled;
ADC_Def.ADC_DMAMode = ADC_DMAMode_Circular;
ADC_Def.ADC_TwoSamplingDelay = 0;
ADC_CommonInit(ADC4,&ADC_Def);
ADC_Struct.ADC_ContinuousConvMode = ADC_ContinuousConvMode_Enable;
ADC_Struct.ADC_Resolution = ADC_Resolution_10b;
ADC_Struct.ADC_ExternalTrigConvEvent = ADC_ExternalTrigConvEvent_0;
ADC_Struct.ADC_ExternalTrigEventEdge = ADC_ExternalTrigEventEdge_None;
ADC_Struct.ADC_DataAlign = ADC_DataAlign_Right;
ADC_Struct.ADC_OverrunMode = ADC_OverrunMode_Disable;
ADC_Struct.ADC_AutoInjMode = ADC_AutoInjec_Disable;
ADC_Struct.ADC_NbrOfRegChannel = 1;
ADC_Init(ADC4,&ADC_Struct);
ADC_RegularChannelConfig(ADC4,ADC_Channel_3,1,ADC_SampleTime_7Cycles5);
dmaADCInit.DMA_BufferSize = ADC_LNG;
dmaADCInit.DMA_DIR = DMA_DIR_PeripheralSRC;
dmaADCInit.DMA_M2M = DMA_M2M_Disable;
dmaADCInit.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
dmaADCInit.DMA_MemoryInc = DMA_MemoryInc_Enable;
dmaADCInit.DMA_Mode = DMA_Mode_Normal;
dmaADCInit.DMA_PeripheralDataSize = DMA_MemoryDataSize_HalfWord;
dmaADCInit.DMA_PeripheralInc = DMA_MemoryInc_Disable;
dmaADCInit.DMA_Priority = DMA_Priority_Medium;
dmaADCInit.DMA_MemoryBaseAddr = (uint32_t)ADC3ConvertedValue;
dmaADCInit.DMA_PeripheralBaseAddr = (uint32_t)&ADC4->DR;
DMA_Init(DMA2_Channel4,&dmaADCInit);
DMA_ITConfig(DMA2_Channel4,DMA2_IT_TC4,ENABLE);
ADC_DMAConfig(ADC4,ADC_DMAMode_OneShot);
ADC_DMACmd(ADC4,ENABLE);
ADC_Cmd(ADC4,ENABLE);
while(!ADC_GetFlagStatus(ADC4, ADC_FLAG_RDY));
DMA_Cmd(DMA2_Channel4,ENABLE);
ADC_StartConversion(ADC4);
}
2016-10-27 08:20 AM
Does it work with DMA2_Channel2?
Have you enabled the SYSCFG clock so the Remap works? These are wrongdmaADCInit.DMA_PeripheralDataSize = DMA_MemoryDataSize_HalfWord;
dmaADCInit.DMA_PeripheralInc = DMA_MemoryInc_Disable;2016-10-27 08:30 AM
Hi clive1
thanks for the answer . I enabled the SYSCFG CLKRCC_APB2PeriphClockCmd(RCC_APB2ENR_SYSCFGEN,ENABLE);
and i corrected the wrong lines but without effect. The DMA is still off.
2016-10-27 09:13 AM
Post complete/minimal code example that compiles, I don't have time to reconstruct this into something that is testable.
I believe I've posted examples using ADC3 and 4 together, not using the F3 so don't think I've tried ADC4+DMA in a single-up manner.Does DMA2_Channel2 work?Do you get a TC interrupt? Is the DMA flagging an error?Are you looking at the right buffer?ADC3ConvertedValue
Try not to put the ADC peripheral in the debug viewer while you use it.2016-10-28 04:49 AM
Hi
tntbc, Try to enable SYSCFG before setting the ADC2/4 DMA Remap bit in SYSCFG_CFGR1.Otherwise try the with another ADC4 input and tell us if you have the same behaviour ?-Hannibal-
2016-10-28 05:46 AM
2016-10-28 08:45 AM
ADC_DMAConfig(ADC4,ADC_DMAMode_OneShot); // Pretty sure it's not the mode you want
This is a clear and concise example, that works..// STM32 ADC4 1UP DMA TIM STM32F3-Discovery - sourcer32@gmail.com
/**************************************************************************************/
// ADC4 ADC2 ADC3 ADC4
// IN1 PA0* PA4 PB1 PE14*
// IN2 PA1 PA5* PE9* PE15*
// IN3 PA2 PA6* PE13* PB12
// IN4 PA3 PA7* --- PB14
// IN5 PF4 PC4 PB13 PB15
//
// *Used on STM32F3-Discovery
// Free pins located in STM32F3-Discovery manual, UM1570
// ADC4 Trigger EXT1 TIM2_CC3
// Pin(s) for this example PB15
/**************************************************************************************/
#include ''stm32f3_discovery.h''
#include ''stm32f30x.h''
/**************************************************************************************/
#define BUFSIZE 10
volatile uint16_t ADCConvertedValues[BUFSIZE];
uint16_t CalibrationValue;
/**************************************************************************************/
void ADC_GPIO_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
/* Enable GPIOB Periph clock */
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE);
/* ADC Channels configuration */
/* Configure PB15 as analog input */
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15;
GPIO_Init(GPIOB, &GPIO_InitStructure);
}
/**************************************************************************************/
void ADC4_DMA_Configuration(void)
{
DMA_InitTypeDef DMA_InitStructure;
/* Enable DMA2 clock */
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA2, ENABLE);
/* DMA configuration */
/* DMA2 Channel4 Init Test */
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&ADC4->DR; // The register of a singular ADC
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)&ADCConvertedValues[0];
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
DMA_InitStructure.DMA_BufferSize = BUFSIZE;
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_Medium;
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
DMA_Init(DMA2_Channel4, &DMA_InitStructure); // ADC4
}
/**************************************************************************************/
void ADC_Configuration(void)
{
ADC_InitTypeDef ADC_InitStructure;
ADC_CommonInitTypeDef ADC_CommonInitStructure;
volatile int i;
/* Configure the ADC clocks */
RCC_ADCCLKConfig(RCC_ADC34PLLCLK_Div1);
/* Enable SYSCFG for remapping */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG,ENABLE);
/* Enable ADC3/4 clocks */
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_ADC34, ENABLE);
/* Use alternate DMA mapping, so ADC4 on DMA2_Channel4 */
SYSCFG_DMAChannelRemapConfig(SYSCFG_DMARemap_ADC2ADC4,ENABLE);
/* ADC GPIO configuration */
ADC_GPIO_Configuration();
/* ADC DMA Channel configuration */
ADC4_DMA_Configuration();
/* ADC Calibration procedure */
ADC_VoltageRegulatorCmd(ADC4, ENABLE);
/* Insert delay equal to 10 µs */
for(i=0; i<10000; i++);
ADC_SelectCalibrationMode(ADC4, ADC_CalibrationMode_Single);
ADC_StartCalibration(ADC4);
while(ADC_GetCalibrationStatus(ADC4) != RESET );
CalibrationValue = ADC_GetCalibrationValue(ADC4);
/* ADC configuration */
ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent;
ADC_CommonInitStructure.ADC_Clock = ADC_Clock_AsynClkMode;
ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled; // Not Multi Mode
ADC_CommonInitStructure.ADC_DMAMode = ADC_DMAMode_Circular;
ADC_CommonInitStructure.ADC_TwoSamplingDelay = 10;
ADC_CommonInit(ADC4, &ADC_CommonInitStructure);
/* */
ADC_InitStructure.ADC_ContinuousConvMode = ADC_ContinuousConvMode_Disable; // Triggered
ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;
ADC_InitStructure.ADC_ExternalTrigConvEvent = ADC_ExternalTrigConvEvent_1; // ADC3/4 EXT1 TIM2_CC3
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 = 1;
ADC_Init(ADC4, &ADC_InitStructure);
/* ADC4 regular configuration */
ADC_RegularChannelConfig(ADC4, ADC_Channel_5, 1, ADC_SampleTime_61Cycles5); // PB15
/* Configures the ADC DMA */
ADC_DMAConfig(ADC4, ADC_DMAMode_Circular);
/* Enable the ADC DMA */
ADC_DMACmd(ADC4, ENABLE);
/* Enable ADC4 */
ADC_Cmd(ADC4, ENABLE);
/* wait for ADC4 ADRDY */
while(!ADC_GetFlagStatus(ADC4, ADC_FLAG_RDY));
/* Enable the DMA channel */
DMA_Cmd(DMA2_Channel4, ENABLE);
/* Start ADC4 Software Conversion */
ADC_StartConversion(ADC4);
}
/**************************************************************************************/
void TIM2_Configuration(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
/* Enable TIM2 Peripheral clock */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
TIM_TimeBaseStructure.TIM_Prescaler = 0;
TIM_TimeBaseStructure.TIM_Period = (SystemCoreClock / 50) - 1; // 50 Hz Sample Rate
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
/* PWM1 Mode configuration: Channel 3 (EXT1 TIM2_CC3) */
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = 10; // Some arbitary width
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OC3Init(TIM2, &TIM_OCInitStructure);
TIM_OC3PreloadConfig(TIM2, TIM_OCPreload_Enable);
TIM_Cmd(TIM2, ENABLE);
}
/**************************************************************************************/
void DMA2_Channel4_IRQHandler(void) // 5 Hz
{
/* Test on DMA2 Channel4 Transfer Complete interrupt */
if(DMA_GetITStatus(DMA2_IT_TC4))
{
/* Clear DMA2 Channel4 Half Transfer, Transfer Complete and Global interrupt pending bits */
DMA_ClearITPendingBit(DMA2_IT_GL4); // DMA2_IT_TC4 would suffice
STM_EVAL_LEDToggle(LED3); // 2.5 Hz
}
}
/**************************************************************************************/
void TIM2_IRQHandler(void) // 50 Hz
{
if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET)
{
TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
STM_EVAL_LEDToggle(LED4); // 25 Hz
}
}
/**************************************************************************************/
void NVIC_Configuration(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
/* Enable the DMA2 CH4 and TIM2 global Interrupt */
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_InitStructure.NVIC_IRQChannel = DMA2_Channel4_IRQn;
NVIC_Init(&NVIC_InitStructure);
NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
NVIC_Init(&NVIC_InitStructure);
}
/**************************************************************************************/
int main(void)
{
/* Initialize LEDs available on STM32F-Discovery board */
STM_EVAL_LEDInit(LED3);
STM_EVAL_LEDInit(LED4);
/* Turn on LD3 */
STM_EVAL_LEDOn(LED3);
STM_EVAL_LEDOn(LED4);
NVIC_Configuration();
TIM2_Configuration();
ADC_Configuration();
/* Enable DMA2 Channel4 Transfer Complete interrupt */
DMA_ITConfig(DMA2_Channel4, DMA_IT_TC, ENABLE);
/* TIM Interrupts enable */
TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
while(1); // Don't want to exit
}
/**************************************************************************************/
#ifdef USE_FULL_ASSERT
/**
* @brief Reports the name of the source file and the source line number
* where the assert_param error has occurred.
* @param file: pointer to the source file name
* @param line: assert_param error line source number
* @retval None
*/
void assert_failed(uint8_t* file, uint32_t line)
{
/* User can add his own implementation to report the file name and line number,
ex: printf(''Wrong parameters value: file %s on line %d
'', file, line) */
/* Infinite loop */
while (1)
{
}
}
#endif
/**************************************************************************************/
2016-10-28 09:17 AM
Hi tntbc,
Try always to enable the DMA before enabling the related peripheral (ADC4 in this case).Also, As you select continuous conversion for the ADC and DMA circular , it should be the ''ADC_IT_EOC'' interrput selected.-Hannibal-2016-10-28 10:48 AM
The OP is not using the ADC IRQ, the reported failure is that the DMA IRQ is not firing, ie the transfers to reach the terminal count are not occurring, or some other failure mode.
SYSCFG was identified earlier as being required to achieve the DMA channel remapping.If I was using all four ADC I'd pair them up into QUAD mode2016-10-30 03:24 AM
Hi i found the mistake,
the command DMA_ITConfig(DMA2_Channel2,DMA2_IT_TC2,ENABLE); is setting the wrong Bit in the register. I called this command incorrect. If I use DMA_ITConfig(DMA2_Channel2,DMA_IT_TC,ENABLE); then it works fine. Thanks for the help. TNTBC