AnsweredAssumed Answered

STM32L071 ADC + DMA + Multichannels Problems

Question asked by B3rsui on May 25, 2018
Latest reply on May 25, 2018 by T J

Hi all,

 

I am working with a custum made PCB which has a STM32L071 micro and I am facing some troubles to read multiple adc inputs via DMA (because HAL IT dondoesn't work because ADC interrupts faster than ISR can excecute).

 

The think is the output from the DMA is beyond 4096 values. I'd tried a lot of combinations in config without luck. I want to use HSE with 8MHz crystal PLL to 32MHz.

General struct


#pragma pack(push, 1)

typedef struct {

uint16_t PresionAire;
uint16_t SensorHumo;
uint16_t CAL_IS1;
uint16_t CAL_IS2;
uint16_t CAL_HUMO;
uint16_t CAL_AIRE;
uint16_t I_Extractor;
uint16_t I_Compresor;

} Sensores;


typedef struct {

uint16_t Systick;

uint16_t EstadoEntradas;

uint8_t ExtractorEncendido;

uint8_t CompresorEncendido;
uint16_t CompresorHabilitado; // Variable de tiempo para apagar el compresor

uint8_t Error;

uint16_t ConversorADC[8];
Sensores Analog;

} General;

#pragma pack(pop)

 

__IO General Gen;

 

 

int main(void){

memset((General *) &Gen, 0x00, sizeof(Gen));

HAL_Init();

Setup();

 

while (1){


LecturaADCs((General *) &Gen);
}
}

void Setup(void){

ConfiguroOscilador();

HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);

SysTick_Config(SystemCoreClock/1000);

ConfiguroIOs();

ConfiguroADC();
}

 

void ConfiguroOscilador(void){

 

 

RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
RCC_OscInitTypeDef RCC_OscInitStruct = {0};

/* -2- Enable HSE Oscillator, select it as PLL source and finally activate the PLL */
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.LSEState = RCC_LSE_OFF;
RCC_OscInitStruct.HSIState = RCC_HSI_OFF;
RCC_OscInitStruct.LSIState = RCC_LSI_OFF;

RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL8;
RCC_OscInitStruct.PLL.PLLDIV = RCC_PLL_DIV2;

if (HAL_RCC_OscConfig(&RCC_OscInitStruct)!= HAL_OK){

while(1);
}

/* -3- Select the PLL as system clock source and configure the HCLK, PCLK1 and PCLK2 clocks dividers */
RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2);
RCC_ClkInitStruct.SYSCLKSource = RCC_CFGR_SW_PLL;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;


if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1) != HAL_OK){
/* Initialization Error */
while(1);
}

__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
__HAL_RCC_GPIOC_CLK_ENABLE();
__HAL_RCC_ADC1_CLK_ENABLE();

}


void ConfiguroIOs(void){

 

 

GPIO_InitTypeDef GPIO_InitStruct;

 

 

__HAL_RCC_ADC1_CLK_ENABLE();

 

 

//********* GPIOA
GPIO_InitStruct.Pin = PIN_SENSOR_PRESION | PIN_SENSOR_HUMO | PIN_CAL_IS1 | PIN_CAL_IS2 | PIN_CAL_HUMO | PIN_CAL_AIRE;
GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

GPIO_InitStruct.Pin = PIN_I_EXTRACTOR | PIN_I_COMPRESOR;
GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

 

}

 

void HAL_ADC_MspInit(ADC_HandleTypeDef* hadc){

 

 

static DMA_HandleTypeDef DmaHandle;

__HAL_RCC_DMA1_CLK_ENABLE();

DmaHandle.Instance = DMA1_Channel1;
DmaHandle.Init.Direction = DMA_PERIPH_TO_MEMORY;
DmaHandle.Init.PeriphInc = DMA_PINC_DISABLE;
DmaHandle.Init.MemInc = DMA_MINC_ENABLE;
DmaHandle.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
DmaHandle.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
DmaHandle.Init.Mode = DMA_NORMAL;
DmaHandle.Init.Priority = DMA_PRIORITY_VERY_HIGH;
DmaHandle.Init.Request = DMA_REQUEST_0;

HAL_DMA_Init(&DmaHandle);

 

 

/* Associate the DMA handle */
__HAL_LINKDMA(&AdcHandle, DMA_Handle, DmaHandle);

 

 

/* NVIC configuration for DMA Input data interrupt */
HAL_NVIC_SetPriority(DMA1_Channel1_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(DMA1_Channel1_IRQn);
}

 

void ConfiguroADC(void){


AdcHandle.Instance = ADC1;

 

 

if (HAL_ADC_DeInit(&AdcHandle) != HAL_OK){

HAL_Delay(100);
}

AdcHandle.Init.OversamplingMode = DISABLE;

AdcHandle.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV1;
AdcHandle.Init.LowPowerAutoPowerOff = DISABLE;
AdcHandle.Init.LowPowerFrequencyMode = DISABLE;
AdcHandle.Init.LowPowerAutoWait = DISABLE;

AdcHandle.Init.Resolution = ADC_RESOLUTION_12B;
AdcHandle.Init.SamplingTime = ADC_SAMPLETIME_12CYCLES_5;
AdcHandle.Init.ScanConvMode = ADC_SCAN_DIRECTION_FORWARD;
AdcHandle.Init.DataAlign = ADC_DATAALIGN_RIGHT;
AdcHandle.Init.ContinuousConvMode = ENABLE;
AdcHandle.Init.DiscontinuousConvMode = DISABLE;
AdcHandle.Init.ExternalTrigConv = ADC_SOFTWARE_START;
AdcHandle.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
AdcHandle.Init.EOCSelection = ADC_EOC_SINGLE_SEQ_CONV;
AdcHandle.Init.DMAContinuousRequests = ENABLE;


if (HAL_ADC_Init(&AdcHandle) != HAL_OK){

HAL_Delay(100);
}


if (HAL_ADCEx_Calibration_Start(&AdcHandle, ADC_SINGLE_ENDED) != HAL_OK){

HAL_Delay(100);
}


sConfig.Channel = (ADC_CHANNEL_2 | ADC_CHANNEL_3 | ADC_CHANNEL_4 | ADC_CHANNEL_5 | ADC_CHANNEL_6 | ADC_CHANNEL_7 | ADC_CHANNEL_8 | ADC_CHANNEL_9);

 

 

if (HAL_ADC_ConfigChannel(&AdcHandle, &sConfig) != HAL_OK){

HAL_Delay(100);
}


if(HAL_ADC_Start_DMA(&AdcHandle, (uint32_t *) Gen.ConversorADC, 8) != HAL_OK){

HAL_Delay(100);
}
}

void LecturaADCs(General *Genb){

 

 

if (!(Gen.ConversorADC[0] & 0x8000)) // Si el bit mas significativo esta en 1 hay dato
return; // Sino me voy

 

 

Gen.ConversorADC[0] &= 0x7FFF; // Borro flag de conversion disponible

memcpy(&Gen.Analog, Gen.ConversorADC, sizeof(Sensores));
memset(Gen.ConversorADC, 0x00, sizeof(Gen.ConversorADC));

 

 

if(HAL_ADC_Start_DMA(&AdcHandle, (uint32_t *) Gen.ConversorADC, 8) != HAL_OK){

HAL_Delay(100);
NVIC_SystemReset();
}
}


void DMA1_Channel1_IRQHandler(void){

 

 

HAL_DMA_IRQHandler(AdcHandle.DMA_Handle);
}

 

 

void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* AdcHandle){

 

 

HAL_ADC_Stop_DMA(AdcHandle);
Gen.ConversorADC[0] |= 0x8000;
}


The values given by the DMA are out of ranges and oscillates on each conversion.

 

Hope someone can help me.

 

Best regards,

 

Bruno

Outcomes