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
You doing wrong in declaring the dma buffer variable. You need to send the start address of the dma buffer. HAL_ADC_Start_DMA(&hadc,(uint32_t *)ADC_Converted_Values,7);
You shoud do like this: HAL_ADC_Start_DMA(&hadc,(uint32_t *)&ADC_Converted_Values,7);
Well, the adc values are limited to 8bit and the dma buffer is declared uint32_t. This could not work properly.
In regular curcumstance, i use an array that was extend by two more element - the first and last element of the array is filled by a predefined value like "0xAA" and "0xBB". If the elements where overwritten by dma, something went wrong an could be detected by a simple compare statement.
example: // Regular mode
#define NumOfAdcChan 7 // num of scanned ADC channels #define DMABUFSIZE NumOfAdcChan + 2 // total elements of DMABuf-Array volatile uint16_t AdcDmaBuf[DMABUFSIZE] = {0xAA, 0, 0, 0, 0, 0, 0xBB}; ...
HAL_ADC_Start_DMA(&hadc,(uint32_t *)&AdcDmaBuf[1], NumOfAdcChan );
I had started to use HAL since a couple of weeks and used stdlib previously. The structures and the handling of the HAL are different compare by the StdLib, but this are more extended and covers more mcu variants. It's just a different api, not less not more.
Hope this helps anyone.
Need to enumerate Rank 1 thru 7
Actually, it's you who's wrong there. As long as that variable has the correct type to begin with, it makes no difference at all whether you put a '&' operator in there or not. Actually, the version without the '&' would be closer to correct.
There is something else wrong with that line, though. The pointer cast should never be necessary, i.e. the following should work:
HAL_ADC_Start_DMA(&hadc, ADC_Converted_Values, 7);
This, OTOH:
volatile uint16_t AdcDmaBuf[DMABUFSIZE] = {0xAA, 0, 0, 0, 0, 0, 0xBB}; ... HAL_ADC_Start_DMA(&hadc,(uint32_t *)&AdcDmaBuf[1], NumOfAdcChan );
is really very wrong. You've now created a misaligned 32-bit pointer and passed that to a function. If that doesn't crash and burn right away, that would indicate the type of that function's argument is wildly incorrect.
Thats entire wrong you wrote. I had used the example of ST to explain the usage. The declaration is ok and common used by every code had seen. In addition, i don't wanna discuss this further because this does'nt helps to solve the question of the thread opener.
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.
Thats entire wrong you wrote.
You have no idea what you're talking about.
i don't wanna discuss this further
So you say, then you go on by discussing it further in another posting.
Yeah, you should read posting instruction immediately above box you are typing into. Use the PRE tags, it look better.
HAL_ADC_Start_DMA (&hadc1, ADValue[1], NumADCChan);
Src\MspInit\ADC\adc.c|65|warning: passing argument 2 of 'HAL_ADC_Start_DMA' makes pointer from integer without a cast | .\drivers\stm32f4xx_hal_driver\inc\stm32f4xx_hal_adc.h|551|note: expected 'uint32_t *' but argument is of type 'uint16_t'|
That's the compiler answer of Your IDEA. I am deep impressed you are talking about.
Your statement passed a variable containment instead the address that pointed to the second element of an 16bit uint array, that i had declared before. The second element contains "0" and that's the address that DMA assumed as destination. The array is an uint16_t typ with n-elements, not a pointer to an uint32_t variable. The ADC channel is declared as half-word, not word.
And, where is YOUR SOLUTION of the thread opener???? This discussion does'nt help's him to solve his question.
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.
That's the compiler answer of Your IDEA.
No, it's not. I never wrote anything about passing
ADValue[1]
to that function. How about you try to get your facts straight at least once in a while?
I am deep impressed you are talking about.
Maybe you should be. But you're clearly not, most likely because you don't even know enough C to be able to understand what the difference is between what I actually wrote, and what you made of it.
Your statement passed a variable containment instead the address that pointed to the second element of an 16bit uint array, that i had declared before.
No, it didn't, for two reason.
1) My statement was made before you introduced an artifically offset array into the mix. I.e. nobody had said anything about offsetting the array bounds to include guard elements, at that time.
2) No, my code snippet does not pass a "containment" (whatever that's supposed to be). It uses the name of the array. If you knew what you're talking about, you would have heard that in C, in this kind of usage, an array name is exactly equivalent to a pointer to the first element of that array.
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