0
\$\begingroup\$

The output value of the ADC seems to flicker between 539-549 (in a range of 0-4095) no matter what voltage is on the input pin. The voltage on the input is usually between 0V - 4V. This might be a hardware issue, since running code that previously worked no longer does, but I just want to make sure.

main:

    int main(void)
    {
      /* STM32L4xx HAL library initialization:
           - Configure the Flash prefetch
           - Systick timer is configured by default as source of time base, but user 
         can eventually implement his proper time base source (a general purpose 
         timer for example or other time source), keeping in mind that Time base 
         duration should be kept 1ms since PPP_TIMEOUT_VALUEs are defined and 
         handled in milliseconds basis.
           - Set NVIC Group Priority to 4 
           - Low Level Initialization
         */

        int n;

        HAL_Init();

        SystemClock_Config();   

        HAL_InitTick(0x0000); // set systick's priority to the highest.

        BSP_LED_Init(LED4);
        BSP_LED_Init(LED5);

        BSP_LCD_GLASS_Init();

        BSP_JOY_Init(JOY_MODE_EXTI); 

        PWM_Init(); //  intializing the PWM pin PB6
        ADC_Init(); //  inializing the ADC in DMA mode on pin PA1

        HAL_Delay(1000);    //  waiting for initial reading
        while (1)
        {
                BSP_LCD_GLASS_Clear();  //  clearing the glass
                updateReading();                //  updating the measured temperature
                showReading();                  //  showing current temp to LCD

        } 
    }

ADC init:

void ADC_Init(void){//initializes the ADC
    Adc_Handle.Instance = ADC1;

    if (HAL_ADC_DeInit(&Adc_Handle) != HAL_OK)
  {
    /* ADC deinitialization Error */
    Error_Handler();
  }
    Adc_Handle.Init.ClockPrescaler        = ADC_CLOCK_ASYNC_DIV1;          /* Asynchronous clock mode, input ADC clock not divided */
  Adc_Handle.Init.Resolution            = ADC_RESOLUTION_12B;             /* 12-bit resolution for converted data */
  Adc_Handle.Init.DataAlign             = ADC_DATAALIGN_RIGHT;           /* Right-alignment for converted data */
  Adc_Handle.Init.ScanConvMode          = DISABLE;                       /* Sequencer disabled (ADC conversion on only 1 channel: channel set on rank 1) */
  Adc_Handle.Init.EOCSelection          = ADC_EOC_SINGLE_CONV;           /* EOC flag picked-up to indicate conversion end */
  Adc_Handle.Init.LowPowerAutoWait      = DISABLE;                       /* Auto-delayed conversion feature disabled */
  Adc_Handle.Init.ContinuousConvMode    = ENABLE;                        /* Continuous mode enabled (automatic conversion restart after each conversion) */
  Adc_Handle.Init.NbrOfConversion       = 1;                             /* Parameter discarded because sequencer is disabled */
  Adc_Handle.Init.DiscontinuousConvMode = DISABLE;                       /* Parameter discarded because sequencer is disabled */
  Adc_Handle.Init.NbrOfDiscConversion   = 1;                             /* Parameter discarded because sequencer is disabled */
  Adc_Handle.Init.ExternalTrigConv      = ADC_SOFTWARE_START;            /* Software start to trig the 1st conversion manually, without external event */
  Adc_Handle.Init.ExternalTrigConvEdge  = ADC_EXTERNALTRIGCONVEDGE_NONE; /* Parameter discarded because software trigger chosen */
  Adc_Handle.Init.DMAContinuousRequests = ENABLE;                        /* DMA circular mode selected */
  Adc_Handle.Init.Overrun               = ADC_OVR_DATA_OVERWRITTEN;      /* DR register is overwritten with the last conversion result in case of overrun */
  Adc_Handle.Init.OversamplingMode      = DISABLE;                       /* No oversampling */
    if (HAL_ADC_Init(&Adc_Handle) != HAL_OK)
  {
    /* ADC initialization Error */
    Error_Handler();
  }
    if (HAL_ADCEx_Calibration_Start(&Adc_Handle, ADC_SINGLE_ENDED) !=  HAL_OK)  
  {
    Error_Handler();
  }
    sConfig.Channel      = ADC_CHANNEL_6;                   /* Sampled channel number */
  sConfig.Rank         = ADC_REGULAR_RANK_1;            /* Rank of sampled channel number ADCx_CHANNEL */
  sConfig.SamplingTime = ADC_SAMPLETIME_640CYCLES_5;    /* Sampling time (number of clock cycles unit) */
  sConfig.SingleDiff   = ADC_SINGLE_ENDED;              /* Single-ended input channel */
  sConfig.OffsetNumber = 0;                                             /* No offset subtraction */ 
  sConfig.Offset             = ADC_OFFSET_NONE;  
    if (HAL_ADC_ConfigChannel(&Adc_Handle, &sConfig) != HAL_OK)
  {
    /* Channel Configuration Error */
    Error_Handler();
  }
    if (HAL_ADC_Start_DMA(&Adc_Handle, (uint32_t *)&ADC1ConvertedValue, 1) != HAL_OK)   //  starting ADC in DMA mode
  {
    Error_Handler();
  }

}

Pin PA1 init:

void HAL_ADC_MspInit(ADC_HandleTypeDef* hadc)
{
  GPIO_InitTypeDef          GPIO_InitStruct;
  static DMA_HandleTypeDef  hdma_adc;

  /*##-1- Enable peripherals and GPIO Clocks #################################*/

    /* ADC1 Periph clock enable */
   __HAL_RCC_ADC_CLK_ENABLE();      //NO ADC1, 2 OR 3??
   /* ADC Periph interface clock configuration */
  __HAL_RCC_ADC_CONFIG(RCC_ADCCLKSOURCE_SYSCLK);  //???

    /* Enable DMA1 clock */
  __HAL_RCC_DMA1_CLK_ENABLE();

  /*##-2- Configure peripheral GPIO ##########################################*/ 
    __HAL_RCC_GPIOA_CLK_ENABLE();
    GPIO_InitStruct.Pin = GPIO_PIN_1;
  GPIO_InitStruct.Mode = GPIO_MODE_ANALOG_ADC_CONTROL;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

  //##-3- Configure the DMA  
    //RM0351, table 45 & 46 on page 342 shows: ADC mapped to DMA1/channel 1  or to DMA2/channel 3.
    hdma_adc.Instance                 = DMA1_Channel1;
  hdma_adc.Init.Request             = DMA_REQUEST_0;
  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_WORD;
  hdma_adc.Init.MemDataAlignment    = DMA_MDATAALIGN_WORD;
  hdma_adc.Init.Mode                = DMA_CIRCULAR;
  hdma_adc.Init.Priority            = DMA_PRIORITY_MEDIUM;
    HAL_DMA_DeInit(&hdma_adc);
  HAL_DMA_Init(&hdma_adc);

  __HAL_LINKDMA(hadc, DMA_Handle, hdma_adc);

  //##-4- Configure the NVIC for DMA 
    HAL_NVIC_SetPriority(DMA1_Channel1_IRQn, 1, 0);
  HAL_NVIC_EnableIRQ(DMA1_Channel1_IRQn);  
}
\$\endgroup\$
  • \$\begingroup\$ To quote you: This might be a hardware issue, since running code that previously worked no longer does, but I just want to make sure. Could you please confirm this is not a hardware issue then? \$\endgroup\$ – domen Jan 14 at 10:13
  • \$\begingroup\$ @domen I don't know how to confirm that... I just wanted to make sure that my settings weren't causing the problem or get some tips on checking if it's a hardware issue. Instead of being condescending you could maybe tell me how I could confirm that. \$\endgroup\$ – Alexander Jan 14 at 12:40
  • \$\begingroup\$ Check power supply, confirm voltage on pins is what you expect it to be, confirm surrounding circuitry works. Have you got another board where you can try this software? Does this work if you change pins? Are you sure this is the exact software that worked previously (do you use SCM)? Has the software toolchain (compiler) changed? \$\endgroup\$ – domen Jan 14 at 14:23
  • \$\begingroup\$ But what I'm really getting at - you've provided the one thing you think works fine (not in self contained state, so it's hard to check if someone decides to really dig deep into this), and you have not provided any other details of system where the actual issue might lie. \$\endgroup\$ – domen Jan 14 at 14:25
  • \$\begingroup\$ It would also help you to learn how to debug. "Does this code work" is hardly a question. Use a debugger or insert prints to confirm the actual values from stm32 match what you expect them to be. Then provide all those info when you're stuck where you don't know how to progress anymore. \$\endgroup\$ – domen Jan 14 at 14:27
1
\$\begingroup\$

If you aren't sure how/if things work just start with possibly shortest "hello world" config, for this example: get ADC triggered once and check its read value. Reference Manual, Datasheet for this exact mcu, debuger are a must. Using HAL/code generators cannot always save you from these, if you wish to have things working. Then you can add DMA and other complexity.

For me it seems there is no "hardware issue" but wrong gpio/channel (or dma? - can't tell how/if you are reading it after DMA transfer) config. So, assuming from your code, you have done proper system clocks initalization etc (your leds are ok?), and you want ADC1 to read from channel 6. So let's check the list to debug your thing, I assume your config code can't be trusted:

  1. Check if pin number is ok: get Datasheet, search for "ADC1". You will get into table with gpio alternative modes (Table 16) eventually. Now search which pin gets ADC1.. with ..IN6: you find "ADC123_IN6"(ensure first channel is IN1, not IN0). For your board it is pin 24, PA1 - port A. Check if your voltage is wired to it. Check on your board manual, schematics if this pin isn't used or hooked to sth else.
  2. Check GPIO port: open Reference manual (RM), get to the section RCC (chapter 6) and search GPIOA. Find it in the "...peripheral clock enable register..." - you get the register name (RCC_AHB2ENR) which controls GPIO ports clock enable - you have to turn on clock for most stm32 peripherals to make them work. Now fire up your IDE, start debug session, run the code past your configuration, open peripheral/register window (assuming your IDE supports this, popular ones do), get the GPIOA periheral, look for register name you found (RCC_AHB2ENR) - you should by now get the idea why search for the register name - check if the EN bit for port A is on. Now I won't describe more how to search for exact things in manuals and inspect target. Carry on with some effort yourself.

  3. Check GPIO configuration: get Table 38 in RM. As you need "Analog input", check in debuger if config registers from that table have proper values for your chosen pin.

We are done with GPIO. Now ADC:

  1. Again, check the clock enable for ADC1, just like for GPIOC.
  2. By skimming the ADC RM chapter you may notice relevant things like "Clock ratio constraint between ADC clock and AHB clock". Check it. Generally, registers reset values are usually ok for starting basic working setup. Though can't tell what HAL is writing everywhere.
  3. Check channel selection: RM page 520 seems relevant for checking the value of registers for channel selection. Oh look, another "caution" remark: check GPIOx_ASCR registers in the GPIO registers configuration. That's why you should always skim through entire chapters of used peripherals (GPIO, in this case).
  4. On page 523 you can find out how to trigger conversion from software... you can use it with your debuger to start conversion on demand with a mouse click to immedietaly check result.
  5. Check the triggering mode configuration - it seems you want continous conversion mode. Find out, how to start running that continous conversion and check it in debuger if it is running.

Repeat for DMA, if you are using it.

Now you know how to debug your software and prove or not, that the hardware is flawed. Oh, we don't know how you wired your voltage source - keep input voltage in spec of the mcu and beware the different grounds (in case you generate voltage from external device).

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.