STM32F4 ADC DMA - ADC1 working, but not ADC3 !?!?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2016-09-15 11:55 AM
I'm trying to get 4 total ADC channels up and running using ADC. One of them is measuring the internal temperature sensor, and the other 3 are measuring external voltages.
Here are the pin's I'm using for each ADC line: #1: ADC1/Temp Sensor (Internal) #2: ADC1/IN4 (PA4) #3: ADC3/IN9 (PF3) #4: ADC3/IN14 (PF4) I can successfully read both channels from ADC1, but the 2 channels from ADC3 are always coming in as zeroes. I have all 3 external channels tied to 3.3V, so they should all be reading as 4095, but only the channel on ADC1 is. I believe I have the correct DMA channels and streams setup. Is there anything obvious I'm overlooking? Thank you! Code:#include ''adc.h''
#include ''stm32f4xx_hal.h''
/* Local Variables -----------------------------------------------------------*/
#define ADC_NUM_SAMPLES 128
/* Global Variables ----------------------------------------------------------*/
ADC_HandleTypeDef hadc1;
ADC_HandleTypeDef hadc3;
DMA_HandleTypeDef hdma_adc1;
DMA_HandleTypeDef hdma_adc3;
uint32_t ADC_buffer1[ADC_NUM_SAMPLES];
uint32_t ADC_buffer2[ADC_NUM_SAMPLES];
/* Global Functions ----------------------------------------------------------*/
/* ADC1 init function */
void MX_ADC1_Init(void)
{
ADC_ChannelConfTypeDef sConfig;
// Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion)
hadc1.Instance = ADC1;
hadc1.Init.ClockPrescaler = ADC_CLOCKPRESCALER_PCLK_DIV4;
hadc1.Init.Resolution = ADC_RESOLUTION_12B;
hadc1.Init.ScanConvMode = ENABLE;
hadc1.Init.ContinuousConvMode = ENABLE;
hadc1.Init.DiscontinuousConvMode = DISABLE;
hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
hadc1.Init.ExternalTrigConv = 0;
hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
hadc1.Init.NbrOfConversion = 2;
hadc1.Init.DMAContinuousRequests = ENABLE;
hadc1.Init.EOCSelection = EOC_SINGLE_CONV;
HAL_ADC_Init(&hadc1);
// Configure Internal Temp Sensor Channel
sConfig.Channel = ADC_CHANNEL_TEMPSENSOR;
sConfig.Rank = 1;
sConfig.SamplingTime = ADC_SAMPLETIME_144CYCLES;
HAL_ADC_ConfigChannel(&hadc1, &sConfig);
// Configure External Temp Sensor Channel
sConfig.Channel = ADC_CHANNEL_4;
sConfig.Rank = 2;
sConfig.SamplingTime = ADC_SAMPLETIME_144CYCLES;
HAL_ADC_ConfigChannel(&hadc1, &sConfig);
HAL_ADC_Start_DMA(&hadc1, (uint32_t*)ADC_buffer1, ADC_NUM_SAMPLES);
}
/* ADC1 init function */
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_CLOCKPRESCALER_PCLK_DIV4;
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 = 0;
hadc3.Init.DataAlign = ADC_DATAALIGN_RIGHT;
hadc3.Init.NbrOfConversion = 2;
hadc3.Init.DMAContinuousRequests = ENABLE;
hadc3.Init.EOCSelection = EOC_SINGLE_CONV;
HAL_ADC_Init(&hadc3);
// Configure Internal Temp Sensor Channel
sConfig.Channel = ADC_CHANNEL_9;
sConfig.Rank = 1;
sConfig.SamplingTime = ADC_SAMPLETIME_144CYCLES;
HAL_ADC_ConfigChannel(&hadc3, &sConfig);
// Configure External Temp Sensor Channel
sConfig.Channel = ADC_CHANNEL_14;
sConfig.Rank = 2;
sConfig.SamplingTime = ADC_SAMPLETIME_144CYCLES;
HAL_ADC_ConfigChannel(&hadc3, &sConfig);
HAL_ADC_Start_DMA(&hadc3, (uint32_t*)ADC_buffer2, ADC_NUM_SAMPLES);
}
void HAL_ADC_MspInit(ADC_HandleTypeDef* hadc)
{
GPIO_InitTypeDef GPIO_InitStruct;
if(hadc->Instance==ADC1)
{
/* Peripheral clock enable */
__ADC1_CLK_ENABLE();
/**ADC1 GPIO Configuration
PA4 ------> ADC1_IN4
*/
GPIO_InitStruct.Pin = GPIO_PIN_4;
GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/* Peripheral DMA init*/
hdma_adc1.Instance = DMA2_Stream0;
hdma_adc1.Init.Channel = DMA_CHANNEL_0;
hdma_adc1.Init.Direction = DMA_PERIPH_TO_MEMORY;
hdma_adc1.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_adc1.Init.MemInc = DMA_MINC_ENABLE;
hdma_adc1.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
hdma_adc1.Init.MemDataAlignment = DMA_PDATAALIGN_WORD;
hdma_adc1.Init.Mode = DMA_CIRCULAR;
hdma_adc1.Init.Priority = DMA_PRIORITY_LOW;
hdma_adc1.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
HAL_DMA_Init(&hdma_adc1);
__HAL_LINKDMA(hadc,DMA_Handle,hdma_adc1);
}
else if(hadc->Instance==ADC3)
{
/* Peripheral clock enable */
__ADC3_CLK_ENABLE();
/**ADC3 GPIO Configuration
PF3 ------> ADC3_IN9
PF4 ------> ADC3_IN14
*/
GPIO_InitStruct.Pin = GPIO_PIN_3|GPIO_PIN_4;
GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOF, &GPIO_InitStruct);
/* Peripheral DMA init*/
hdma_adc3.Instance = DMA2_Stream1;
hdma_adc3.Init.Channel = DMA_CHANNEL_2;
hdma_adc3.Init.Direction = DMA_PERIPH_TO_MEMORY;
hdma_adc3.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_adc3.Init.MemInc = DMA_MINC_ENABLE;
hdma_adc3.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
hdma_adc3.Init.MemDataAlignment = DMA_PDATAALIGN_WORD;
hdma_adc3.Init.Mode = DMA_CIRCULAR;
hdma_adc3.Init.Priority = DMA_PRIORITY_LOW;
hdma_adc3.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
HAL_DMA_Init(&hdma_adc3);
__HAL_LINKDMA(hadc,DMA_Handle,hdma_adc3);
}
}
void HAL_ADC_MspDeInit(ADC_HandleTypeDef* hadc)
{
if(hadc->Instance==ADC1)
{
/* Peripheral clock disable */
__ADC1_CLK_DISABLE();
/**ADC1 GPIO Configuration
PA4 ------> ADC1_IN4
*/
HAL_GPIO_DeInit(GPIOA, GPIO_PIN_4);
/* Peripheral DMA DeInit*/
HAL_DMA_DeInit(hadc->DMA_Handle);
/* Peripheral interrupt DeInit*/
//HAL_NVIC_DisableIRQ(ADC_IRQn);
}
else if(hadc->Instance==ADC3)
{
/* Peripheral clock disable */
__ADC3_CLK_DISABLE();
/**ADC3 GPIO Configuration
PF3 ------> ADC3_IN9
PF4 ------> ADC3_IN14
*/
HAL_GPIO_DeInit(GPIOF, GPIO_PIN_3|GPIO_PIN_4);
/* Peripheral DMA DeInit*/
HAL_DMA_DeInit(hadc->DMA_Handle);
/* Peripheral interrupt DeInit*/
//HAL_NVIC_DisableIRQ(ADC_IRQn);
}
}
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* AdcHandle)
{
uint8_t i;
uint32_t sum1, sum2;
sum1=sum2=0;
if (AdcHandle->Instance == ADC1)
{
for (i=0; i<
ADC_NUM_SAMPLES
; i+=2)
{
sum1 += ADC_buffer1[i];
sum2 += ADC_buffer1[i+1];
}
sum1 /= (ADC_NUM_SAMPLES/2);
sum2 /= (ADC_NUM_SAMPLES/2);
}
else if (AdcHandle->Instance == ADC3)
{
for (i=0; i<ADC_NUM_SAMPLES; i+=2)
{
sum1 += ADC_buffer2[i];
sum2 += ADC_buffer2[i+1];
}
sum1 /= (ADC_NUM_SAMPLES/2);
sum2 /= (ADC_NUM_SAMPLES/2);
}
}
/**
* Enable DMA controller clock
*/
void MX_DMA_Init(void)
{
/* DMA controller clock enable */
__DMA2_CLK_ENABLE();
/* DMA interrupt init */
HAL_NVIC_SetPriority(DMA2_Stream0_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(DMA2_Stream0_IRQn);
HAL_NVIC_SetPriority(DMA2_Stream1_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(DMA2_Stream1_IRQn);
}
/**
* @brief This function handles DMA2 stream0 global interrupt.
*/
void DMA2_Stream0_IRQHandler(void)
{
HAL_DMA_IRQHandler(&hdma_adc1);
}
/**
* @brief This function handles DMA2 stream1 global interrupt.
*/
void DMA2_Stream1_IRQHandler(void)
{
HAL_DMA_IRQHandler(&hdma_adc3);
}
Here is what I call on powerup as well:
MX_DMA_Init();
MX_ADC1_Init();
MX_ADC3_Init();
#dogfooding #no-hablo-hal #!stm32-!dma-!adc
- Labels:
-
STM32Cube MCU Packages
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2016-09-19 7:14 AM
So I've tried setting up only ADC3, and not ADC1, and there is no change. I feel like there is something missing in the setup for ADC3 and the DMA2 stream/channel.
Any pointers on where to look?Thank you!- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2016-09-19 8:19 AM
Seems to be reasonable enough, I'm not using HAL, but at this point I'd probably dig into the library/registers, confirm the common portion of the ADC is set correctly, and the DMA from alternate sources is supported properly.
Up vote any posts that you find helpful, it shows what's working..
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2016-10-04 2:10 PM
Giving this a quick bump to see if anyone has any suggestions/advice.
ADC1 works great, so I don't see why ADC3 is having issues. The only difference is the DMA2 using a different channel & stream.Thanks!- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2016-10-05 7:48 AM
It's now working! I needed to enable the specific port clock:
else
if (hadc->Instance==ADC3) { /* Peripheral clock enable */ __GPIOF_CLK_ENABLE(); __ADC3_CLK_ENABLE(); I had already enabled the port clock used by ADC1 elsewhere in the code, which is why that was working correctly.