Skip to main content
Visitor II
March 19, 2024
Solved

ADC in conjustion with DMA

  • March 19, 2024
  • 4 replies
  • 3968 views

Hi

I am facing an odd problem with ADC in conjunction with DMA on STM32L151V8T-A. 

I can see that it measures all three channels. However, the result of each channel is stored in the first element of my results array (Result[3]). 

Every time that the callback function is called the results of one out of three channels is stored in Result[0] element. It is as if the memory address is not increasing.

Can somebody help?

    This topic has been closed for replies.
    Best answer by mƎALLEm

    I attached a project where I did 3 channels conversion in continuous mode with DMA on STM32L152D_EVAL board. Unfortunately, I don't have your board on hands.

    The three converted channels are:

    - Channel 31: potentiometer

    - Channel 16: temperature sensor

    - Channel 17: Vrefint

    I tested the project with IAR, you can port it easily to CubeIDE with CubeMx.

    As you can see in this screenshot, the data converted are arranged in the correct order.

    SofLit_0-1711122362478.png

    You can inspire from my project to find your issue.

    Please select this answer if it does answer your question.

     

    4 replies

    ST Employee
    March 19, 2024

    Hello @Pejwaak,

    Please, make sure in your DMA settings you have correctly enable the incrementing address of "Destination Address".

    Feel free to share your settings :)

    Kind Regards,

    Gwénolé

    PejwaakAuthor
    Visitor II
    March 19, 2024

    Hi

    Thanks for getting to me. I am not writing the low level code. I am using HAL library and I assumed as long as I follow the working examples. It should do the same thing although this is a different STM32 microcontroller.

    Here is the part of the code that runs it. I also use the call back function to sent the ADCFlag.

    HAL_ADC_Start_DMA(&hadc, ADCArray, 3);
     HAL_TIM_Base_Start_IT(&htim2);
     /* USER CODE END 2 */
    
     /* Infinite loop */
     /* USER CODE BEGIN WHILE */
     while (1)
     {
     /* USER CODE END WHILE */
    
     /* USER CODE BEGIN 3 */
     if(ADCFlag){
     ADCStat = HAL_ADC_GetState(&hadc);
     if(ADCStat == 0){
     ADCFlag = 0;
     HAL_ADC_Start_DMA(&hadc, ADCArray, 3);
     }
     
    Technical Moderator
    March 19, 2024

    Hello,

    Did you enable Scan mode?

    SofLit_0-1710862082364.png

    Did you enable Memory incrementation in DMA config as stated by @GwenoleB ?

    SofLit_1-1710862158687.png

     

    PejwaakAuthor
    Visitor II
    March 19, 2024

    Hi

    Yes, I have taken every standard step according to the examples. Like I said all channels are being sampled but at the end of the sequence only one channel is written to ACDArray[0] and the rest remain zero. then at then end of next sequence the values for another channel is written two ACDArray[0] and the rest remain zero. It is really odd. 

    PejwaakAuthor
    Visitor II
    March 19, 2024

    Hi

    Thanks it is a lo of line. I am going to put the relevant bits here. Hopefully it will work.

    static void MX_ADC_Init(void)
    {
    
    /* USER CODE BEGIN ADC_Init 0 */
    
    /* USER CODE END ADC_Init 0 */
    
    ADC_ChannelConfTypeDef sConfig = {0};
    
    /* USER CODE BEGIN ADC_Init 1 */
    
    /* USER CODE END ADC_Init 1 */
    /** Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion)
    */
    hadc.Instance = ADC1;
    hadc.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV4;
    hadc.Init.Resolution = ADC_RESOLUTION_10B;
    hadc.Init.DataAlign = ADC_DATAALIGN_RIGHT;
    hadc.Init.ScanConvMode = ADC_SCAN_ENABLE;
    hadc.Init.EOCSelection = ADC_EOC_SEQ_CONV;
    hadc.Init.LowPowerAutoWait = ADC_AUTOWAIT_DISABLE;
    hadc.Init.LowPowerAutoPowerOff = ADC_AUTOPOWEROFF_DISABLE;
    hadc.Init.ChannelsBank = ADC_CHANNELS_BANK_A;
    hadc.Init.ContinuousConvMode = ENABLE;
    hadc.Init.NbrOfConversion = 3;
    hadc.Init.DiscontinuousConvMode = DISABLE;
    hadc.Init.ExternalTrigConv = ADC_SOFTWARE_START;
    hadc.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
    hadc.Init.DMAContinuousRequests = ENABLE;
    if (HAL_ADC_Init(&hadc) != HAL_OK)
    {
    Error_Handler();
    }
    /** Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.
    */
    sConfig.Channel = ADC_CHANNEL_0;
    sConfig.Rank = ADC_REGULAR_RANK_1;
    sConfig.SamplingTime = ADC_SAMPLETIME_16CYCLES;
    if (HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK)
    {
    Error_Handler();
    }
    /** Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.
    */
    sConfig.Channel = ADC_CHANNEL_2;
    sConfig.Rank = ADC_REGULAR_RANK_2;
    if (HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK)
    {
    Error_Handler();
    }
    /** Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.
    */
    sConfig.Channel = ADC_CHANNEL_6;
    sConfig.Rank = ADC_REGULAR_RANK_3;
    if (HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK)
    {
    Error_Handler();
    }
    /* USER CODE BEGIN ADC_Init 2 */
    
    /* USER CODE END ADC_Init 2 */
    
    }

    This is the configuration of ADC. The rest of the code is presented above. It is very simple. Start with DMA, set the flag by callback function, reset the flag and restart the ADC with DMA again. 

    Technical Moderator
    March 19, 2024

    Could you please share your .ioc file?

    PS: next time please use </> button to insert your code for source code readability.

     

    PejwaakAuthor
    Visitor II
    March 19, 2024
    #MicroXplorer Configuration settings - do not modify
    ADC.Channel-0\#ChannelRegularConversion=ADC_CHANNEL_0
    ADC.Channel-1\#ChannelRegularConversion=ADC_CHANNEL_2
    ADC.Channel-3\#ChannelRegularConversion=ADC_CHANNEL_6
    ADC.ClockPrescaler=ADC_CLOCK_ASYNC_DIV4
    ADC.ContinuousConvMode=ENABLE
    ADC.DMAContinuousRequests=ENABLE
    ADC.IPParameters=Rank-0\#ChannelRegularConversion,Channel-0\#ChannelRegularConversion,SamplingTime-0\#ChannelRegularConversion,NbrOfConversionFlag,ClockPrescaler,ScanConvMode,ContinuousConvMode,Rank-1\#ChannelRegularConversion,Channel-1\#ChannelRegularConversion,SamplingTime-1\#ChannelRegularConversion,NbrOfConversion,DMAContinuousRequests,Rank-3\#ChannelRegularConversion,Channel-3\#ChannelRegularConversion,SamplingTime-3\#ChannelRegularConversion,Resolution
    ADC.NbrOfConversion=3
    ADC.NbrOfConversionFlag=1
    ADC.Rank-0\#ChannelRegularConversion=1
    ADC.Rank-1\#ChannelRegularConversion=2
    ADC.Rank-3\#ChannelRegularConversion=3
    ADC.Resolution=ADC_RESOLUTION_10B
    ADC.SamplingTime-0\#ChannelRegularConversion=ADC_SAMPLETIME_16CYCLES
    ADC.SamplingTime-1\#ChannelRegularConversion=ADC_SAMPLETIME_16CYCLES
    ADC.SamplingTime-3\#ChannelRegularConversion=ADC_SAMPLETIME_16CYCLES
    ADC.ScanConvMode=ADC_SCAN_ENABLE
    Dma.ADC.0.Direction=DMA_PERIPH_TO_MEMORY
    Dma.ADC.0.Instance=DMA1_Channel1
    Dma.ADC.0.MemDataAlignment=DMA_MDATAALIGN_HALFWORD
    Dma.ADC.0.MemInc=DMA_MINC_ENABLE
    Dma.ADC.0.Mode=DMA_CIRCULAR
    Dma.ADC.0.PeriphDataAlignment=DMA_PDATAALIGN_HALFWORD
    Dma.ADC.0.PeriphInc=DMA_PINC_DISABLE
    Dma.ADC.0.Priority=DMA_PRIORITY_LOW
    Dma.ADC.0.RequestParameters=Instance,Direction,PeriphInc,MemInc,PeriphDataAlignment,MemDataAlignment,Mode,Priority
    Dma.Request0=ADC
    Dma.RequestsNb=1
    File.Version=6
    KeepUserPlacement=false
    Mcu.Family=STM32L1
    Mcu.IP0=ADC
    Mcu.IP1=DAC
    Mcu.IP2=DMA
    Mcu.IP3=NVIC
    Mcu.IP4=RCC
    Mcu.IP5=SYS
    Mcu.IP6=TIM2
    Mcu.IP7=USART3
    Mcu.IPNb=8
    Mcu.Name=STM32L151V(8-B)TxA
    Mcu.Package=LQFP100
    Mcu.Pin0=PH0-OSC_IN
    Mcu.Pin1=PH1-OSC_OUT
    Mcu.Pin10=PD13
    Mcu.Pin11=PD14
    Mcu.Pin12=PA13
    Mcu.Pin13=PA14
    Mcu.Pin14=VP_SYS_VS_Systick
    Mcu.Pin15=VP_TIM2_VS_ClockSourceINT
    Mcu.Pin2=PA0-WKUP1
    Mcu.Pin3=PA2
    Mcu.Pin4=PA4
    Mcu.Pin5=PA6
    Mcu.Pin6=PE11
    Mcu.Pin7=PE12
    Mcu.Pin8=PD8
    Mcu.Pin9=PD9
    Mcu.PinsNb=16
    Mcu.ThirdPartyNb=0
    Mcu.UserConstants=
    Mcu.UserName=STM32L151V8TxA
    MxCube.Version=6.4.0
    MxDb.Version=DB.6.0.40
    NVIC.BusFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false
    NVIC.DMA1_Channel1_IRQn=true\:0\:0\:false\:false\:true\:false\:true
    NVIC.DebugMonitor_IRQn=true\:0\:0\:false\:false\:true\:false\:false
    NVIC.ForceEnableDMAVector=true
    NVIC.HardFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false
    NVIC.MemoryManagement_IRQn=true\:0\:0\:false\:false\:true\:false\:false
    NVIC.NonMaskableInt_IRQn=true\:0\:0\:false\:false\:true\:false\:false
    NVIC.PendSV_IRQn=true\:0\:0\:false\:false\:true\:false\:false
    NVIC.PriorityGroup=NVIC_PRIORITYGROUP_4
    NVIC.SVC_IRQn=true\:0\:0\:false\:false\:true\:false\:false
    NVIC.SysTick_IRQn=true\:15\:0\:false\:false\:true\:false\:true
    NVIC.TIM2_IRQn=true\:0\:0\:false\:false\:true\:true\:true
    NVIC.UsageFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false
    PA0-WKUP1.GPIOParameters=GPIO_Label
    PA0-WKUP1.GPIO_Label=Water_Tempe1
    PA0-WKUP1.Locked=true
    PA0-WKUP1.Mode=IN0
    PA0-WKUP1.Signal=ADC_IN0
    PA13.Mode=Serial_Wire
    PA13.Signal=SYS_JTMS-SWDIO
    PA14.Mode=Serial_Wire
    PA14.Signal=SYS_JTCK-SWCLK
    PA2.GPIOParameters=GPIO_Label
    PA2.GPIO_Label=XDCR_TEMP1
    PA2.Mode=IN2
    PA2.Signal=ADC_IN2
    PA4.GPIOParameters=GPIO_Label
    PA4.GPIO_Label=Amp_PSU_Voltage_Adjust
    PA4.Signal=COMP_DAC1_group
    PA6.Mode=IN6
    PA6.Signal=ADC_IN6
    PD13.GPIOParameters=GPIO_Label
    PD13.GPIO_Label=V24_Voltage_PGOOD
    PD13.Locked=true
    PD13.Signal=GPIO_Input
    PD14.GPIOParameters=GPIO_Label
    PD14.GPIO_Label=Amp_Voltage_PGOOD
    PD14.Locked=true
    PD14.Signal=GPIO_Input
    PD8.Locked=true
    PD8.Mode=Asynchronous
    PD8.Signal=USART3_TX
    PD9.Locked=true
    PD9.Mode=Asynchronous
    PD9.Signal=USART3_RX
    PE11.GPIOParameters=GPIO_Label
    PE11.GPIO_Label=Test_Output1
    PE11.Locked=true
    PE11.Signal=GPIO_Output
    PE12.GPIOParameters=GPIO_Label
    PE12.GPIO_Label=Test_Output2
    PE12.Locked=true
    PE12.Signal=GPIO_Output
    PH0-OSC_IN.Mode=HSE-External-Oscillator
    PH0-OSC_IN.Signal=RCC_OSC_IN
    PH1-OSC_OUT.Mode=HSE-External-Oscillator
    PH1-OSC_OUT.Signal=RCC_OSC_OUT
    PinOutPanel.RotationAngle=0
    ProjectManager.AskForMigrate=true
    ProjectManager.BackupPrevious=false
    ProjectManager.CompilerOptimize=6
    ProjectManager.ComputerToolchain=false
    ProjectManager.CoupleFile=false
    ProjectManager.CustomerFirmwarePackage=
    ProjectManager.DefaultFWLocation=true
    ProjectManager.DeletePrevious=true
    ProjectManager.DeviceId=STM32L151V8TxA
    ProjectManager.FirmwarePackage=STM32Cube FW_L1 V1.10.4
    ProjectManager.FreePins=false
    ProjectManager.HalAssertFull=false
    ProjectManager.HeapSize=0x200
    ProjectManager.KeepUserCode=true
    ProjectManager.LastFirmware=true
    ProjectManager.LibraryCopy=1
    ProjectManager.MainLocation=Core/Src
    ProjectManager.NoMain=false
    ProjectManager.PreviousToolchain=
    ProjectManager.ProjectBuild=false
    ProjectManager.ProjectFileName=Control_Centre_Eval.ioc
    ProjectManager.ProjectName=Control_Centre_Eval
    ProjectManager.RegisterCallBack=
    ProjectManager.StackSize=0x400
    ProjectManager.TargetToolchain=STM32CubeIDE
    ProjectManager.ToolChainLocation=
    ProjectManager.UnderRoot=true
    ProjectManager.functionlistsort=1-SystemClock_Config-RCC-false-HAL-false,2-MX_GPIO_Init-GPIO-false-HAL-true,3-MX_ADC_Init-ADC-false-HAL-true,4-MX_DAC_Init-DAC-false-HAL-true,5-MX_DMA_Init-DMA-false-HAL-true,6-MX_USART3_UART_Init-USART3-false-HAL-true,7-MX_TIM2_Init-TIM2-false-HAL-true
    RCC.48MHZClocksFreq_Value=32000000
    RCC.AHBFreq_Value=32000000
    RCC.APB1Freq_Value=32000000
    RCC.APB1TimFreq_Value=32000000
    RCC.APB2CLKDivider=RCC_HCLK_DIV16
    RCC.APB2Freq_Value=2000000
    RCC.APB2TimFreq_Value=4000000
    RCC.FCLKCortexFreq_Value=32000000
    RCC.FamilyName=M
    RCC.HCLKFreq_Value=32000000
    RCC.HSE_VALUE=8000000
    RCC.HSI_VALUE=16000000
    RCC.IPParameters=48MHZClocksFreq_Value,AHBFreq_Value,APB1Freq_Value,APB1TimFreq_Value,APB2CLKDivider,APB2Freq_Value,APB2TimFreq_Value,FCLKCortexFreq_Value,FamilyName,HCLKFreq_Value,HSE_VALUE,HSI_VALUE,LSE_VALUE,LSI_VALUE,MCOPinFreq_Value,MSI_VALUE,PLLCLKFreq_Value,PLLMUL,PLLSourceVirtual,PWRFreq_Value,RTCFreq_Value,RTCHSEDivFreq_Value,SYSCLKFreq_VALUE,SYSCLKSource,TIMFreq_Value,TimerFreq_Value,VCOInputFreq_Value,VCOOutputFreq_Value
    RCC.LSE_VALUE=32768
    RCC.LSI_VALUE=37000
    RCC.MCOPinFreq_Value=32000000
    RCC.MSI_VALUE=2097000
    RCC.PLLCLKFreq_Value=32000000
    RCC.PLLMUL=RCC_PLL_MUL8
    RCC.PLLSourceVirtual=RCC_PLLSOURCE_HSE
    RCC.PWRFreq_Value=32000000
    RCC.RTCFreq_Value=37000
    RCC.RTCHSEDivFreq_Value=4000000
    RCC.SYSCLKFreq_VALUE=32000000
    RCC.SYSCLKSource=RCC_SYSCLKSOURCE_PLLCLK
    RCC.TIMFreq_Value=32000000
    RCC.TimerFreq_Value=32000000
    RCC.VCOInputFreq_Value=8000000
    RCC.VCOOutputFreq_Value=64000000
    SH.COMP_DAC1_group.0=DAC_OUT1,DAC_OUT1
    SH.COMP_DAC1_group.ConfNb=1
    TIM2.AutoReloadPreload=TIM_AUTORELOAD_PRELOAD_ENABLE
    TIM2.IPParameters=Prescaler,Period,AutoReloadPreload
    TIM2.Period=999
    TIM2.Prescaler=31
    USART3.BaudRate=38400
    USART3.IPParameters=VirtualMode,BaudRate
    USART3.VirtualMode=VM_ASYNC
    VP_SYS_VS_Systick.Mode=SysTick
    VP_SYS_VS_Systick.Signal=SYS_VS_Systick
    VP_TIM2_VS_ClockSourceINT.Mode=Internal
    VP_TIM2_VS_ClockSourceINT.Signal=TIM2_VS_ClockSourceINT
    board=custom
    isbadioc=false

    Here it is. Thanks for continues help :)

    Technical Moderator
    March 20, 2024

    Ok thanks. I will look at it by tomorrow or after and get back to you with a feedback