Hi;
I want to read 7 channel ADC value with DMA. Firstly Init ADC Settings;
void ADC_INIT(void) { //ADC_ChannelConfTypeDef sConfig; hadc.Instance = ADC1; hadc.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV1; hadc.Init.Resolution = ADC_RESOLUTION_8B; // 12 bit yap alican !!!!! hadc.Init.DataAlign = ADC_DATAALIGN_RIGHT; hadc.Init.ScanConvMode = ADC_SCAN_DIRECTION_FORWARD; /* Sequencer will convert the number of channels configured below, successively from the lowest to the highest channel number */ hadc.Init.EOCSelection = ADC_EOC_SINGLE_CONV; hadc.Init.LowPowerAutoWait = DISABLE; hadc.Init.LowPowerAutoPowerOff = DISABLE; hadc.Init.ContinuousConvMode = DISABLE; /* Continuous mode disabled to have only 1 rank converted at each conversion trig, and because discontinuous mode is enabled */ hadc.Init.DiscontinuousConvMode = ENABLE; /* Sequencer of regular group will convert the sequence in several sub-divided sequences */ hadc.Init.ExternalTrigConv = ADC_SOFTWARE_START; /* Software start to trig the 1st conversion manually, without external event */ hadc.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE; /* Parameter discarded because trig of conversion by software start (no external event) */ hadc.Init.DMAContinuousRequests = ENABLE; /* ADC-DMA continuous requests to match with DMA configured in circular mode */ hadc.Init.Overrun = ADC_OVR_DATA_OVERWRITTEN; hadc.Init.SamplingTimeCommon = ADC_SAMPLETIME_239CYCLES_5; HAL_ADC_Init(&hadc); sConfig.Rank = 0; sConfig.SamplingTime = ADC_SAMPLETIME_1CYCLE_5 ; sConfig.Channel = REF_1_5_Volt_Pin; HAL_ADC_ConfigChannel(&hadc, &sConfig); sConfig.Channel = L1_voltage_Pin; HAL_ADC_ConfigChannel(&hadc, &sConfig); sConfig.Channel = L2_voltage_Pin; HAL_ADC_ConfigChannel(&hadc, &sConfig); sConfig.Channel = L3_voltage_Pin; HAL_ADC_ConfigChannel(&hadc, &sConfig); sConfig.Channel = L1_curent_Pin; HAL_ADC_ConfigChannel(&hadc, &sConfig); sConfig.Channel = L2_curent_Pin; HAL_ADC_ConfigChannel(&hadc, &sConfig); sConfig.Channel = L3_curent_Pin; HAL_ADC_ConfigChannel(&hadc, &sConfig) } void ADC_DMA_INIT(void) { /* DMA controller clock enable */ __DMA1_CLK_ENABLE(); /* DMA interrupt init */ HAL_NVIC_SetPriority(DMA1_Channel1_IRQn, 0, 0); HAL_NVIC_EnableIRQ(DMA1_Channel1_IRQn); } void HAL_ADC_MspInit(ADC_HandleTypeDef* hadc) { if(hadc->Instance==ADC1) { GPIO_InitTypeDef GPIO_InitStruct; RCC_OscInitTypeDef RCC_OscInitStructure; /*##-1- Enable peripherals and GPIO Clocks #################################*/ /* Enable clock of GPIO associated to the peripheral channels */ __HAL_RCC_GPIOA_CLK_ENABLE(); /* Enable clock of ADCx peripheral */ __HAL_RCC_ADC1_CLK_ENABLE(); /* Note: In case of usage of asynchronous clock derived from ADC dedicated */ /* HSI RC oscillator 14MHz, with ADC setting */ /* "AdcHandle.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV1", */ /* the clock source has to be enabled at RCC top level using function */ /* "HAL_RCC_OscConfig()" (see comments in stm32l1_hal_adc.c header) */ /* Enable asynchronous clock source of ADCx */ /* (place oscillator HSI14 under control of the ADC) */ HAL_RCC_GetOscConfig(&RCC_OscInitStructure); RCC_OscInitStructure.OscillatorType = RCC_OSCILLATORTYPE_HSI14; RCC_OscInitStructure.HSI14CalibrationValue = RCC_HSI14CALIBRATION_DEFAULT; RCC_OscInitStructure.HSI14State = RCC_HSI14_ADC_CONTROL; HAL_RCC_OscConfig(&RCC_OscInitStructure); /* Enable clock of DMA associated to the peripheral */ __HAL_RCC_DMA1_CLK_ENABLE(); /*##- 2- Configure peripheral GPIO #########################*/ GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3 |GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6; GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; GPIO_InitStruct.Pull = GPIO_NOPULL; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); /*##-3- Configure the DMA ##################################################*/ /* Configure DMA parameters */ hdma_adc.Instance = DMA1_Channel1; hdma_adc.Init.Direction = DMA_PERIPH_TO_MEMORY; hdma_adc.Init.PeriphInc = DMA_PINC_DISABLE; hdma_adc.Init.MemInc = DMA_MINC_ENABLE; hdma_adc.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD; /* Transfer from ADC by half-word to match with ADC configuration: ADC resolution 10 or 12 bits */ hdma_adc.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD; /* Transfer to memory by half-word to match with buffer variable type: half-word */ hdma_adc.Init.Mode = DMA_CIRCULAR; /* DMA in circular mode to match with ADC configuration: DMA continuous requests */ hdma_adc.Init.Priority = DMA_PRIORITY_HIGH; /* Deinitialize & Initialize the DMA for new transfer */ HAL_DMA_DeInit(&hdma_adc); HAL_DMA_Init(&hdma_adc); /* Associate the initialized DMA handle to the ADC handle */ __HAL_LINKDMA(hadc, DMA_Handle, hdma_adc); } }
then i set Timer every 1 ms overflow and call interrupt
in main function : ADC init /* ADC Start with DMA */ HAL_ADC_Start_DMA(&hadc,(uint32_t *)ADC_Converted_Values,7); then i call HAL_ADC_Start(&hadc); function every 1 ms thanks to TIMER 3
This is my code but I dont see ADC value if i use 7 channel so if i use Converted_Values Buffer size is 7 i dont measure ADC value and system is lock. but i set 4 channel i measure value.
what can i measure 7 channel with DMA
Thanks all of things Alican
Need to enumerate Rank 1 thru 7
Here is my simple example that's stolen from the ST-Examples and modified to be an example for you. I had tested them on an STM32F407 disco-board. If you are interessting in the hole project let me know it. I ha replaced the declaration __IO with volatile for my better unterstanding this means.
#define NumADCChan 8 volatile uint16_t ADValue[NumADCChan+2]= {0xAAAA,0,0,0,0,0,0,0,0,0xEEEE}; // DMA-Buffer
/* ADC1 init function */ void MX_ADC1_Init (void) { ADC_ChannelConfTypeDef sConfig;
__HAL_RCC_ADC1_CLK_ENABLE(); // ADC1 Periph clock enable __HAL_RCC_DMA2_CLK_ENABLE(); // Enable DMA2 clock
/**Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion) */ hadc1.Instance = ADC1; hadc1.Init.ClockPrescaler = ADC_CLOCKPRESCALER_PCLK_DIV8; hadc1.Init.Resolution = ADC_RESOLUTION_12B; hadc1.Init.NbrOfConversion = NumADCChan; // Anzahl der ADC-Kanäle hadc1.Init.ScanConvMode = ENABLE; hadc1.Init.ContinuousConvMode = ENABLE; hadc1.Init.DiscontinuousConvMode = DISABLE; hadc1.Init.NbrOfDiscConversion = 0; hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE; hadc1.Init.ExternalTrigConv = ADC_EXTERNALTRIGCONV_T1_CC1; // just 0; hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT; // Daten werden rechtsbündig ausgelesen hadc1.Init.DMAContinuousRequests = ENABLE; hadc1.Init.EOCSelection = DISABLE;
HAL_ADC_Init (&hadc1);
// ##############################################################################################
sConfig.SamplingTime = ADC_SAMPLETIME_480CYCLES; sConfig.Channel = ADC_CHANNEL_1; // The channel your scan sConfig.Rank = 1; // the order of value in the dma-buffer array HAL_ADC_ConfigChannel (&hadc1, &sConfig);
sConfig.Channel = ADC_CHANNEL_2; sConfig.Rank = 2; HAL_ADC_ConfigChannel (&hadc1, &sConfig);
sConfig.Channel = ADC_CHANNEL_6; sConfig.Rank = 3; HAL_ADC_ConfigChannel (&hadc1, &sConfig);
sConfig.Channel = ADC_CHANNEL_4; sConfig.Rank = 4; HAL_ADC_ConfigChannel (&hadc1, &sConfig);
sConfig.Channel = ADC_CHANNEL_3; sConfig.Rank = 5; HAL_ADC_ConfigChannel (&hadc1, &sConfig);
sConfig.Channel = ADC_CHANNEL_5; sConfig.Rank = 6; HAL_ADC_ConfigChannel (&hadc1, &sConfig);
sConfig.Channel = ADC_CHANNEL_8; sConfig.Rank = 7; HAL_ADC_ConfigChannel (&hadc1, &sConfig);
sConfig.Channel = ADC_CHANNEL_7; sConfig.Rank = 8; HAL_ADC_ConfigChannel (&hadc1, &sConfig);
// ########### and now starts DMA HAL_ADC_Start_DMA (&hadc1, (uint32_t *) &ADValue[1], NumADCChan ); // 8 channels
###################################################################################
A discussion if this maybe right or wrong declared should done with the engineers of ST, who hat written the reference code and the HAL lib's itself. This works and is stable.
Sorry that the code looks not pretty nice after posting them.
Yeah, you should read posting instruction immediately above box you are typing into. Use the PRE tags, it look better.
I was in rush, but would like to send an answer before i left. Yepp, i aggree, it looks horrible. Nobody would see like this.
And i had watched your example one more time and found, that the rank assigning of each channel is missing.
sConfig.Rank = 1; sConfig.SamplingTime = ADC_SAMPLETIME_1CYCLE_5 ; sConfig.Channel = REF_1_5_Volt_Pin; HAL_ADC_ConfigChannel(&hadc, &sConfig); sConfig.Rank = 2; sConfig.Channel = L1_voltage_Pin; HAL_ADC_ConfigChannel(&hadc, &sConfig); sConfig.Rank = 3; sConfig.Channel = L2_voltage_Pin; HAL_ADC_ConfigChannel(&hadc, &sConfig); sConfig.Rank = 4; sConfig.Channel = L3_voltage_Pin; HAL_ADC_ConfigChannel(&hadc, &sConfig); sConfig.Rank = 5; sConfig.Channel = L1_curent_Pin; HAL_ADC_ConfigChannel(&hadc, &sConfig); sConfig.Rank = 6; sConfig.Channel = L2_curent_Pin; HAL_ADC_ConfigChannel(&hadc, &sConfig); sConfig.Rank = 7 sConfig.Channel = L3_curent_Pin; HAL_ADC_ConfigChannel(&hadc, &sConfig)
I am not sure but i believe that rank could not be 0.
Hi thx All right . if Adjust DMA ( DMA_PDATAALIGN_WORD) :
hdma_adc.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD; hdma_adc.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;
then used uint32_t: volatile uint32_t AdcDmaBuf[NumADCChan]
also if Adjust DMA ( DMA_PDATAALIGN_HALFWORD ) :
hdma_adc.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD; /* Transfer from ADC by half-word to match with ADC configuration: ADC resolution 10 or 12 bits */
hdma_adc.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD; /* Transfer to memory by half-word to match with buffer variable type: half-word */
then used uint16_t : volatile uint16_t AdcDmaBuf[NumADCChan]
best regards