cancel
Showing results for 
Search instead for 
Did you mean: 

Triple mode ADC with new HAL

b2527456
Associate II
Posted on December 02, 2014 at 01:06

Hello,

I'm trying to set the ADC(s) of the stm32f407 in triple mode, using DMA for data transfers. Based on the the only available example in the cube package and some old code, written using the stdpheriph, I wrote the following code but unfortunately it doesn't work. It never calls the DMA Interrupt service routine and the value in the ADC->CDR register stay stuck to the first conversion. Here's the code:

void
HAL_ADC_MspInit(ADC_HandleTypeDef* adc_handler)
{
GPIO_InitTypeDef gpio_init_struct;
static
DMA_HandleTypeDef dma_adc_handler;
/*
Pins timer alternate function mapping:
-----------------------
Pin ADC Channel
-----------------------
PA01 ADC1 CH1
PA02 ADC2 CH2
PA03 ADC3 CH3
*/
// Enable DMA, ADC 1,2,3 and related GPIO ports clock
__DMA2_CLK_ENABLE();
__ADC1_CLK_ENABLE();
__ADC2_CLK_ENABLE();
__ADC3_CLK_ENABLE();
__GPIOA_CLK_ENABLE();
// ADCs GPIO pin configuration
gpio_init_struct.Pin = GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3;
gpio_init_struct.Mode = GPIO_MODE_ANALOG;
gpio_init_struct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOA, &gpio_init_struct);
// ADC1 master, ADC 2,3 slaves
// DMA2 Stream0 channel0 (physically mapped to ADC1) configuration
dma_adc_handler.Instance = DMA2_Stream0;
dma_adc_handler.Init.Channel = DMA_CHANNEL_0;
dma_adc_handler.Init.Direction = DMA_PERIPH_TO_MEMORY;
dma_adc_handler.Init.PeriphInc = DMA_PINC_DISABLE;
dma_adc_handler.Init.MemInc = DMA_MINC_ENABLE;
dma_adc_handler.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
dma_adc_handler.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;
dma_adc_handler.Init.Mode = DMA_CIRCULAR;
dma_adc_handler.Init.Priority = DMA_PRIORITY_HIGH;
dma_adc_handler.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
dma_adc_handler.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_HALFFULL;
dma_adc_handler.Init.MemBurst = DMA_MBURST_SINGLE;
dma_adc_handler.Init.PeriphBurst = DMA_PBURST_SINGLE;
HAL_DMA_Init(&dma_adc_handler);
// Associate the initialized DMA handle to the the ADC handle
__HAL_LINKDMA(adc_handler, DMA_Handle, dma_adc_handler);
// NVIC configuration for DMA transfer complete interrupt
HAL_NVIC_SetPriority(DMA2_Stream0_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(DMA2_Stream0_IRQn);
}
//---------------------------------------------------------------------------------------------------------
void
Befm_Sense::init()
{
// ADC(s) configuration
adc1_handle.Instance = ADC1;
adc1_handle.Init.ClockPrescaler = ADC_CLOCKPRESCALER_PCLK_DIV2; 
//0 [1] -> max ADC clock
adc1_handle.Init.Resolution = ADC_RESOLUTION12b;
adc1_handle.Init.ScanConvMode = DISABLE;
adc1_handle.Init.ContinuousConvMode = ENABLE;
adc1_handle.Init.DiscontinuousConvMode = DISABLE;
adc1_handle.Init.NbrOfDiscConversion = 0;
adc1_handle.Init.ExternalTrigConv = ADC_EXTERNALTRIGCONVEDGE_NONE;
adc1_handle.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
// adc1_handle.Init.ExternalTrigConv = ADC_EXTERNALTRIGCONV_T1_CC1;
// adc1_handle.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_RISING;
adc1_handle.Init.DataAlign = ADC_DATAALIGN_RIGHT;
adc1_handle.Init.NbrOfConversion = 1;
adc1_handle.Init.DMAContinuousRequests = ENABLE;
adc1_handle.Init.EOCSelection = EOC_SINGLE_CONV;
adc2_handle.Instance = ADC2;
adc2_handle.Init = adc1_handle.Init;
adc3_handle.Instance = ADC3;
adc3_handle.Init = adc1_handle.Init;
if
(HAL_ADC_Init(&adc1_handle) != HAL_OK) {
info::error();
}
if
(HAL_ADC_Init(&adc2_handle) != HAL_OK) {
info::error();
}
if
(HAL_ADC_Init(&adc3_handle) != HAL_OK) {
info::error();
}
// Configure ADC1 regular channel 1
adc_config_struct.Channel = ADC_CHANNEL_1;
adc_config_struct.Rank = 1;
adc_config_struct.SamplingTime = ADC_SAMPLETIME_15CYCLES;
adc_config_struct.Offset = 0;
if
(HAL_ADC_ConfigChannel(&adc1_handle, &adc_config_struct) != HAL_OK) {
info::error();
}
// Configure ADC2 regular channel 2
adc_config_struct.Channel = ADC_CHANNEL_2;
if
(HAL_ADC_ConfigChannel(&adc2_handle, &adc_config_struct) != HAL_OK) {
info::error();
}
// Configure ADC3 regular channel 3
adc_config_struct.Channel = ADC_CHANNEL_3;
if
(HAL_ADC_ConfigChannel(&adc3_handle, &adc_config_struct) != HAL_OK) {
info::error();
}
// Configure ADC(s) in triple-mode simultaneous
adc_multimode_struct.Mode = ADC_TRIPLEMODE_REGSIMULT;
adc_multimode_struct.DMAAccessMode = ADC_DMAACCESSMODE_1;
adc_multimode_struct.TwoSamplingDelay = ADC_TWOSAMPLINGDELAY_5CYCLES;
if
(HAL_ADCEx_MultiModeConfigChannel(&adc1_handle, &adc_multimode_struct) != HAL_OK) {
info::error();
}
if
(HAL_ADCEx_MultiModeConfigChannel(&adc2_handle, &adc_multimode_struct) != HAL_OK) {
info::error();
}
if
(HAL_ADCEx_MultiModeConfigChannel(&adc3_handle, &adc_multimode_struct) != HAL_OK) {
info::error();
}
// Start ADC
// Enables ADC DMA request after last transfer (Multi-ADC mode) and enables ADC peripheral
// Only master ADC (ADC1)
if
(HAL_ADCEx_MultiModeStart_DMA(&adc1_handle, (uint32_t *)&phases_v, 3) != HAL_OK) {
info::error();
}
}
//---------------------------------------------------------------------------------------------------------
// DMA (ADC) interrupt handler
void
DMA2_Stream0_IRQHandler(
void
)
{
HAL_DMA_IRQHandler(adc1_handle.DMA_Handle);
}
void
ADC_IRQHandler(
void
)
{
HAL_ADC_IRQHandler(&adc1_handle);
}

I've done many tests but I can't figure out why it doesn't work or if it's correct due to the lack of example code. #hal-adc-dma-triplemode
10 REPLIES 10
b2527456
Associate II
Posted on December 02, 2014 at 17:20

Please, can some from ST post some working example code. I'm not asking for a solution for my specific problem, just some example code as it was available in the old stdPeriph package.

frankmeyer9
Associate II
Posted on December 02, 2014 at 17:35

Please, can some from ST post some working example code.

 

ST staff rarely did that. In fact, they play a rather passive role in this forum - except for receiving/acknowledging Cube bugs.

I'm not asking for a solution for my specific problem, just some example code as it was available in the old stdPeriph package.

 

Why not going back to the 'old' SPL, then ?

I never switched to the Cube package, realizing the number of bug reports here.

(That implies that I can't provide such an example for Cube ..)

b2527456
Associate II
Posted on December 02, 2014 at 18:11

 

Why not going back to the 'old' SPL, then ?

Because in the SPL page http://www.st.com/web/en/catalog/tools/PF257901 a *nice* image says: <<The software is superseded, for new design is recommended to take advantage of the STM32cube>>

During this summer (circa july 2014) the ''semaphore'' light at the top left of the page was red, indicating a the support was terminated. So I decided to switch to the new HAL

If you (ST) write such a message people usually understand that the deployment it's at a mature stage and ready for deployment, otherwise, typically, word like ''experimental'' or ''beta'' are used to warn the user!

Another reason is that many IDE, due by the same message, are dropping the support for the spl in favor of the new HAL

b2527456
Associate II
Posted on December 02, 2014 at 18:18

I modified the code to ''link'' only ADC1 with DMA and manually start the ADC 2 and 3 withADCx->CR2 |= (uint32_t)ADC_CR2_ADON

Still no improvements...

void
HAL_ADC_MspInit(ADC_HandleTypeDef* adc_handler)
{
if
(adc_handler->Instance != ADC1)
return
;
/****************************************************/

Posted on December 02, 2014 at 18:47

During this summer (circa july 2014) the ''semaphore'' light at the top left of the page was red, indicating a the support was terminated. So I decided to switch to the new HAL

Depends on who's ''support'' you're looking for. You're not going to get a whole bunch of vendor engineers deployed to your location unless you're Apple, or otherwise doing a crap ton of business. From ST, or anyone. It's not the 1990's anymore.

At one point they marked it NRND, but have since backed away, since anyone with a lot of parts and code isn't going to rewrite it and requalify it on a whim.

If you (ST) write such a message people usually understand that the deployment it's at a mature stage an ready for deployment, otherwise, typically, word like ''experimental'' or ''beta'' are used to warn the user!

The new code is not mature, or validated very well, some would fail a code review here.

I don't work for ST, my opinions are my own, I've worked in the semiconductor/software business for close to 30 years.

Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..
b2527456
Associate II
Posted on December 03, 2014 at 12:32

Since I've got no response I've try to follow another way using the ADC(s) independently with injected channel, and the conversion triggered by TIM1 CC4.

So, even in this case troubles... the manual UM1725, at page 97, says: Start the ADC peripheral using HAL_ADCEx_InjectedStart_DMA()

 

The problem is that there is NO such a function in the stm32f4xx_hal_adc_ex.c HAL file!

Totally nightmarish....

frankmeyer9
Associate II
Posted on December 03, 2014 at 13:01

Totally nightmarish....

 

Perhaps that's the reason why many professional/experienced users  shun the Cube software ...

chrispaulcole
Associate
Posted on December 13, 2014 at 20:57

Did you ever get this working?  I am  having the same trouble as you.

-Chris

b2527456
Associate II
Posted on December 15, 2014 at 11:55

No, as a workaround I've set the ADC(s) in ''interrupt mode'' with injected channel without using the DMA. Right now I don't enough time to mess around with the HAL lib