Skip to main content
Visitor II
November 7, 2024
Question

ADC not working on STM32H753. It keeps reading 0.

  • November 7, 2024
  • 4 replies
  • 1509 views
I used this sample code I took somewhere to try out but the ADC is not working on STM32H753.
It keeps reading 0. Can anyone help?
 

 

#include "main.h"
#include <stdio.h>
#include <stdint.h>
#include "uart.h"
/* Definition for ADCx clock resources */
#define ADCx ADC1
#define ADCx_CLK_ENABLE() __HAL_RCC_ADC12_CLK_ENABLE()
#define ADCx_CHANNEL_GPIO_CLK_ENABLE() __HAL_RCC_GPIOA_CLK_ENABLE()

#define ADCx_FORCE_RESET() __HAL_RCC_ADC12_FORCE_RESET()
#define ADCx_RELEASE_RESET() __HAL_RCC_ADC12_RELEASE_RESET()

/* Definition for ADCx Channel Pin */
#define ADCx_CHANNEL_PIN GPIO_PIN_0
#define ADCx_CHANNEL_GPIO_PORT GPIOA

/* Definition for ADCx's Channel */
#define ADCx_CHANNEL ADC_CHANNEL_0
#define SAMPLINGTIME ADC_SAMPLETIME_8CYCLES_5

/* ADC handler declaration */
ADC_HandleTypeDef AdcHandle;

/* Variable used to get converted value */
__IO uint16_t uhADCxConvertedValue = 0;

void SystemClock_Config(void);
static void MPU_Config(void);
static void MX_GPIO_Init(void);

int main(void)
{
 ADC_ChannelConfTypeDef sConfig;

 MPU_Config();
 HAL_Init();
 SystemClock_Config();
 MX_GPIO_Init();
 UART_Init();
 
 /*##-1- Configure the ADC peripheral #######################################*/
 AdcHandle.Instance = ADCx;
 
 HAL_ADC_DeInit(&AdcHandle);
 AdcHandle.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV2; /* Asynchronous clock mode, input ADC clock divided by 2*/
 AdcHandle.Init.Resolution = ADC_RESOLUTION_16B; /* 16-bit resolution for converted data */
 AdcHandle.Init.ScanConvMode = DISABLE; /* Sequencer disabled (ADC conversion on only 1 channel: channel set on rank 1) */
 AdcHandle.Init.EOCSelection = ADC_EOC_SINGLE_CONV; /* EOC flag picked-up to indicate conversion end */
 AdcHandle.Init.LowPowerAutoWait = DISABLE; /* Auto-delayed conversion feature disabled */
 AdcHandle.Init.ContinuousConvMode = DISABLE; /* Continuous mode disabled to have only 1 conversion at each conversion trig */
 AdcHandle.Init.NbrOfConversion = 1; /* Parameter discarded because sequencer is disabled */
 AdcHandle.Init.DiscontinuousConvMode = DISABLE; /* Parameter discarded because sequencer is disabled */
 AdcHandle.Init.NbrOfDiscConversion = 1; /* Parameter discarded because sequencer is disabled */
 AdcHandle.Init.ExternalTrigConv = ADC_SOFTWARE_START; /* Software start to trig the 1st conversion manually, without external event */
 AdcHandle.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE; /* Parameter discarded because software trigger chosen */
 AdcHandle.Init.ConversionDataManagement = ADC_CONVERSIONDATA_DR; /* Regular Conversion data stored in DR register only */
 AdcHandle.Init.Overrun = ADC_OVR_DATA_OVERWRITTEN; /* DR register is overwritten with the last conversion result in case of overrun */
 AdcHandle.Init.OversamplingMode = DISABLE; /* No oversampling */

 HAL_ADC_Init(&AdcHandle);

 /*##-2- Configure ADC regular channel ######################################*/
 sConfig.Channel = ADCx_CHANNEL; /* Sampled channel number */
 sConfig.Rank = ADC_REGULAR_RANK_1; /* Rank of sampled channel number ADCx_CHANNEL */
 sConfig.SamplingTime = ADC_SAMPLETIME_387CYCLES_5; /* Sampling time (number of clock cycles unit) */
 sConfig.SingleDiff = ADC_SINGLE_ENDED; /* Single-ended input channel */
 sConfig.OffsetNumber = ADC_OFFSET_NONE; /* No offset subtraction */
 sConfig.Offset = 0; /* Parameter discarded because offset correction is disabled */

 HAL_ADC_ConfigChannel(&AdcHandle, &sConfig);
 
 /* Run the ADC calibration in single-ended mode */
 HAL_ADCEx_Calibration_Start(&AdcHandle, ADC_CALIB_OFFSET_LINEARITY, ADC_SINGLE_ENDED);
 

 while (1)
 {
 /*##-3- Start the conversion process #######################################*/
 HAL_ADC_Start(&AdcHandle);
 
 HAL_ADC_PollForConversion(&AdcHandle, 1000);
 
 /* ADC conversion completed */
 /*##-5- Get the converted value of regular channel ########################*/
 uhADCxConvertedValue = HAL_ADC_GetValue(&AdcHandle);
 printf("Starting .... %d \r\n", uhADCxConvertedValue);
 }
}

// GPIO Initialization for PA0 as Analog
static void MX_GPIO_Init(void)
{
 __HAL_RCC_GPIOA_CLK_ENABLE(); // Enable clock for GPIOA
 GPIO_InitTypeDef GPIO_InitStruct = {0};
 GPIO_InitStruct.Pin = GPIO_PIN_0; // Select PA0
 GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; // Set as analog mode
 GPIO_InitStruct.Pull = GPIO_NOPULL; // No pull-up or pull-down
 HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); // Initialize PA0
}

void SystemClock_Config(void)
{
 RCC_OscInitTypeDef RCC_OscInitStruct = {0};
 RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

 /** Supply configuration update enable
 */
 HAL_PWREx_ConfigSupply(PWR_LDO_SUPPLY);

 /** Configure the main internal regulator output voltage
 */
 __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);

 while(!__HAL_PWR_GET_FLAG(PWR_FLAG_VOSRDY)) {}

 /** Initializes the RCC Oscillators according to the specified parameters
 * in the RCC_OscInitTypeDef structure.
 */
 RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
 RCC_OscInitStruct.HSIState = RCC_HSI_DIV1;
 RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
 RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
 RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
 RCC_OscInitStruct.PLL.PLLM = 4;
 RCC_OscInitStruct.PLL.PLLN = 50;
 RCC_OscInitStruct.PLL.PLLP = 2;
 RCC_OscInitStruct.PLL.PLLQ = 2;
 RCC_OscInitStruct.PLL.PLLR = 2;
 RCC_OscInitStruct.PLL.PLLRGE = RCC_PLL1VCIRANGE_3;
 RCC_OscInitStruct.PLL.PLLVCOSEL = RCC_PLL1VCOWIDE;
 RCC_OscInitStruct.PLL.PLLFRACN = 0;
 if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
 {
 Error_Handler();
 }

 /** Initializes the CPU, AHB and APB buses clocks
 */
 RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
 |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2
 |RCC_CLOCKTYPE_D3PCLK1|RCC_CLOCKTYPE_D1PCLK1;
 RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
 RCC_ClkInitStruct.SYSCLKDivider = RCC_SYSCLK_DIV1;
 RCC_ClkInitStruct.AHBCLKDivider = RCC_HCLK_DIV2;
 RCC_ClkInitStruct.APB3CLKDivider = RCC_APB3_DIV2;
 RCC_ClkInitStruct.APB1CLKDivider = RCC_APB1_DIV2;
 RCC_ClkInitStruct.APB2CLKDivider = RCC_APB2_DIV2;
 RCC_ClkInitStruct.APB4CLKDivider = RCC_APB4_DIV2;

 if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
 {
 Error_Handler();
 }
}


void MPU_Config(void)
{
 MPU_Region_InitTypeDef MPU_InitStruct = {0};

 /* Disables the MPU */
 HAL_MPU_Disable();

 MPU_InitStruct.Enable = MPU_REGION_ENABLE;
 MPU_InitStruct.Number = MPU_REGION_NUMBER0;
 MPU_InitStruct.BaseAddress = 0x0;
 MPU_InitStruct.Size = MPU_REGION_SIZE_4GB;
 MPU_InitStruct.SubRegionDisable = 0x87;
 MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0;
 MPU_InitStruct.AccessPermission = MPU_REGION_NO_ACCESS;
 MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_DISABLE;
 MPU_InitStruct.IsShareable = MPU_ACCESS_SHAREABLE;
 MPU_InitStruct.IsCacheable = MPU_ACCESS_NOT_CACHEABLE;
 MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE;

 HAL_MPU_ConfigRegion(&MPU_InitStruct);
 /* Enables the MPU */
 HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT);
}

void Error_Handler(void)
{
 __disable_irq();
 while (1)
 {
 }
}

#ifdef USE_FULL_ASSERT
/**
 * @brief Reports the name of the source file and the source line number
 * where the assert_param error has occurred.
 * @PAram file: pointer to the source file name
 * @PAram line: assert_param error line source number
 * @retval None
 */
void assert_failed(uint8_t *file, uint32_t line)
{
 /* USER CODE BEGIN 6 */
 /* User can add his own implementation to report the file name and line number,
 ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
 /* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */

 

    This topic has been closed for replies.

    4 replies

    Graduate
    November 7, 2024

    You have: #define ADCx_CLK_ENABLE() __HAL_RCC_ADC12_CLK_ENABLE()

    but do you ever actually use it?

    AskiaAuthor
    Visitor II
    November 7, 2024

    Not really. In fact, I tried multiple times and couldn't get it to work, so I resolved to trying out an already working code on PA0 for testing and guidance. 

     

    Graduate
    November 7, 2024

    The ADC will definitely not work if its clock has not been enabled.

    AskiaAuthor
    Visitor II
    November 7, 2024

    I enabled it and tested it but it's still not working. Only reading 0

    Super User
    November 7, 2024

    Please see the Posting Tips for how to properly post source code:

    https://community.st.com/t5/community-guidelines/how-to-write-your-question-to-maximize-your-chances-to-find-a/ta-p/575228

    I edited the post for you

    Graduate II
    November 8, 2024

    You don't check HAL status so how do you know if it returned HAL_OK, HAL_ERROR, or HAL_TIMEOUT?

    HAL_ADC_PollForConversion(&AdcHandle, 1000);

     

    A better approach would be

    	if(HAL_ADC_PollForConversion(&AdcHandle, 100) == HAL_OK)
    	{
    		/* ADC conversion completed */
    		/*##-5- Get the converted value of regular channel ########################*/
    		uhADCxConvertedValue = HAL_ADC_GetValue(&AdcHandle);
    		printf("Starting .... %d \r\n", uhADCxConvertedValue);
    	}
    	else 
    	{
    		// handle error or timeout
    	}