1. STM32G474 ADC 개요
STM32G474는 STMicroelectronics의 STM32G4 시리즈에 속하는 고성능 32비트 ARM Cortex-M4 마이크로컨트롤러로, 최대 170MHz로 동작하며 고성능 ADC(Analog-to-Digital Converter)를 제공합니다. ADC는 아날로그 신호를 디지털 데이터로 변환하며, 센서 데이터 수집, 전압 측정 등에 사용됩니다. 이 문서에서는 STM32G474의 ADC를 HAL API를 사용하여 단일 변환, 연속 변환, 스캔 모드로 설정하고 사용하는 방법을 상세히 설명합니다. 모든 예제 코드는 STM32CubeMX로 생성된 완전한 코드로 구성되며, STM32CubeIDE에서 실행 가능합니다. 각 코드에는 상세한 한글 주석이 포함되어 있습니다.
ADC 모듈의 주요 특징
- ADC 모듈: STM32G474는 최대 5개의 ADC(ADC1~ADC5)를 제공하며, 최대 12비트 해상도 지원.
- 채널: 각 ADC는 최대 16개의 외부 채널을 지원.
- 변환 모드:
- 단일 변환: 한 번의 변환 후 ADC 정지.
- 연속 변환: 변환 완료 후 자동으로 다음 변환 시작.
- 스캔 모드: 여러 채널을 순차적으로 변환.
- 트리거: 소프트웨어, 외부(타이머, GPIO), 하드웨어 트리거 지원.
- 샘플링 시간: 채널별로 설정 가능 (1.5~247.5 사이클).
- 인터럽트: 변환 완료, 오버런, 아날로그 와치독 인터럽트 지원.
- 클럭: ADC는 AHB 클럭에서 파생된 비동기 클럭으로 동작, 저전력 모드 지원.
HAL API는 ADC 설정을 간소화하여 하드웨어 레지스터 직접 조작 없이 효율적인 사용이 가능합니다.
2. 주요 ADC HAL API 함수
2.1. ADC 초기화 및 설정 함수
- HAL_ADC_Init(ADC_HandleTypeDef hadc)*
- 설명: ADC 모듈을 초기화하여 해상도, 데이터 정렬, 클럭 설정 등을 적용.
- 매개변수: hadc (ADC 핸들러 구조체).
- 사용 예: ADC1을 12비트 해상도로 설정.
- HAL_ADC_ConfigChannel(ADC_HandleTypeDef hadc, ADC_ChannelConfTypeDef sConfig)**
- 설명: ADC 채널과 샘플링 시간 설정.
- 매개변수: sConfig (채널 설정 구조체).
- HAL_ADC_Start(ADC_HandleTypeDef hadc)*
- 설명: ADC 변환 시작 (소프트웨어 트리거).
- HAL_ADC_PollForConversion(ADC_HandleTypeDef hadc, uint32_t Timeout)*
- 설명: 변환 완료까지 폴링 방식으로 대기.
- 반환값: HAL_OK (성공), HAL_TIMEOUT (타임아웃).
- HAL_ADC_GetValue(ADC_HandleTypeDef hadc)*
- 설명: 변환된 디지털 값을 반환.
- 반환값: 12비트 ADC 값 (0~4095).
2.2. 인터럽트 및 DMA 관련 함수
- HAL_ADC_Start_IT(ADC_HandleTypeDef hadc)*
- 설명: 인터럽트 모드로 ADC 변환 시작.
- HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef hadc)*
- 설명: 변환 완료 시 호출되는 콜백 함수 (오버라이드 필요).
- HAL_ADC_Start_DMA(ADC_HandleTypeDef hadc, uint32_t pData, uint32_t Length)**
- 설명: DMA를 사용하여 ADC 데이터를 메모리로 전송.
- HAL_NVIC_SetPriority(IRQn_Type IRQn, uint32_t PreemptPriority, uint32_t SubPriority)
- 설명: ADC 인터럽트 우선순위 설정.
- HAL_NVIC_EnableIRQ(IRQn_Type IRQn)
- 설명: ADC 인터럽트 활성화.
3. ADC 설정 및 동작 원리
STM32G474의 ADC를 효과적으로 사용하려면 시스템 클럭, GPIO(아날로그 입력용), ADC 설정, 디버깅 절차를 정확히 구성해야 합니다. 아래는 STM32CubeMX와 STM32CubeIDE를 사용한 설정 절차와 동작 원리를 설명합니다.
3.1. STM32CubeMX 설정 절차
STM32CubeMX를 사용하여 ADC, 시스템 클럭, 디버깅 인터페이스를 설정하는 단계는 다음과 같습니다:
- 프로젝트 생성:
- STM32CubeMX를 열고 "New Project" 선택.
- MCU 선택 창에서 "STM32G474" 검색, 패키지(예: LQFP64) 선택.
- 프로젝트 이름 지정 및 저장 경로 설정.
- 시스템 클럭 설정 (최대 170 MHz, HSE 사용):
- Pinout & Configuration 탭에서 "System Core" > "RCC" 선택.
- "HSE"를 "Crystal/Ceramic Resonator"로 설정 (외부 8 MHz 크리스털 가정).
- Clock Configuration 탭:
- HSE를 8 MHz로 입력.
- PLL Source Mux를 "HSE"로 설정.
- PLL 설정: PLLM = 1, PLLN = 85, PLLR = 2, PLLR Enable 활성화.
- System Clock Mux를 "PLLCLK"로 설정.
- 결과: SYSCLK = (8 MHz / 1) * 85 / 2 = 170 MHz.
- HCLK (AHB), PCLK1 (APB1)을 170 MHz로 설정 (Divider = 1).
- Flash Latency를 4 WS로 설정.
- 클럭 트리에서 에러 없음 확인.
- GPIO 및 ADC 설정:
- Pinout & Configuration 탭:
- 아날로그 입력: GPIOA Pin 0, 1, 2를 "GPIO_Analog"로 설정, User Label을 각각 "ADC_IN0", "ADC_IN1", "ADC_IN2"로 지정.
- "Analog" > "ADC1" 활성화.
- ADC1 Parameter Settings:
- Resolution: 12-bit.
- Clock Prescaler: Asynchronous clock mode, divider 1.
- 단일 변환 (예제 1): Continuous Conversion Mode 비활성화, Number of Conversion = 1, Channel 1 (PA0) 선택, Sampling Time 247.5 Cycles.
- 연속 변환 (예제 2): Continuous Conversion Mode 활성화, Number of Conversion = 1, Channel 1 (PA0) 선택, Sampling Time 247.5 Cycles.
- 스캔 모드 (예제 3): Scan Conversion Mode 활성화, Number of Conversion = 3, Channel 1 (PA0), 2 (PA1), 3 (PA2) 선택, Sampling Time 247.5 Cycles.
- 디버깅 인터페이스 설정:
- "System Core" > "SYS"에서 Debug를 "Serial Wire" (SWD)로 설정.
- SWD 핀 (PA13: SWDIO, PA14: SWCLK) 자동 예약.
- 프로젝트 설정 및 코드 생성:
- Project Manager 탭:
- Project Name과 저장 경로 확인.
- Toolchain/IDE를 "STM32CubeIDE"로 설정.
- Code Generator 옵션에서 "Copy only the necessary library files" 선택.
- "Generate Code" 클릭.
- Project Manager 탭:
3.2. ADC 동작 원리
- 시스템 초기화:
- 시스템 클럭을 170 MHz로 설정, GPIO 및 ADC 클럭 활성화 (__HAL_RCC_GPIOx_CLK_ENABLE(), __HAL_RCC_ADC12_CLK_ENABLE()).
- HAL 라이브러리와 Systick 초기화 (HAL_Init()).
- GPIO 설정:
- 아날로그 입력 핀(예: GPIOA Pin 0, 1, 2)을 GPIO_MODE_ANALOG로 설정.
- 풀업/풀다운 저항 비활성화 (GPIO_NOPULL).
- ADC 설정:
- ADC_HandleTypeDef 구조체로 ADC 모듈 설정 (해상도, 클럭, 연속/스캔 모드 등).
- ADC_ChannelConfTypeDef 구조체로 채널 및 샘플링 시간 설정.
- HAL_ADC_Init 및 HAL_ADC_ConfigChannel로 설정 적용.
- ADC 동작:
- 단일 변환: HAL_ADC_Start로 변환 시작, HAL_ADC_PollForConversion으로 완료 대기, HAL_ADC_GetValue로 데이터 읽기.
- 연속 변환: HAL_ADC_Start로 변환 시작, 이후 자동으로 반복 변환, 주기적으로 HAL_ADC_GetValue 호출.
- 스캔 모드: 여러 채널을 순차 변환, HAL_ADC_PollForConversion을 각 채널마다 호출하여 데이터 수집.
- 결과 처리:
- 12비트 ADC 값(0~4095)을 변수에 저장.
- 전압 변환: ADC 값 * (VREF / 4095), VREF는 일반적으로 3.3V.
3.3. 디버깅 설정 절차 (STM32CubeIDE)
- 디버그 인터페이스 연결:
- STM32G474 보드와 ST-LINK 디버거 연결 (SWDIO: PA13, SWCLK: PA14, GND, 3.3V).
- STM32CubeIDE에서 프로젝트 열고 "Run" > "Debug Configurations" 선택.
- 디버그 구성:
- "STM32 Cortex-M MCU Debugging"에서 새 구성 생성.
- Debugger 탭:
- Debug Probe: ST-LINK (OpenOCD).
- Interface: Serial Wire (SWD).
- "Enable" 체크.
- Startup 탭:
- "Load image"와 "Load symbols" 활성화.
- .elf 파일 경로 확인.
- "Apply" 후 "Debug" 클릭.
- 디버깅 기능 사용:
- 브레이크포인트 설정: main.c에서 코드 라인에 더블 클릭.
- 변수 모니터링: "Expressions" 또는 "Variables" 창에서 adcValue 확인.
- 디버깅 실행: "Resume" (F8), "Step Over" (F6), "Step Into" (F5).
3.4. 프로그램 다운로드 절차 (STM32CubeIDE)
- 프로그램 빌드:
- STM32CubeIDE에서 프로젝트 열고 "Project" > "Build Project" 클릭.
- Console 창에서 빌드 오류 없음 확인.
- 프로그램 다운로드:
- ST-LINK 디버거 연결 후 "Run" > "Run Configurations" 선택.
- "STM32 Cortex-M MCU"에서 새 구성 생성.
- Main 탭에서 .elf 파일 선택 확인.
- "Run" 클릭하여 STM32G474에 다운로드.
- 다운로드 완료 후 보드 자동 리셋 및 프로그램 실행.
- 검증:
- 각 예제에서 ADC 값이 adcValue 변수에 저장됨 (디버깅으로 확인).
- 아날로그 입력(예: 가변 저항)에 따라 값이 0~4095 범위에서 변화.
4. ADC 예제 코드
아래는 STM32G474의 ADC1을 HAL API로 제어하는 STM32CubeMX 생성 예제 코드입니다. 시스템 클럭은 HSE 8 MHz를 사용하여 170 MHz로 설정됩니다. 각 예제는 단일 변환, 연속 변환, 스캔 모드를 구현하며, GPIOA 핀 0, 1, 2를 아날로그 입력으로 사용합니다.
4.1. 예제 1: 단일 변환 (Single Conversion)
GPIOA 핀 0를 아날로그 입력으로 설정하여 ADC1으로 단일 변환을 수행합니다.
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file : main.c
* @brief : Main program body
******************************************************************************
* @attention
*
* STM32CubeMX-generated code for ADC1 single conversion with GPIOA Pin 0.
* Reads ADC value in polling mode. System clock set to 170 MHz using HSE.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
ADC_HandleTypeDef hadc1; // ADC1 핸들러 구조체
/* USER CODE END PTD */
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
#define ADC_IN_Pin GPIO_PIN_0 // GPIOA 핀 0을 ADC 입력으로 사용
#define ADC_IN_GPIO_Port GPIOA // ADC 입력이 연결된 GPIO 포트
/* USER CODE END PD */
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
/* USER CODE END PM */
/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN PV */
volatile uint32_t adcStatus = 0; // ADC 상태 변수: 0 (초기화 완료), 1 (동작 중), 0xFFFF (오류)
volatile uint16_t adcValue = 0; // ADC 변환 값 저장 변수
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void); // 시스템 클럭 설정 함수 선언
static void MX_GPIO_Init(void); // GPIO 초기화 함수 선언
static void MX_ADC1_Init(void); // ADC1 초기화 함수 선언
/* USER CODE BEGIN PFP */
/* USER CODE END PFP */
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
/**
* @brief The application entry point.
* @retval int
*/
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init(); // HAL 라이브러리 및 시스템 타이머(Systick) 초기화
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config(); // 시스템 클럭을 170 MHz로 설정 (HSE 8 MHz 사용)
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init(); // GPIOA 핀 0를 아날로그 모드로 초기화
MX_ADC1_Init(); // ADC1 초기화
/* USER CODE BEGIN 2 */
if (adcStatus != 1) // ADC 초기화 성공 여부 확인
{
adcStatus = 0xFFFF; // 초기화 실패 시 오류 상태 설정
while (1); // 오류 발생 시 무한 루프
}
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
HAL_ADC_Start(&hadc1); // ADC 단일 변환 시작
if (HAL_ADC_PollForConversion(&hadc1, 10) == HAL_OK) // 변환 완료 확인 (최대 10ms 대기)
{
adcValue = HAL_ADC_GetValue(&hadc1); // 변환된 ADC 값 읽기
adcStatus = 1; // 동작 상태 업데이트
}
else
{
adcStatus = 0xFFFF; // 변환 실패 시 오류 상태 설정
}
HAL_Delay(1000); // 1초 대기 후 다음 변환
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
/**
* @brief System Clock Configuration
* @retval None
*/
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0}; // 오실레이터 설정 구조체 초기화
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; // 클럭 설정 구조체 초기화
/** Configure the main internal regulator output voltage
*/
HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1); // 전압 레귤레이터를 Scale 1로 설정 (최대 성능)
/** Initializes the RCC Oscillators according to the specified parameters
* in the RCC_OscInitTypeDef structure.
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE; // 외부 HSE 오실레이터 사용
RCC_OscInitStruct.HSEState = RCC_HSE_ON; // HSE 활성화
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; // PLL 활성화
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE; // PLL 소스를 HSE로 설정
RCC_OscInitStruct.PLL.PLLM = 1; // PLL 분주기 M = 1
RCC_OscInitStruct.PLL.PLLN = 85; // PLL 곱셈기 N = 85
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2; // PLL P 출력 분주기 = 2
RCC_OscInitStruct.PLL.PLLQ = RCC_PLLQ_DIV2; // PLL Q 출력 분주기 = 2
RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2; // PLL R 출력 분주기 = 2 (SYSCLK = 8 MHz * 85 / 2 = 170 MHz)
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_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; // 시스템 클럭 소스를 PLL로 설정
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; // AHB 클럭 분주기 = 1 (HCLK = 170 MHz)
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1; // APB1 클럭 분주기 = 1 (PCLK1 = 170 MHz)
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; // APB2 클럭 분주기 = 1 (PCLK2 = 170 MHz)
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4) != HAL_OK) // 클럭 설정 및 플래시 레이턴시 4 WS 적용
{
Error_Handler(); // 설정 실패 시 오류 처리
}
/** Configure ADC clock
*/
RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};
PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_ADC12; // ADC12 클럭 선택
PeriphClkInit.Adc12ClockSelection = RCC_ADC12CLKSOURCE_SYSCLK; // ADC 클럭 소스를 SYSCLK로 설정
if (HAL_RCCEx_PeriphCLK shootConfig(&PeriphClkInit) != HAL_OK)
{
Error_Handler(); // ADC 클럭 설정 실패 시 오류 처리
}
}
/**
* @brief ADC1 Initialization Function
* @param None
* @retval None
*/
static void MX_ADC1_Init(void)
{
ADC_ChannelConfTypeDef sConfig = {0}; // ADC 채널 설정 구조체 초기화
/** Common config
*/
hadc1.Instance = ADC1; // ADC1 선택
hadc1.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV1; // ADC 클럭 분주기: 비동기 클럭, 분주 없음
hadc1.Init.Resolution = ADC_RESOLUTION_12B; // 12비트 해상도 설정
hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT; // 데이터 오른쪽 정렬
hadc1.Init.ScanConvMode = ADC_SCAN_DISABLE; // 스캔 모드 비활성화 (단일 채널)
hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV; // 단일 변환 완료 시 EOC 플래그 설정
hadc1.Init.ContinuousConvMode = ADC_CONTINUOUS_DISABLE; // 연속 변환 모드 비활성화
if (HAL_ADC_Init(&hadc1) != HAL_OK) // ADC 초기화
{
Error_Handler(); // 초기화 실패 시 오류 처리
}
/** Configure Regular Channel
*/
sConfig.Channel = ADC_CHANNEL_1; // ADC 채널 1 (GPIOA 핀 0) 선택
sConfig.Rank = ADC_REGULAR_RANK_1; // 첫 번째 채널로 설정
sConfig.SamplingTime = ADC_SAMPLETIME_247CYCLES_5; // 샘플링 시간: 247.5 사이클
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK) // 채널 설정 적용
{
Error_Handler(); // 설정 실패 시 오류 처리
}
adcStatus = 1; // ADC 초기화 성공 표시
}
/**
* @brief GPIO Initialization Function
* @param None
* @retval None
*/
static void MX_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0}; // GPIO 설정 구조체 초기화
/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOA_CLK_ENABLE(); // GPIOA 포트 클럭 활성화
/*Configure GPIO pin : PA0 */
GPIO_InitStruct.Pin = ADC_IN_Pin; // 설정할 핀: GPIOA 핀 0
GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; // 아날로그 모드 설정
GPIO_InitStruct.Pull = GPIO_NOPULL; // 풀업/풀다운 저항 사용 안 함
HAL_GPIO_Init(ADC_IN_GPIO_Port, &GPIO_InitStruct); // GPIOA 핀 0 설정 적용
}
/* USER CODE BEGIN 4 */
/* USER CODE END 4 */
/**
* @brief This function is executed in case of error occurrence.
* @retval None
*/
void Error_Handler(void)
{
/* USER CODE BEGIN Error_Handler_Debug */
adcStatus = 0xFFFF; // 오류 상태 설정
while (1) // 무한 루프에서 대기
{
}
/* USER CODE END Error_Handler_Debug */
}
#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 */
while (1) // 어설션 오류 시 무한 루프
{
}
/* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */
설명:
- 기능: GPIOA 핀 0를 아날로그 입력으로 설정하여 ADC1으로 단일 변환 수행.
- 설정: GPIOA 핀 0은 아날로그 모드, ADC1은 12비트, 단일 변환 모드, 샘플링 시간 247.5 사이클.
- GPIO: GPIOA 핀 0 (ADC 입력).
- 출력: ADC 변환 결과는 adcValue 변수에 저장 (0~4095).
- 클럭: HSE 8 MHz, PLL로 170 MHz SYSCLK.
- 검증: 디버깅 모드에서 adcValue를 모니터링하여 입력 전압에 따라 값이 1초 간격으로 변화.
4.2. 예제 2: 연속 변환 (Continuous Conversion)
GPIOA 핀 0를 아날로그 입력으로 설정하여 ADC1으로 연속 변환을 수행합니다.
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file : main.c
* @brief : Main program body
******************************************************************************
* @attention
*
* STM32CubeMX-generated code for ADC1 continuous conversion with GPIOA Pin 0.
* Reads ADC value in polling mode. System clock set to 170 MHz using HSE.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
ADC_HandleTypeDef hadc1; // ADC1 핸들러 구조체
/* USER CODE END PTD */
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
#define ADC_IN_Pin GPIO_PIN_0 // GPIOA 핀 0을 ADC 입력으로 사용
#define ADC_IN_GPIO_Port GPIOA // ADC 입력이 연결된 GPIO 포트
/* USER CODE END PD */
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
/* USER CODE END PM */
/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN PV */
volatile uint32_t adcStatus = 0; // ADC 상태 변수: 0 (초기화 완료), 1 (동작 중), 0xFFFF (오류)
volatile uint16_t adcValue = 0; // ADC 변환 값 저장 변수
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void); // 시스템 클럭 설정 함수 선언
static void MX_GPIO_Init(void); // GPIO 초기화 함수 선언
static void MX_ADC1_Init(void); // ADC1 초기화 함수 선언
/* USER CODE BEGIN PFP */
/* USER CODE END PFP */
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
/**
* @brief The application entry point.
* @retval int
*/
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init(); // HAL 라이브러리 및 시스템 길이머(Systick) 초기화
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config(); // 시스템 클럭을 170 MHz로 설정 (HSE 8 MHz 사용)
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init(); // GPIOA 핀 0를 아날로그 모드로 초기화
MX_ADC1_Init(); // ADC1 초기화
/* USER CODE BEGIN 2 */
HAL_ADC_Start(&hadc1); // ADC 연속 변환 시작
if (adcStatus != 1) // ADC 초기화 성공 여부 확인
{
adcStatus = 0xFFFF; // 초기화 실패 시 오류 상태 설정
while (1); // 오류 발생 시 무한 루프
}
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
if (HAL_ADC_PollForConversion(&hadc1, 10) == HAL_OK) // 변환 완료 확인 (최대 10ms 대기)
{
adcValue = HAL_ADC_GetValue(&hadc1); // 변환된 ADC 값 읽기
adcStatus = 1; // 동작 상태 업데이트
}
else
{
adcStatus = 0xFFFF; // 변환 실패 시 오류 상태 설정
}
HAL_Delay(100); // 100ms 대기 후 다음 읽기
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
/**
* @brief System Clock Configuration
* @retval None
*/
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0}; // 오실레이터 설정 구조체 초기화
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; // 클럭 설정 구조체 초기화
/** Configure the main internal regulator output voltage
*/
HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1); // 전압 레귤레이터를 Scale 1로 설정 (최대 성능)
/** Initializes the RCC Oscillators according to the specified parameters
* in the RCC_OscInitTypeDef structure.
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE; // 외부 HSE 오실레이터 사용
RCC_OscInitStruct.HSEState = RCC_HSE_ON; // HSE 활성화
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; // PLL 활성화
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE; // PLL 소스를 HSE로 설정
RCC_OscInitStruct.PLL.PLLM = 1; // PLL 분주기 M = 1
RCC_OscInitStruct.PLL.PLLN = 85; // PLL 곱셈기 N = 85
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2; // PLL P 출력 분주기 = 2
RCC_OscInitStruct.PLL.PLLQ = RCC_PLLQ_DIV2; // PLL Q 출력 분주기 = 2
RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2; // PLL R 출력 분주기 = 2 (SYSCLK = 8 MHz * 85 / 2 = 170 MHz)
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_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; // 시스템 클럭 소스를 PLL로 설정
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; // AHB 클럭 분주기 = 1 (HCLK = 170 MHz)
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1; // APB1 클럭 분주기 = 1 (PCLK1 = 170 MHz)
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; // APB2 클럭 분주기 = 1 (PCLK2 = 170 MHz)
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4) != HAL_OK) // 클럭 설정 및 플래시 레이턴시 4 WS 적용
{
Error_Handler(); // 설정 실패 시 오류 처리
}
/** Configure ADC clock
*/
RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};
PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_ADC12; // ADC12 클럭 선택
PeriphClkInit.Adc12ClockSelection = RCC_ADC12CLKSOURCE_SYSCLK; // ADC 클럭 소스를 SYSCLK로 설정
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
{
Error_Handler(); // ADC 클럭 설정 실패 시 오류 처리
}
}
/**
* @brief ADC1 Initialization Function
* @param None
* @retval None
*/
static void MX_ADC1_Init(void)
{
ADC_ChannelConfTypeDef sConfig = {0}; // ADC 채널 설정 구조체 초기화
/** Common config
*/
hadc1.Instance = ADC1; // ADC1 선택
hadc1.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV1; // ADC 클럭 분주기: 비동기 클럭, 분주 없음
hadc1.Init.Resolution = ADC_RESOLUTION_12B; // 12비트 해상도 설정
hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT; // 데이터 오른쪽 정렬
hadc1.Init.ScanConvMode = ADC_SCAN_DISABLE; // 스캔 모드 비활성화 (단일 채널)
hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV; // 단일 변환 완료 시 EOC 플래그 설정
hadc1.Init.ContinuousConvMode = ADC_CONTINUOUS_ENABLE; // 연속 변환 모드 활성화
if (HAL_ADC_Init(&hadc1) != HAL_OK) // ADC 초기화
{
Error_Handler(); // 초기화 실패 시 오류 처리
}
/** Configure Regular Channel
*/
sConfig.Channel = ADC_CHANNEL_1; // ADC 채널 1 (GPIOA 핀 0) 선택
sConfig.Rank = ADC_REGULAR_RANK_1; // 첫 번째 채널로 설정
sConfig.SamplingTime = ADC_SAMPLETIME_247CYCLES_5; // 샘플링 시간: 247.5 사이클
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK) // 채널 설정 적용
{
Error_Handler(); // 설정 실패 시 오류 처리
}
adcStatus = 1; // ADC 초기화 성공 표시
}
/**
* @brief GPIO Initialization Function
* @param None
* @retval None
*/
static void MX_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0}; // GPIO 설정 구조체 초기화
/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOA_CLK_ENABLE(); // GPIOA 포트 클럭 활성화
/*Configure GPIO pin : PA0 */
GPIO_InitStruct.Pin = ADC_IN_Pin; // 설정할 핀: GPIOA 핀 0
GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; // 아날로그 모드 설정
GPIO_InitStruct.Pull = GPIO_NOPULL; // 풀업/풀다운 저항 사용 안 함
HAL_GPIO_Init(ADC_IN_GPIO_Port, &GPIO_InitStruct); // GPIOA 핀 0 설정 적용
}
/* USER CODE BEGIN 4 */
/* USER CODE END 4 */
/**
* @brief This function is executed in case of error occurrence.
* @retval None
*/
void Error_Handler(void)
{
/* USER CODE BEGIN Error_Handler_Debug */
adcStatus = 0xFFFF; // 오류 상태 설정
while (1) // 무한 루프에서 대기
{
}
/* USER CODE END Error_Handler_Debug */
}
#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 */
while (1) // 어설션 오류 시 무한 루프
{
}
/* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */
설명:
- 기능: GPIOA 핀 0를 아날로그 입력으로 설정하여 ADC1으로 연속 변환 수행.
- 설정: GPIOA 핀 0은 아날로그 모드, ADC1은 12비트, 연속 변환 모드, 샘플링 시간 247.5 사이클.
- GPIO: GPIOA 핀 0 (ADC 입력).
- 출력: ADC 변환 결과는 adcValue 변수에 저장 (0~4095).
- 클럭: HSE 8 MHz, PLL로 170 MHz SYSCLK.
- 검증: 디버깅 모드에서 adcValue를 모니터링하여 입력 전압에 따라 값이 100ms 간격으로 변화.
4.3. 예제 3: 스캔 모드 (Scan Mode)
GPIOA 핀 0, 1, 2를 아날로그 입력으로 설정하여 ADC1으로 스캔 모드를 수행합니다.
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file : main.c
* @brief : Main program body
******************************************************************************
* @attention
*
* STM32CubeMX-generated code for ADC1 scan mode with GPIOA Pins 0, 1, 2.
* Reads ADC values in polling mode. System clock set to 170 MHz using HSE.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
ADC_HandleTypeDef hadc1; // ADC1 핸들러 구조체
/* USER CODE END PTD */
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
#define ADC_IN0_Pin GPIO_PIN_0 // GPIOA 핀 0을 ADC 입력 1로 사용
#define ADC_IN1_Pin GPIO_PIN_1 // GPIOA 핀 1을 ADC 입력 2로 사용
#define ADC_IN2_Pin GPIO_PIN_2 // GPIOA 해 2을 ADC 입력 3으로 사용
#define ADC_IN_GPIO_Port GPIOA // ADC 입력이 연결된 GPIO 포트
/* USER CODE END PD */
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
/* USER CODE END PM */
/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN PV */
volatile uint32_t adcStatus = 0; // ADC 상태 변수: 0 (초기화 완료), 1 (동작 중), 0xFFFF (오류)
volatile uint16_t adcValues[3] = {0}; // ADC 변환 값 저장 배열 (3개 채널)
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void); // 시스템 클럭 설정 함수 선언
static void MX_GPIO_Init(void); // GPIO 초기화 함수 선언
static void MX_ADC1_Init(void); // ADC1 초기화 함수 선언
/* USER CODE BEGIN PFP */
/* USER CODE END PFP */
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
/**
* @brief The application entry point.
* @retval int
*/
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init(); // HAL 라이브러리 및 시스템 타이머(Systick) 초기화
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config(); // 시스템 클럭을 170 MHz로 설정 (HSE 8 MHz 사용)
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init(); // GPIOA 핀 0, 1, 2를 아날로그 모드로 초기화
MX_ADC1_Init(); // ADC1 초기화
/* USER CODE BEGIN 2 */
if (adcStatus != 1) // ADC 초기화 성공 여부 확인
{
adcStatus = 0xFFFF; // 초기화 실패 시 오류 상태 설정
while (1); // 오류 발생 시 무한 루프
}
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
HAL_ADC_Start(&hadc1); // ADC 스캔 모드 변환 시작
for (uint8_t i = 0; i < 3; i++) // 3개 채널 순차 변환
{
if (HAL_ADC_PollForConversion(&hadc1, 10) == HAL_OK) // 변환 완료 확인 (최대 10ms 대기)
{
adcValues[i] = HAL_ADC_GetValue(&hadc1); // 각 채널의 ADC 값 읽기
adcStatus = 1; // 동작 상태 업데이트
}
else
{
adcStatus = 0xFFFF; // 변환 실패 시 오류 상태 설정
break;
}
}
HAL_Delay(1000); // 1초 대기 후 다음 스캔
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
/**
* @brief System Clock Configuration
* @retval None
*/
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0}; // 오실레이터 설정 구조체 초기화
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; // 클럭 설정 구조체 초기화
/** Configure the main internal regulator output voltage
*/
HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1); // 전압 레귤레이터를 Scale 1로 설정 (최대 성능)
/** Initializes the RCC Oscillators according to the specified parameters
* in the RCC_OscInitTypeDef structure.
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE; // 외부 HSE 오실레이터 사용
RCC_OscInitStruct.HSEState = RCC_HSE_ON; // HSE 활성화
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; // PLL 활성화
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE; // PLL 소스를 HSE로 설정
RCC_OscInitStruct.PLL.PLLM = 1; // PLL 분주기 M = 1
RCC_OscInitStruct.PLL.PLLN = 85; // PLL 곱셈기 N = 85
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2; // PLL P 출력 분주기 = 2
RCC_OscInitStruct.PLL.PLLQ = RCC_PLLQ_DIV2; // PLL Q 출력 분주기 = 2
RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2; // PLL R 출력 분주기 = 2 (SYSCLK = 8 MHz * 85 / 2 = 170 MHz)
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_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; // 시스템 클럭 소스를 PLL로 설정
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; // AHB 클럭 분주기 = 1 (HCLK = 170 MHz)
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1; // APB1 클럭 분주기 = 1 (PCLK1 = 170 MHz)
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; // APB2 클럭 분주기 = 1 (PCLK2 = 170 MHz)
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4) != HAL_OK) // 클럭 설정 및 플래시 레이턴시 4 WS 적용
{
Error_Handler(); // 설정 실패 시 오류 처리
}
/** Configure ADC clock
*/
RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};
PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_ADC12; // ADC12 클럭 선택
PeriphClkInit.Adc12ClockSelection = RCC_ADC12CLKSOURCE_SYSCLK; // ADC 클럭 소스를 SYSCLK로 설정
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
{
Error_Handler(); // ADC 클럭 설정 실패 시 오류 처리
}
}
/**
* @brief ADC1 Initialization Function
* @param None
* @retval None
*/
static void MX_ADC1_Init(void)
{
ADC_ChannelConfTypeDef sConfig = {0}; // ADC 채널 설정 구조체 초기화
/** Common config
*/
hadc1.Instance = ADC1; // ADC1 선택
hadc1.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV1; // ADC 클럭 분주기: 비동기 클럭, 분주 없음
hadc1.Init.Resolution = ADC_RESOLUTION_12B; // 12비트 해상도 설정
hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT; // 데이터 오른쪽 정렬
hadc1.Init.ScanConvMode = ADC_SCAN_ENABLE; // 스캔 모드 활성화
hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV; // 단일 변환 완료 시 EOC 플래그 설정
hadc1.Init.ContinuousConvMode = ADC_CONTINUOUS_DISABLE; // 연속 변환 모드 비활성화
hadc1.Init.NbrOfConversion = 3; // 변환할 채널 수: 3
if (HAL_ADC_Init(&hadc1) != HAL_OK) // ADC 초기화
{
Error_Handler(); // 초기화 실패 시 오류 처리
}
/** Configure Regular Channel 1 (PA0)
*/
sConfig.Channel = ADC_CHANNEL_1; // ADC 채널 1 (GPIOA 핀 0) 선택
sConfig.Rank = ADC_REGULAR_RANK_1; // 첫 번째 채널
sConfig.SamplingTime = ADC_SAMPLETIME_247CYCLES_5; // 샘플링 시간: 247.5 사이클
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK) // 채널 설정 적용
{
Error_Handler(); // 설정 실패 시 오류 처리
}
/** Configure Regular Channel 2 (PA1)
*/
sConfig.Channel = ADC_CHANNEL_2; // ADC 채널 2 (GPIOA 핀 1) 선택
sConfig.Rank = ADC_REGULAR_RANK_2; // 두 번째 채널
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK) // 채널 설정 적용
{
Error_Handler(); // 설정 실패 시 오류 처리
}
/** Configure Regular Channel 3 (PA2)
*/
sConfig.Channel = ADC_CHANNEL_3; // ADC 채널 3 (GPIOA 핀 2) 선택
sConfig.Rank = ADC_REGULAR_RANK_3; // 세 번째 채널
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK) // 채널 설정 적용
{
Error_Handler(); // 설정 실패 시 오류 처리
}
adcStatus = 1; // ADC 초기화 성공 표시
}
/**
* @brief GPIO Initialization Function
* @param None
* @retval None
*/
static void MX_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0}; // GPIO 설정 구조체 초기화
/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOA_CLK_ENABLE(); // GPIOA 포트 클럭 활성화
/*Configure GPIO pins : PA0, PA1, PA2 */
GPIO_InitStruct.Pin = ADC_IN0_Pin | ADC_IN1_Pin | ADC_IN2_Pin; // 설정할 핀: GPIOA 핀 0, 1, 2
GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; // 아날로그 모드 설정
GPIO_InitStruct.Pull = GPIO_NOPULL; // 풀업/풀다운 저항 사용 안 함
HAL_GPIO_Init(ADC_IN_GPIO_Port, &GPIO_InitStruct); // GPIOA 핀 설정 적용
}
/* USER CODE BEGIN 4 */
/* USER CODE END 4 */
/**
* @brief This function is executed in case of error occurrence.
* @retval None
*/
void Error_Handler(void)
{
/* USER CODE BEGIN Error_Handler_Debug */
adcStatus = 0xFFFF; // 오류 상태 설정
while (1) // 무한 루프에서 대기
{
}
/* USER CODE END Error_Handler_Debug */
}
#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 */
while (1) // 어설션 오류 시 무한 루프
{
}
/* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */
설명:
- 기능: GPIOA 핀 0, 1, 2를 아날로그 입력으로 설정하여 ADC1으로 스캔 모드 수행.
- 설정: GPIOA 핀 0, 1, 2는 아날로그 모드, ADC1은 12비트, 스캔 모드, 3개 채널, 샘플링 시간 247.5 사이클.
- GPIO: GPIOA 핀 0, 1, 2 (ADC 입력).
- 출력: ADC 변환 결과는 adcValues 배열에 저장 (0~4095).
- 클럭: HSE 8 MHz, PLL로 170 MHz SYSCLK.
- 검증: 디버깅 모드에서 adcValues[0], adcValues[1], adcValues[2]를 모니터링하여 각 채널의 입력 전압에 따라 값이 1초 간격으로 변화.
5. 추가 고려 사항
- 클럭 설정: HSE 주파수(예: 8 MHz 또는 25 MHz)에 따라 PLL 설정 조정. STM32CubeMX 클럭 트리로 검증.
- 샘플링 시간: 높은 임피던스 소스의 경우 긴 샘플링 시간(예: 247.5 사이클) 권장.
- 참조 전압 (VREF): ADC 값은 VREF(일반적으로 3.3V)에 따라 스케일링. 전압 계산: Voltage = adcValue * (VREF / 4095).
- 스캔 모드: 다중 채널 사용 시 DMA(HAL_ADC_Start_DMA)를 활용하면 효율적.
- 인터럽트: 실시간 애플리케이션에서는 폴링 대신 인터럽트(HAL_ADC_Start_IT) 사용 권장.
- 디버깅: SWD 인터페이스로 adcValue 또는 adcValues 배열을 실시간 모니터링.
- 저전력: ADC 클럭과 샘플링 시간을 최적화하여 전력 소모 감소.
키워드: STM32G474, ADC, HAL API, STM32G4, 마이크로컨트롤러, STM32CubeIDE, STM32CubeMX, 단일 변환, 연속 변환, 스캔 모드, 아날로그 입력, HSE 클럭, 디버깅
'MCU > STM32' 카테고리의 다른 글
[STM32G474] PWM으로 전력변환 DC-DC 토폴로지별 PWM 생성 방법: HAL API 활용(1) (0) | 2025.08.19 |
---|---|
[STM32G474] PWM 사용법: HAL API로 PWM 설정 및 코드 예제 (Advanced-Control 타이머) (0) | 2025.08.19 |
[STM32G474] ADC 사용법: HAL API로 타이머 트리거, 하드웨어 트리거, 인터럽트, DMA 설정 및 코드 예제 (0) | 2025.08.19 |
[STM32G474] 타이머 트리거 사용법: HAL API로 타이머 트리거 설정 및 코드 예제 (0) | 2025.08.19 |
[STM32G474] 타이머 사용법: HAL API로 타이머 설정 및 코드 예제 (0) | 2025.08.19 |
[STM32G474] I2C, SPI 사용법: HAL API로 설정 및 코드 예제 (0) | 2025.08.19 |
[STM32G474] UART 사용법: HAL API로 UART 설정 및 코드 예제 (0) | 2025.08.19 |
[STM32G474] GPIO 사용법: HAL API로 GPIO 설정 및 코드 예제 (0) | 2025.08.19 |