2017-04-02 09:19 AM
Hi all,
I am developing an application with my STM32F746G-Discovery board; for this application I need to acquire 4 to 6 analog signals from external sensors.
My application uses the Arduino UNO headers on the back of the discovery board to interface with a motor driver shield by Pololu; I was already able to generate the logic and PWM signals to control the motor status, direction and rotation speed by means of an LCD GUI.Now I need to acquire some analog signals from external sensors, possibly using DMA to transfer ADC samples in memory.Until now I was able to initialize the ADC and DMA using STM32CubeMX, defining the needed ADC3 channels, associated ranks, working mode and so on.This is the MX_ADC3_Init function generated by STM32CubeMX:
/* ADC3 init function */
static void MX_ADC3_Init(void){ADC_ChannelConfTypeDef sConfig;
/**Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion)
*/ hadc3.Instance = ADC3; hadc3.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV8; hadc3.Init.Resolution = ADC_RESOLUTION_12B; hadc3.Init.ScanConvMode = ENABLE; hadc3.Init.ContinuousConvMode = ENABLE; hadc3.Init.DiscontinuousConvMode = DISABLE; hadc3.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE; hadc3.Init.ExternalTrigConv = ADC_SOFTWARE_START; hadc3.Init.DataAlign = ADC_DATAALIGN_RIGHT; hadc3.Init.NbrOfConversion = 2; hadc3.Init.DMAContinuousRequests = ENABLE; hadc3.Init.EOCSelection = ADC_EOC_SEQ_CONV; if (HAL_ADC_Init(&hadc3) != HAL_OK) { Error_Handler(); }/**Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.
*/ sConfig.Channel = ADC_CHANNEL_0; sConfig.Rank = 1; sConfig.SamplingTime = ADC_SAMPLETIME_480CYCLES; if (HAL_ADC_ConfigChannel(&hadc3, &sConfig) != HAL_OK) { Error_Handler(); }/**Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.
*/ sConfig.Channel = ADC_CHANNEL_7; sConfig.Rank = 2; if (HAL_ADC_ConfigChannel(&hadc3, &sConfig) != HAL_OK) { Error_Handler(); }}
and this is the DMA Init function:
/**
* Enable DMA controller clock */static void MX_DMA_Init(void) { /* DMA controller clock enable */ __HAL_RCC_DMA2_CLK_ENABLE();/* DMA interrupt init */
/* DMA2_Stream0_IRQn interrupt configuration */ HAL_NVIC_SetPriority(DMA2_Stream0_IRQn, 0, 0); HAL_NVIC_EnableIRQ(DMA2_Stream0_IRQn);}Using this template code and following some online demos I was able to intercept the single ADC channel conversion complete interrupt but I would like to define a DMA Transfer Complete Callback function to scale all sensors readings using a single function; however I can't figure out how to do this.
I tried to define a custom XferCpltCallback function with this prototype
void myADC_DMA_XferCpltCallback(DMA_HandleTypeDef* hdma_adc)
{ // ADC readings scaling code}
and pointing to it inserting this code after the MX_DMA_init() call:
if (HAL_DMA_RegisterCallback(&hdma_adc3, HAL_DMA_XFER_CPLT_CB_ID, myDMA_XferCpltCallback) != HAL_OK)
return 0;and then starting the DMA with:
if (HAL_ADC_Start_DMA(&hadc3, (uint32_t*) ADC_BUF, 2) != HAL_OK)
return 0;before the infinite loop in the main function.
Debugging the code I can see that both functions return HAL_OK, so I can guess that the callback is correctly registered and that the DMA starts without errors.
However if I put an interrupt at the beginning of the callback function I can see that it is never called and that the ADC samples buffer (ADC_BUF) is never updated.
Can anyone of you give me some hint on how I should define this callback and how I should point to it?
Thanks in advance for any help.
#dma #adc #sdram #multichannel #stm32f746g-discoverySolved! Go to Solution.
2017-04-05 02:31 AM
OK, after a long debug activity, I found the solution by myself: the problem was caused by the initialization of the external SDRAM bank of the STM32F746G-DISCO by the BSP_SDRAM_Init() function that in my original code was called after the initialization of the DMA with MX_DMA_Init() function.
The external SDRAM is requested by the CMSIS RTOS to manage the GUI on the LCD; with a step-by-step execution I noted that the configuration of DMA2 used to take samples from ADC3 in my application was completely modified after the call to BSP_SDRAM_Init().Exchanging the relative positions of calls of MX_DMA_Init() and BSP_SDRAM_Init() in the main function solved the problem.
2017-04-05 02:31 AM
OK, after a long debug activity, I found the solution by myself: the problem was caused by the initialization of the external SDRAM bank of the STM32F746G-DISCO by the BSP_SDRAM_Init() function that in my original code was called after the initialization of the DMA with MX_DMA_Init() function.
The external SDRAM is requested by the CMSIS RTOS to manage the GUI on the LCD; with a step-by-step execution I noted that the configuration of DMA2 used to take samples from ADC3 in my application was completely modified after the call to BSP_SDRAM_Init().Exchanging the relative positions of calls of MX_DMA_Init() and BSP_SDRAM_Init() in the main function solved the problem.