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.
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.
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.
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.
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.