본문 바로가기
아날로그회로(Analog Circuit)/ADC관련

[PGA302]STM32용 I2C 드라이버 코드 구현(PGA302 I2C Driver Implementation Using STM32)

by linuxgo 2025. 8. 20.
반응형

개요

이 문서는 STM32마이크로컨트롤러에서 I2C 인터페이스를 통해 PGA302 센서 신호 컨디셔너를 제어하는 드라이버 구현 방법을 설명합니다 (This document describes the implementation of a driver for controlling the PGA302 sensor signal conditioner via the I2C interface on the STM32 microcontroller). PGA302는 압력 및 온도 센서 신호를 처리하기 위한 고정밀 아날로그 프론트엔드(AFE) 장치로, STM32Cube HAL 라이브러리를 사용하여 I2C를 통해 레지스터 설정 및 데이터 읽기가 가능합니다 (The PGA302 is a high-precision analog front-end (AFE) device for processing pressure and temperature sensor signals, enabling register configuration and data reading via I2C using the STM32Cube HAL library).

PGA302 사양

PGA302는 Texas Instruments에서 제공하는 저드리프트, 저소음의 프로그래머블 센서 신호 컨디셔너로, 다양한 저항성 브릿지 센서 애플리케이션(압력, 온도, 레벨 감지 등)을 위해 설계되었습니다 (The PGA302 is a low-drift, low-noise programmable sensor signal conditioner from Texas Instruments, designed for various resistive bridge sensor applications (pressure, temperature, level sensing, etc.)). 다음은 PGA302의 주요 사양을 데이터시트를 기반으로 정리한 내용입니다 (The following is a summary of the key specifications of the PGA302 based on the datasheet):

 

PGA302 Simplified Block Diagram

 

Pin Configuration and Functions

주요 특징 (Key Features)

  • 기능 (Functionality): 저항성 브릿지 센서(압력, 온도, 레벨 감지) 및 기타 애플리케이션(유량계, 중량계, 힘 감지, 가속도계, 습도 센서, 전류 감지)을 위한 신호 컨디셔닝 (Signal conditioning for resistive bridge sensors (pressure, temperature, level sensing) and other applications (flow meters, weight scales, force sensing, accelerometers, humidity sensors, current sensing)).
  • 입력 (Input):
    • 두 개의 동일한 아날로그 프론트엔드(AFE) 채널 제공 (Provides two identical analog front-end (AFE) channels).
    • 각 AFE 채널은 최대 200V/V의 프로그래머블 게인 증폭기(PGA) 포함 (Each AFE channel includes a programmable gain amplifier (PGA) up to 200V/V).
    • 한 채널은 센서 오프셋 보상 기능, 다른 채널은 내부 온도 센서 통합 (One channel supports sensor offset compensation, while the other integrates an internal temperature sensor).
    • 16비트 시그마-델타 ADC로 아날로그 입력을 디지털로 변환 (Converts analog inputs to digital using a 16-bit sigma-delta ADC).
  • 출력 (Output):
    • 1.25V, 14비트 DAC와 4V/V 게인의 레이티오메트릭 전압 출력 버퍼로 0~5V 레이티오메트릭 출력 제공 (Provides a 0~5V ratiometric output with a 1.25V, 14-bit DAC and a 4V/V gain ratiometric voltage output buffer).
    • 3차 온도 계수(TC) 및 비선형성(NL) 디지털 보상 알고리즘 구현 (Implements third-order temperature coefficient (TC) and nonlinearity (NL) digital compensation algorithms).
  • 브릿지 여기 (Bridge Excitation):
    • 2.5V 브릿지 여기 전압 제공 (Provides a 2.5V bridge excitation voltage).
    • 최대 1mA까지 프로그래머블 전류 출력 소스 (Programmable current output source up to 1mA).
  • 인터페이스 (Interface):
    • I2C 인터페이스(7비트 주소, 최대 속도 명시되지 않음, 일반적으로 100kHz 또는 400kHz 사용) (I2C interface (7-bit address, maximum speed not specified, typically 100kHz or 400kHz)).
    • One-Wire Interface(OWI)로 전원 라인을 통한 통신 및 최종 시스템 보정 지원 (Supports communication and final system calibration via power line with One-Wire Interface (OWI)).
  • 메모리 (Memory): 통합 EEPROM에 선형화 알고리즘 매개변수 및 사용자 데이터 저장 (Stores linearization algorithm parameters and user data in integrated EEPROM).
  • 진단 (Diagnostics):
    • 여기 출력 소스, AFE 입력, 전원 공급에 대한 진단 기능 (Diagnostic functions for excitation output source, AFE inputs, and power supply).
    • 센서 오픈/쇼트와 같은 시스템 진단 지원 (Supports system diagnostics such as sensor open/short).
  • 지원 센서 유형 (Supported Sensor Types): 피에조저항성, 세라믹 필름, 스트레인 게이지, 스틸 멤브레인 등 (Piezoresistive, ceramic film, strain gauge, steel membrane, etc.).

전기적 특성 (Electrical Characteristics)

  • 동작 전압 (Operating Voltage): 2.7V ~ 5.5V (권장 동작 조건) (2.7V ~ 5.5V (recommended operating condition)).
  • 브릿지 여기 전압 (Bridge Excitation Voltage): 2.5V (고정) (2.5V (fixed)).
  • 전류 소스 (Current Source): 50μA, 100μA, 200μA, 1000μA 프로그래머블 출력 (50μA, 100μA, 200μA, 1000μA programmable output).
  • ADC 해상도 (ADC Resolution): 16비트 (시그마-델타) (16-bit (sigma-delta)).
  • DAC 해상도 (DAC Resolution): 14비트 (14-bit).
  • 게인 범위 (Gain Range): 1.33V/V ~ 200V/V (8단계: 1.33, 2, 4, 10, 20, 40, 100, 200) (1.33V/V ~ 200V/V (8 steps: 1.33, 2, 4, 10, 20, 40, 100, 200)).
  • 오프셋 보상 (Offset Compensation): 0mV ~ 54.75mV (16단계) (0mV ~ 54.75mV (16 steps)).
  • 샘플링 속도 (Sampling Rate): 출력 샘플링 주기 약 96μs (샘플 주기 제어 비트 = 0b00, 디지털 필터 설정에 따라 변동 가능, 특정 레지스터 정보 미제공) (Output sampling period approximately 96μs (sample period control bit = 0b00, may vary depending on digital filter settings, specific register information not provided)).
  • ESD 등급 (ESD Rating): HBM ±2000V, CDM ±500V (HBM ±2000V, CDM ±500V).
  • 동작 온도 (Operating Temperature): -40°C ~ +150°C (-40°C ~ +150°C).

패키지 및 핀 구성 (Package and Pin Configuration)

  • 패키지 (Package): TSSOP-16 (TSSOP-16).
  • 핀 기능 (Pin Functions):
    • VINP, VINN: 브릿지 입력 (압력/온도) (VINP, VINN: Bridge inputs (pressure/temperature)).
    • VOUT: 0~5V 레이티오메트릭 출력 (VOUT: 0~5V ratiometric output).
    • SDA, SCL: I2C 인터페이스 (SDA, SCL: I2C interface).
    • VBRG: 2.5V 브릿지 여기 출력 (VBRG: 2.5V bridge excitation output).
    • VDD, VSS: 전원 및 접지 (VDD, VSS: Power and ground).
    • 기타: 온도 센서, 전류 소스 제어 등 (Others: Temperature sensor, current source control, etc.).

애플리케이션 (Applications)

  • 압력, 온도, 레벨 감지 (Pressure, temperature, level sensing).
  • 유량계, 중량계, 힘 감지(스트레인 게이지 기반) (Flow meters, weight scales, force sensing (strain gauge-based)).
  • 가속도계, 습도 센서, 전류 감지(shunt 기반) (Accelerometers, humidity sensors, current sensing (shunt-based)).

STM32L432KC를 사용한 PGA302 I2C 드라이버 구현(PGA302 I2C Driver Implementation Using STM32L432KC)

하드웨어 요구사항

  • 마이크로컨트롤러 (Microcontroller): STM32L432KC (STM32L432KC).
  • I2C 인터페이스 (I2C Interface): I2C1 (SCL: PB6, SDA: PB7) (I2C1 (SCL: PB6, SDA: PB7)).
  • 선택적 아날로그 입력 (Optional Analog Input): PA0 (GPIO 입력, 선택 사항) (PA0 (GPIO input, optional)).
  • PGA302 장치 (PGA302 Device): I2C 슬레이브 주소 0x42 (기본) (I2C slave address 0x42 (default)).
  • 개발 환경 (Development Environment): STM32CubeMX, STM32CubeIDE 또는 유사한 툴 (STM32CubeMX, STM32CubeIDE, or similar tools).
  • 클럭 설정 (Clock Configuration): 48MHz 시스템 클럭 (I2C 타이밍 값 기준) (48MHz system clock (based on I2C timing values)).

소프트웨어 요구사항

  • STM32Cube HAL 라이브러리 (stm32l4xx_hal.h) (STM32Cube HAL library (stm32l4xx_hal.h)).
  • pga302.h 및 pga302.c 파일 (pga302.h and pga302.c files).
  • STM32CubeMX로 생성된 I2C 및 GPIO 초기화 코드 (I2C and GPIO initialization code generated by STM32CubeMX).

드라이버 설계 개요

드라이버는 다음과 같은 기능을 제공합니다 (The driver provides the following functionalities):

  • I2C를 통한 PGA302 레지스터 읽기/쓰기 (PGA302 register read/write via I2C).
  • 압력 및 온도 게인 설정 (Pressure and temperature gain settings).
  • 온도 모드 및 MUX 제어 (Temperature mode and MUX control).
  • 오프셋 조정 (Offset adjustment).
  • 압력 및 온도 ADC 데이터 읽기 (Pressure and temperature ADC data reading).
  • EEPROM 및 테스트 페이지 액세스 (EEPROM and test page access).

드라이버는 모든 함수에서 I2C_HandleTypeDef *hi2c와 uint8_t slave_address를 인자로 받아 전역 변수 없이 동작합니다 (The driver operates without global variables by taking I2C_HandleTypeDef *hi2c and uint8_t slave_address as arguments in all functions). 설정 간 지연은 pga302_Config 내에서 HAL_Delay(100)로 처리되며, 호출자가 필요 시 추가 지연을 관리할 수 있습니다 (Delays between settings are handled within pga302_Config using HAL_Delay(100), and the caller can manage additional delays if needed). 함수 반환 값은 int 타입으로, 성공 시 0, 오류 시 -1을 반환합니다 (Function return values are of int type, returning 0 on success and -1 on error).

코드 구현

1. 헤더 파일: pga302.h (Header File: pga302.h)

PGA302 레지스터, 설정 값, 함수 프로토타입을 정의하며, 상세한 주석을 추가했습니다 (Defines PGA302 registers, configuration values, and function prototypes with detailed comments).

#ifndef PGA302_H
#define PGA302_H

#ifdef __cplusplus
extern "C" {
#endif

#include "stm32l4xx_hal.h"

// PGA302 드라이버 API 정의
// PGA302 센서 신호 컨디셔너의 I2C 통신 및 설정을 위한 함수 제공
// 저항성 브릿지 센서(압력, 온도 등) 신호 처리 및 0~5V 레이티오메트릭 출력 지원

// 레지스터 정의
#define PGA302_REG_TEST_MICRO_INTERFACE_CONTROL        0x0C // 마이크로 인터페이스 제어 레지스터 (소프트 리셋, 인터페이스 선택)
#define PGA302_REG_TEST_PADC_DATA_1                    0x10 // 압력 ADC 데이터 LSB
#define PGA302_REG_TEST_PADC_DATA_2                    0x11 // 압력 ADC 데이터 MSB
#define PGA302_REG_TEST_TADC_DATA_1                    0x14 // 온도 ADC 데이터 LSB
#define PGA302_REG_TEST_TADC_DATA_2                    0x15 // 온도 ADC 데이터 MSB
#define PGA302_REG_CTRL_STATUS_PSMON_1                 0x58 // 전원 상태 모니터링 레지스터
#define PGA302_REG_CTRL_STATUS_AFEDIAG                 0x5A // 아날로그 프론트엔드 진단 레지스터
#define PGA302_REG_CTRL_STATUS_P_GAIN_SELECT           0x47 // 압력 게인 선택 레지스터
#define PGA302_REG_CTRL_STATUS_T_GAIN_SELECT           0x48 // 온도 게인 선택 및 온도 모드/MUX 제어 레지스터
#define PGA302_REG_CTRL_STATUS_TEMP_CTRL               0x4C // 온도 전류 제어 및 오프셋 조정 레지스터
#define PGA302_REG_CTRL_STATUS_OFFSET_CANCEL           0x4E // 오프셋 캔슬 레지스터
#define PGA302_REG_CTRL_STATUS_DAC_REG0_1              0x30 // DAC 레지스터 0-1 (출력 설정)
#define PGA302_REG_CTRL_STATUS_DAC_REG0_2              0x31 // DAC 레지스터 0-2 (출력 설정)
#define PGA302_REG_CTRL_STATUS_OP_STAGE_CTRL           0x3B // 출력 스테이지 제어 레지스터
#define PGA302_REG_EEPROM_ARRAY_START                  0x00 // EEPROM 배열 시작 주소
#define PGA302_REG_EEPROM_ARRAY_END                    0x7F // EEPROM 배열 끝 주소
#define PGA302_REG_EEPROM_CACHE_BYTE_0                 0x80 // EEPROM 캐시 바이트 0
#define PGA302_REG_EEPROM_CACHE_BYTE_1                 0x81 // EEPROM 캐시 바이트 1
#define PGA302_REG_EEPROM_PAGE_ADDRESS                 0x82 // EEPROM 페이지 주소
#define PGA302_REG_EEPROM_CTRL                         0x83 // EEPROM 제어 레지스터
#define PGA302_REG_EEPROM_CRC                          0x84 // EEPROM CRC 레지스터
#define PGA302_REG_EEPROM_STATUS                       0x85 // EEPROM 상태 레지스터
#define PGA302_REG_EEPROM_CRC_STATUS                   0x86 // EEPROM CRC 상태 레지스터
#define PGA302_REG_EEPROM_CRC_VALUE                    0x87 // EEPROM CRC 값 레지스터

// 설정 값 정의
#define PGA302_SET_IF_SEL_ACCESSES_CONTROLLER          0x00 // 컨트롤러 액세스 (마이크로 인터페이스 제어)
#define PGA302_SET_IF_SEL_ACCESSES_DIGITAL_INTERFACE   0x01 // 디지털 인터페이스 액세스 (I2C/OWI)
#define PGA302_SET_TSEM_MODE_SINGLE_ENDED              0x00 // 단일 입력 온도 모드
#define PGA302_SET_TSEM_MODE_DIFFERENTIAL              0x01 // 차동 입력 온도 모드
#define PGA302_SET_T_MUX_CTRL_EXT_TEMPE                0x00 // 외부 온도 센서 선택
#define PGA302_SET_T_MUX_CTRL_TEST                     0x01 // 테스트 모드 선택
#define PGA302_SET_T_MUX_CTRL_INT_TEMPE                0x02 // 내부 온도 센서 선택
#define PGA302_SET_T_MUX_CTRL_BRIDGE_CURRENT           0x03 // 브릿지 전류 측정
#define PGA302_SET_T_MUX_CTRL_ITEMP                    0x04 // 내부 전류 측정
#define PGA302_SET_GAIN_1_33                           0x00 // 게인 1.33V/V
#define PGA302_SET_GAIN_2                              0x01 // 게인 2V/V
#define PGA302_SET_GAIN_4                              0x02 // 게인 4V/V
#define PGA302_SET_GAIN_10                             0x03 // 게인 10V/V
#define PGA302_SET_GAIN_20                             0x04 // 게인 20V/V
#define PGA302_SET_GAIN_40                             0x05 // 게인 40V/V
#define PGA302_SET_GAIN_100                            0x06 // 게인 100V/V
#define PGA302_SET_GAIN_200                            0x07 // 게인 200V/V
#define PGA302_SET_ITEMP_CTRL_50_mA                    0x00 // 50μA 전류 제어
#define PGA302_SET_ITEMP_CTRL_100_mA                   0x01 // 100μA 전류 제어
#define PGA302_SET_ITEMP_CTRL_200_mA                   0x02 // 200μA 전류 제어
#define PGA302_SET_ITEMP_CTRL_1000_mA                  0x03 // 1000μA 전류 제어
#define PGA302_SET_ITEMP_CTRL_OFF                      0x04 // 전류 제어 끄기
#define PGA302_SET_OFFSET_CANCEL_0_mV                  0x00 // 오프셋 0mV
#define PGA302_SET_OFFSET_CANCEL_3_65_mV               0x01 // 오프셋 3.65mV
#define PGA302_SET_OFFSET_CANCEL_7_3_mV                0x02 // 오프셋 7.3mV
#define PGA302_SET_OFFSET_CANCEL_10_95_mV              0x03 // 오프셋 10.95mV
#define PGA302_SET_OFFSET_CANCEL_14_6_mV               0x04 // 오프셋 14.6mV
#define PGA302_SET_OFFSET_CANCEL_18_28_mV              0x05 // 오프셋 18.28mV
#define PGA302_SET_OFFSET_CANCEL_21_9_mV               0x06 // 오프셋 21.9mV
#define PGA302_SET_OFFSET_CANCEL_25_55_mV              0x07 // 오프셋 25.55mV
#define PGA302_SET_OFFSET_CANCEL_29_2_mV               0x08 // 오프셋 29.2mV
#define PGA302_SET_OFFSET_CANCEL_32_85_mV              0x09 // 오프셋 32.85mV
#define PGA302_SET_OFFSET_CANCEL_36_5_mV               0x0A // 오프셋 36.5mV
#define PGA302_SET_OFFSET_CANCEL_40_15_mV              0x0B // 오프셋 40.15mV
#define PGA302_SET_OFFSET_CANCEL_43_8_mV               0x0C // 오프셋 43.8mV
#define PGA302_SET_OFFSET_CANCEL_47_45_mV              0x0D // 오프셋 47.45mV
#define PGA302_SET_OFFSET_CANCEL_51_1_mV               0x0E // 오프셋 51.1mV
#define PGA302_SET_OFFSET_CANCEL_54_75_mV              0x0F // 오프셋 54.75mV
#define PGA302_SET_OFFSET_CURRENT_VINPN                0x00 // VINP-N 오프셋 전류
#define PGA302_SET_OFFSET_CURRENT_VINPP                0x01 // VINP-P 오프셋 전류
#define PGA302_SET_DEV_ADDR                            0x42 // 기본 I2C 슬레이브 주소
#define PGA302_SET_MEMORY_PAGE_TEST_REG                0x40 // 테스트 레지스터 페이지 주소
#define PGA302_SET_MEMORY_PAGE_CONTROL_AND_STATUS_REG  0x42 // 제어 및 상태 레지스터 페이지 주소
#define PGA302_SET_MEMORY_PAGE_EEPROM_CACHE_CELLS      0x45 // EEPROM 캐시 페이지 주소
#define PGA302_SET_MEMORY_PAGE_CTRL_AND_STATUS_REG     0x47 // 제어 및 상태 레지스터 페이지 주소(대체)

// 비트 마스크 정의
#define PGA302_SOFT_RESET                     0x02 // 소프트 리셋 비트
#define PGA302_P_GAIN_BIT_MASK                0xF8 // 압력 게인 선택 비트 마스크
#define PGA302_T_GAIN_BIT_MASK                0xF8 // 온도 게인 선택 비트 마스크
#define PGA302_TEMP_MODE_BIT_MASK             0xF7 // 온도 모드 선택 비트 마스크
#define PGA302_T_MUX_CTRL_BIT_MASK            0x8F // 온도 MUX 제어 비트 마스크
#define PGA302_ITEMP_CTRL_BIT_MASK            0x8F // 전류 제어 비트 마스크
#define PGA302_OFFSET_BIT_MASK                0x1F // 오프셋 조정 비트 마스크

// 함수 프로토타입
// I2C 및 선택적 아날로그 핀 초기화
// hi2c: I2C 핸들, i2c_speed: I2C 속도(100kHz 또는 400kHz), i2c_address: PGA302 슬레이브 주소,
// an_port: 아날로그 입력 GPIO 포트, an_pin: 아날로그 입력 핀
// 반환: 0(성공), -1(오류)
int pga302_init(I2C_HandleTypeDef *hi2c, uint32_t i2c_speed, uint8_t i2c_address, GPIO_TypeDef *an_port, uint16_t an_pin);

// 기본 설정 적용 (소프트 리셋, 디지털 인터페이스, 게인, 온도 모드, MUX 설정)
// hi2c: I2C 핸들, slave_address: PGA302 슬레이브 주소
// 반환: 0(성공), -1(오류)
int pga302_Config(I2C_HandleTypeDef *hi2c, uint8_t slave_address);

// 범용 레지스터 쓰기
// hi2c: I2C 핸들, slave_address: 슬레이브 주소, reg: 대상 레지스터, tx_buf: 전송 데이터, tx_len: 데이터 길이
// 반환: 0(성공), -1(오류)
int pga302_generic_write(I2C_HandleTypeDef *hi2c, uint8_t slave_address, uint8_t reg, uint8_t *tx_buf, uint8_t tx_len);

// 범용 레지스터 읽기
// hi2c: I2C 핸들, slave_address: 슬레이브 주소, reg: 대상 레지스터, rx_buf: 수신 데이터, rx_len: 데이터 길이
// 반환: 0(성공), -1(오류)
int pga302_generic_read(I2C_HandleTypeDef *hi2c, uint8_t slave_address, uint8_t reg, uint8_t *rx_buf, uint8_t rx_len);

// EEPROM 쓰기
// hi2c: I2C 핸들, slave_address: 슬레이브 주소, reg: 대상 레지스터, tx_buf: 전송 데이터, tx_len: 데이터 길이
// 반환: 0(성공), -1(오류)
int pga302_generic_eeprom_write(I2C_HandleTypeDef *hi2c, uint8_t slave_address, uint8_t reg, uint8_t *tx_buf, uint8_t tx_len);

// EEPROM 읽기
// hi2c: I2C 핸들, slave_address: 슬레이브 주소, reg: 대상 레지스터, rx_buf: 수신 데이터, rx_len: 데이터 길이
// 반환: 0(성공), -1(오류)
int pga302_generic_eeprom_read(I2C_HandleTypeDef *hi2c, uint8_t slave_address, uint8_t reg, uint8_t *rx_buf, uint8_t rx_len);

// 테스트 페이지 쓰기
// hi2c: I2C 핸들, slave_address: 슬레이브 주소, reg: 대상 레지스터, tx_buf: 전송 데이터, tx_len: 데이터 길이
// 반환: 0(성공), -1(오류)
int pga302_generic_test_page_write(I2C_HandleTypeDef *hi2c, uint8_t slave_address, uint8_t reg, uint8_t *tx_buf, uint8_t tx_len);

// 테스트 페이지 읽기
// hi2c: I2C 핸들, slave_address: 슬레이브 주소, reg: 대상 레지스터, rx_buf: 수신 데이터, rx_len: 데이터 길이
// 반환: 0(성공), -1(오류)
int pga302_generic_test_page_read(I2C_HandleTypeDef *hi2c, uint8_t slave_address, uint8_t reg, uint8_t *rx_buf, uint8_t rx_len);

// 메모리 페이지 설정
// hi2c: I2C 핸들, slave_address: 슬레이브 주소 포인터, memory_page: 메모리 페이지 값
// 반환: 0(성공), -1(오류)
int pga302_set_memory_page_slave_addr(I2C_HandleTypeDef *hi2c, uint8_t *slave_address, uint8_t memory_page);

// 컨트롤러 액세스 설정
// hi2c: I2C 핸들, slave_address: 슬레이브 주소
// 반환: 0(성공), -1(오류)
int pga302_accesses_controller(I2C_HandleTypeDef *hi2c, uint8_t slave_address);

// 디지털 인터페이스 액세스 설정
// hi2c: I2C 핸들, slave_address: 슬레이브 주소
// 반환: 0(성공), -1(오류)
int pga302_accesses_digital_interface_control(I2C_HandleTypeDef *hi2c, uint8_t slave_address);

// 소프트 리셋
// hi2c: I2C 핸들, slave_address: 슬레이브 주소
// 반환: 0(성공), -1(오류)
int pga302_soft_reset(I2C_HandleTypeDef *hi2c, uint8_t slave_address);

// 압력 게인 설정
// hi2c: I2C 핸들, slave_address: 슬레이브 주소, p_gain: 게인 값 (0~7)
// 반환: 0(성공), -1(오류)
int pga302_set_p_gain(I2C_HandleTypeDef *hi2c, uint8_t slave_address, uint8_t p_gain);

// 온도 게인 설정
// hi2c: I2C 핸들, slave_address: 슬레이브 주소, t_gain: 게인 값 (0~7)
// 반환: 0(성공), -1(오류)
int pga302_set_t_gain(I2C_HandleTypeDef *hi2c, uint8_t slave_address, uint8_t t_gain);

// 온도 모드 설정
// hi2c: I2C 핸들, slave_address: 슬레이브 주소, t_mode: 온도 모드 (단일/차동)
// 반환: 0(성공), -1(오류)
int pga302_set_temp_mode(I2C_HandleTypeDef *hi2c, uint8_t slave_address, uint8_t t_mode);

// 온도 MUX 제어 설정
// hi2c: I2C 핸들, slave_address: 슬레이브 주소, t_mux_ctrl: MUX 제어 값
// 반환: 0(성공), -1(오류)
int pga302_set_t_mux_ctrl(I2C_HandleTypeDef *hi2c, uint8_t slave_address, uint8_t t_mux_ctrl);

// 전류 제어 설정
// hi2c: I2C 핸들, slave_address: 슬레이브 주소, itemp_ctrl: 전류 제어 값
// 반환: 0(성공), -1(오류)
int pga302_itemp_ctrl(I2C_HandleTypeDef *hi2c, uint8_t slave_address, uint8_t itemp_ctrl);

// 오프셋 설정
// hi2c: I2C 핸들, slave_address: 슬레이브 주소, offset_cancel_val: 오프셋 값, offset_cancel_sel: 오프셋 선택
// 반환: 0(성공), -1(오류)
int pga302_set_offset(I2C_HandleTypeDef *hi2c, uint8_t slave_address, uint8_t offset_cancel_val, uint8_t offset_cancel_sel);

// 압력 ADC 데이터 읽기
// hi2c: I2C 핸들, slave_address: 슬레이브 주소
// 반환: 16비트 ADC 데이터 (오류 시 0)
int16_t pga302_get_p_adc_data(I2C_HandleTypeDef *hi2c, uint8_t slave_address);

// 온도 ADC 데이터 읽기
// hi2c: I2C 핸들, slave_address: 슬레이브 주소
// 반환: 16비트 ADC 데이터 (오류 시 0)
int16_t pga302_get_t_adc_data(I2C_HandleTypeDef *hi2c, uint8_t slave_address);

#ifdef __cplusplus
}
#endif
#endif // PGA302_H

2. 소스 파일: pga302.c

드라이버의 핵심 로직을 구현하며, 상세한 주석을 추가했습니다.

#include "pga302.h"

// pga302_init: PGA302의 I2C 인터페이스 및 선택적 아날로그 입력 핀 초기화
// 매개변수:
// - hi2c: I2C 핸들 (STM32 HAL I2C 구조체)
// - i2c_speed: I2C 통신 속도 (100kHz 또는 400kHz)
// - i2c_address: PGA302의 I2C 슬레이브 주소 (기본: 0x42)
// - an_port: 아날로그 입력 GPIO 포트 (NULL 가능)
// - an_pin: 아날로그 입력 GPIO 핀 (GPIO_PIN_RESET 가능)
// 반환값: 0 (성공), -1 (I2C 초기화 실패)
int pga302_init(I2C_HandleTypeDef *hi2c, uint32_t i2c_speed, uint8_t i2c_address, GPIO_TypeDef *an_port, uint16_t an_pin)
{
    // I2C 설정: I2C1 사용, 7비트 주소 모드, 클럭 스트레칭 비활성화
    hi2c->Instance = I2C1; // I2C1 포트 설정
    hi2c->Init.Timing = (i2c_speed == 100000) ? 0x10808BDF : 0x00D07BFF; // 100kHz 또는 400kHz 타이밍 (48MHz 기준)
    hi2c->Init.OwnAddress1 = 0; // 마스터 모드이므로 자신의 주소 사용 안 함
    hi2c->Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT; // 7비트 주소 모드
    hi2c->Init.DualAddressMode = I2C_DUALADDRESS_DISABLE; // 듀얼 주소 비활성화
    hi2c->Init.OwnAddress2 = 0; // 두 번째 주소 사용 안 함
    hi2c->Init.GeneralCallMode = I2C_GENERALCALL_DISABLE; // 일반 호출 비활성화
    hi2c->Init.NoStretchMode = I2C_NOSTRETCH_DISABLE; // 클럭 스트레칭 활성화

    // I2C 초기화
    if (HAL_I2C_Init(hi2c) != HAL_OK) {
        return -1; // 초기화 실패 시 오류 반환
    }

    // 아날로그 핀 설정 (선택적)
    if (an_port != NULL && an_pin != GPIO_PIN_RESET) {
        GPIO_InitTypeDef GPIO_InitStruct = {0}; // GPIO 설정 구조체 초기화
        GPIO_InitStruct.Pin = an_pin; // 핀 번호 설정 (예: PA0)
        GPIO_InitStruct.Mode = GPIO_MODE_INPUT; // 입력 모드
        GPIO_InitStruct.Pull = GPIO_NOPULL; // 풀업/풀다운 없음
        HAL_GPIO_Init(an_port, &GPIO_InitStruct); // GPIO 초기화
    }

    return 0; // 성공
}

// pga302_Config: PGA302의 기본 설정 적용 (소프트 리셋, 디지털 인터페이스, 게인, 온도 모드, MUX 설정)
// 매개변수:
// - hi2c: I2C 핸들
// - slave_address: PGA302 슬레이브 주소
// 반환값: 0 (성공), -1 (설정 실패)
int pga302_Config(I2C_HandleTypeDef *hi2c, uint8_t slave_address)
{
    // 1. 소프트 리셋 수행
    if (pga302_soft_reset(hi2c, slave_address) != 0) return -1;
    HAL_Delay(100); // 리셋 후 안정화 대기 (100ms)

    // 2. 디지털 인터페이스(I2C/OWI) 활성화
    if (pga302_accesses_digital_interface_control(hi2c, slave_address) != 0) return -1;
    HAL_Delay(100); // 설정 적용 대기

    // 3. 압력 게인 설정 (200V/V)
    if (pga302_set_p_gain(hi2c, slave_address, PGA302_SET_GAIN_200) != 0) return -1;
    HAL_Delay(100); // 설정 적용 대기

    // 4. 온도 게인 설정 (200V/V)
    if (pga302_set_t_gain(hi2c, slave_address, PGA302_SET_GAIN_200) != 0) return -1;
    HAL_Delay(100); // 설정 적용 대기

    // 5. 차동 온도 모드 설정
    if (pga302_set_temp_mode(hi2c, slave_address, PGA302_SET_TSEM_MODE_DIFFERENTIAL) != 0) return -1;
    HAL_Delay(100); // 설정 적용 대기

    // 6. 내부 온도 센서 선택
    if (pga302_set_t_mux_ctrl(hi2c, slave_address, PGA302_SET_T_MUX_CTRL_INT_TEMPE) != 0) return -1;
    HAL_Delay(100); // 설정 적용 대기

    return 0; // 모든 설정 성공
}

// pga302_generic_write: PGA302 레지스터에 데이터 쓰기
// 매개변수:
// - hi2c: I2C 핸들
// - slave_address: 슬레이브 주소
// - reg: 대상 레지스터 주소
// - tx_buf: 전송할 데이터 버퍼
// - tx_len: 전송 데이터 길이
// 반환값: 0 (성공), -1 (I2C 전송 실패)
int pga302_generic_write(I2C_HandleTypeDef *hi2c, uint8_t slave_address, uint8_t reg, uint8_t *tx_buf, uint8_t tx_len)
{
    uint8_t data_buf[257]; // 레지스터 주소 + 데이터 (최대 256바이트 데이터 + 1바이트 주소)
    data_buf[0] = reg; // 첫 바이트는 레지스터 주소
    for (uint8_t cnt = 0; cnt < tx_len; cnt++) {
        data_buf[cnt + 1] = tx_buf[cnt]; // 데이터 복사
    }
    // I2C 마스터 전송 (슬레이브 주소는 7비트로 왼쪽 시프트)
    if (HAL_I2C_Master_Transmit(hi2c, slave_address << 1, data_buf, tx_len + 1, HAL_MAX_DELAY) != HAL_OK) {
        return -1; // 전송 실패
    }
    return 0; // 성공
}

// pga302_generic_read: PGA302 레지스터에서 데이터 읽기
// 매개변수:
// - hi2c: I2C 핸들
// - slave_address: 슬레이브 주소
// - reg: 대상 레지스터 주소
// - rx_buf: 수신 데이터 저장 버퍼
// - rx_len: 수신 데이터 길이
// 반환값: 0 (성공), -1 (I2C 전송/수신 실패)
int pga302_generic_read(I2C_HandleTypeDef *hi2c, uint8_t slave_address, uint8_t reg, uint8_t *rx_buf, uint8_t rx_len)
{
    // 1. 레지스터 주소 전송
    if (HAL_I2C_Master_Transmit(hi2c, slave_address << 1, &reg, 1, HAL_MAX_DELAY) != HAL_OK) {
        return -1; // 주소 전송 실패
    }
    // 2. 데이터 수신
    if (HAL_I2C_Master_Receive(hi2c, slave_address << 1, rx_buf, rx_len, HAL_MAX_DELAY) != HAL_OK) {
        return -1; // 데이터 수신 실패
    }
    return 0; // 성공
}

// pga302_generic_eeprom_write: EEPROM에 데이터 쓰기
// 매개변수:
// - hi2c: I2C 핸들
// - slave_address: 슬레이브 주소
// - reg: 대상 EEPROM 레지스터
// - tx_buf: 전송 데이터
// - tx_len: 데이터 길이
// 반환값: 0 (성공), -1 (오류)
int pga302_generic_eeprom_write(I2C_HandleTypeDef *hi2c, uint8_t slave_address, uint8_t reg, uint8_t *tx_buf, uint8_t tx_len)
{
    uint8_t temp_slave_address = slave_address; // 임시 슬레이브 주소
    // EEPROM 캐시 페이지 설정
    if (pga302_set_memory_page_slave_addr(hi2c, &temp_slave_address, PGA302_SET_MEMORY_PAGE_EEPROM_CACHE_CELLS) != 0) return -1;
    // 데이터 쓰기
    return pga302_generic_write(hi2c, temp_slave_address, reg, tx_buf, tx_len);
}

// pga302_generic_eeprom_read: EEPROM에서 데이터 읽기
// 매개변수:
// - hi2c: I2C 핸들
// - slave_address: 슬레이브 주소
// - reg: 대상 EEPROM 레지스터
// - rx_buf: 수신 데이터 저장 버퍼
// - rx_len: 데이터 길이
// 반환값: 0 (성공), -1 (오류)
int pga302_generic_eeprom_read(I2C_HandleTypeDef *hi2c, uint8_t slave_address, uint8_t reg, uint8_t *rx_buf, uint8_t rx_len)
{
    uint8_t temp_slave_address = slave_address; // 임시 슬레이브 주소
    // EEPROM 캐시 페이지 설정
    if (pga302_set_memory_page_slave_addr(hi2c, &temp_slave_address, PGA302_SET_MEMORY_PAGE_EEPROM_CACHE_CELLS) != 0) return -1;
    // 데이터 읽기
    return pga302_generic_read(hi2c, temp_slave_address, reg, rx_buf, rx_len);
}

// pga302_generic_test_page_write: 테스트 페이지에 데이터 쓰기
// 매개변수:
// - hi2c: I2C 핸들
// - slave_address: 슬레이브 주소
// - reg: 대상 테스트 페이지 레지스터
// - tx_buf: 전송 데이터
// - tx_len: 데이터 길이
// 반환값: 0 (성공), -1 (오류)
int pga302_generic_test_page_write(I2C_HandleTypeDef *hi2c, uint8_t slave_address, uint8_t reg, uint8_t *tx_buf, uint8_t tx_len)
{
    uint8_t temp_slave_address = slave_address; // 임시 슬레이브 주소
    // 테스트 레지스터 페이지 설정
    if (pga302_set_memory_page_slave_addr(hi2c, &temp_slave_address, PGA302_SET_MEMORY_PAGE_TEST_REG) != 0) return -1;
    // 데이터 쓰기
    return pga302_generic_write(hi2c, temp_slave_address, reg, tx_buf, tx_len);
}

// pga302_generic_test_page_read: 테스트 페이지에서 데이터 읽기
// 매개변수:
// - hi2c: I2C 핸들
// - slave_address: 슬레이브 주소
// - reg: 대상 테스트 페이지 레지스터
// - rx_buf: 수신 데이터 저장 버퍼
// - rx_len: 데이터 길이
// 반환값: 0 (성공), -1 (오류)
int pga302_generic_test_page_read(I2C_HandleTypeDef *hi2c, uint8_t slave_address, uint8_t reg, uint8_t *rx_buf, uint8_t rx_len)
{
    uint8_t temp_slave_address = slave_address; // 임시 슬레이브 주소
    // 테스트 레지스터 페이지 설정
    if (pga302_set_memory_page_slave_addr(hi2c, &temp_slave_address, PGA302_SET_MEMORY_PAGE_TEST_REG) != 0) return -1;
    // 데이터 읽기
    return pga302_generic_read(hi2c, temp_slave_address, reg, rx_buf, rx_len);
}

// pga302_set_memory_page_slave_addr: 메모리 페이지 설정 및 슬레이브 주소 업데이트
// 매개변수:
// - hi2c: I2C 핸들
// - slave_address: 슬레이브 주소 포인터 (업데이트됨)
// - memory_page: 설정할 메모리 페이지 (테스트, 제어/상태, EEPROM 등)
// 반환값: 0 (성공), -1 (잘못된 페이지)
int pga302_set_memory_page_slave_addr(I2C_HandleTypeDef *hi2c, uint8_t *slave_address, uint8_t memory_page)
{
    // 유효한 메모리 페이지인지 확인
    if ((memory_page == PGA302_SET_MEMORY_PAGE_TEST_REG) ||
        (memory_page == PGA302_SET_MEMORY_PAGE_CONTROL_AND_STATUS_REG) ||
        (memory_page == PGA302_SET_MEMORY_PAGE_EEPROM_CACHE_CELLS) ||
        (memory_page == PGA302_SET_MEMORY_PAGE_CTRL_AND_STATUS_REG)) {
        *slave_address = memory_page; // 슬레이브 주소를 메모리 페이지로 업데이트
        return 0; // 성공
    }
    return -1; // 잘못된 페이지
}

// pga302_accesses_controller: 컨트롤러 액세스 설정
// 매개변수:
// - hi2c: I2C 핸들
// - slave_address: 슬레이브 주소
// 반환값: 0 (성공), -1 (오류)
int pga302_accesses_controller(I2C_HandleTypeDef *hi2c, uint8_t slave_address)
{
    uint8_t tx_buf[1] = {PGA302_SET_IF_SEL_ACCESSES_CONTROLLER}; // 컨트롤러 액세스 설정값
    uint8_t temp_slave_address = slave_address; // 임시 슬레이브 주소
    // 테스트 레지스터 페이지 설정
    if (pga302_set_memory_page_slave_addr(hi2c, &temp_slave_address, PGA302_SET_MEMORY_PAGE_TEST_REG) != 0) return -1;
    // 인터페이스 제어 레지스터에 쓰기
    return pga302_generic_write(hi2c, temp_slave_address, PGA302_REG_TEST_MICRO_INTERFACE_CONTROL, tx_buf, 1);
}

// pga302_accesses_digital_interface_control: 디지털 인터페이스(I2C/OWI) 액세스 설정
// 매개변수:
// - hi2c: I2C 핸들
// - slave_address: 슬레이브 주소
// 반환값: 0 (성공), -1 (오류)
int pga302_accesses_digital_interface_control(I2C_HandleTypeDef *hi2c, uint8_t slave_address)
{
    uint8_t tx_buf[1] = {PGA302_SET_IF_SEL_ACCESSES_DIGITAL_INTERFACE}; // 디지털 인터페이스 설정값
    uint8_t temp_slave_address = slave_address; // 임시 슬레이브 주소
    // 테스트 레지스터 페이지 설정
    if (pga302_set_memory_page_slave_addr(hi2c, &temp_slave_address, PGA302_SET_MEMORY_PAGE_TEST_REG) != 0) return -1;
    // 인터페이스 제어 레지스터에 쓰기
    return pga302_generic_write(hi2c, temp_slave_address, PGA302_REG_TEST_MICRO_INTERFACE_CONTROL, tx_buf, 1);
}

// pga302_soft_reset: PGA302 소프트 리셋 수행
// 매개변수:
// - hi2c: I2C 핸들
// - slave_address: 슬레이브 주소
// 반환값: 0 (성공), -1 (오류)
int pga302_soft_reset(I2C_HandleTypeDef *hi2c, uint8_t slave_address)
{
    uint8_t tx_buf[1] = {PGA302_SOFT_RESET}; // 소프트 리셋 명령
    uint8_t temp_slave_address = slave_address; // 임시 슬레이브 주소
    // 테스트 레지스터 페이지 설정
    if (pga302_set_memory_page_slave_addr(hi2c, &temp_slave_address, PGA302_SET_MEMORY_PAGE_TEST_REG) != 0) return -1;
    // 인터페이스 제어 레지스터에 리셋 명령 쓰기
    return pga302_generic_write(hi2c, temp_slave_address, PGA302_REG_TEST_MICRO_INTERFACE_CONTROL, tx_buf, 1);
}

// pga302_set_p_gain: 압력 게인 설정
// 매개변수:
// - hi2c: I2C 핸들
// - slave_address: 슬레이브 주소
// - p_gain: 압력 게인 값 (0~7, 1.33~200V/V)
// 반환값: 0 (성공), -1 (잘못된 게인 또는 I2C 오류)
int pga302_set_p_gain(I2C_HandleTypeDef *hi2c, uint8_t slave_address, uint8_t p_gain)
{
    if (p_gain < 8) { // 유효한 게인 값인지 확인
        uint8_t rx_buf; // 현재 레지스터 값 저장
        uint8_t temp_slave_address = slave_address; // 임시 슬레이브 주소
        // 제어/상태 페이지 설정
        if (pga302_set_memory_page_slave_addr(hi2c, &temp_slave_address, PGA302_SET_MEMORY_PAGE_CONTROL_AND_STATUS_REG) != 0) return -1;
        // 현재 압력 게인 레지스터 읽기
        if (pga302_generic_read(hi2c, temp_slave_address, PGA302_REG_CTRL_STATUS_P_GAIN_SELECT, &rx_buf, 1) != 0) return -1;
        rx_buf &= PGA302_P_GAIN_BIT_MASK; // 기존 비트 마스크 적용
        rx_buf |= p_gain; // 새로운 게인 값 적용
        // 업데이트된 값 쓰기
        if (pga302_generic_write(hi2c, temp_slave_address, PGA302_REG_CTRL_STATUS_P_GAIN_SELECT, &rx_buf, 1) != 0) return -1;
        return 0; // 성공
    }
    return -1; // 잘못된 게인 값
}

// pga302_set_t_gain: 온도 게인 설정
// 매개변수:
// - hi2c: I2C 핸들
// - slave_address: 슬레이브 주소
// - t_gain: 온도 게인 값 (0~7, 1.33~200V/V)
// 반환값: 0 (성공), -1 (잘못된 게인 또는 I2C 오류)
int pga302_set_t_gain(I2C_HandleTypeDef *hi2c, uint8_t slave_address, uint8_t t_gain)
{
    if (t_gain < 8) { // 유효한 게인 값인지 확인
        uint8_t rx_buf; // 현재 레지스터 값 저장
        uint8_t temp_slave_address = slave_address; // 임시 슬레이브 주소
        // 제어/상태 페이지 설정
        if (pga302_set_memory_page_slave_addr(hi2c, &temp_slave_address, PGA302_SET_MEMORY_PAGE_CONTROL_AND_STATUS_REG) != 0) return -1;
        // 현재 온도 게인 레지스터 읽기
        if (pga302_generic_read(hi2c, temp_slave_address, PGA302_REG_CTRL_STATUS_T_GAIN_SELECT, &rx_buf, 1) != 0) return -1;
        rx_buf &= PGA302_T_GAIN_BIT_MASK; // 기존 비트 마스크 적용
        rx_buf |= t_gain; // 새로운 게인 값 적용
        // 업데이트된 값 쓰기
        if (pga302_generic_write(hi2c, temp_slave_address, PGA302_REG_CTRL_STATUS_T_GAIN_SELECT, &rx_buf, 1) != 0) return -1;
        return 0; // 성공
    }
    return -1; // 잘못된 게인 값
}

// pga302_set_temp_mode: 온도 모드 설정 (단일/차동)
// 매개변수:
// - hi2c: I2C 핸들
// - slave_address: 슬레이브 주소
// - t_mode: 온도 모드 (0: 단일, 1: 차동)
// 반환값: 0 (성공), -1 (잘못된 모드 또는 I2C 오류)
int pga302_set_temp_mode(I2C_HandleTypeDef *hi2c, uint8_t slave_address, uint8_t t_mode)
{
    if (t_mode == PGA302_SET_TSEM_MODE_SINGLE_ENDED || t_mode == PGA302_SET_TSEM_MODE_DIFFERENTIAL) {
        uint8_t rx_buf; // 현재 레지스터 값 저장
        uint8_t temp_slave_address = slave_address; // 임시 슬레이브 주소
        // 제어/상태 페이지 설정
        if (pga302_set_memory_page_slave_addr(hi2c, &temp_slave_address, PGA302_SET_MEMORY_PAGE_CONTROL_AND_STATUS_REG) != 0) return -1;
        // 현재 온도 게인 레지스터 읽기 (온도 모드는 동일 레지스터에 저장)
        if (pga302_generic_read(hi2c, temp_slave_address, PGA302_REG_CTRL_STATUS_T_GAIN_SELECT, &rx_buf, 1) != 0) return -1;
        rx_buf &= PGA302_TEMP_MODE_BIT_MASK; // 기존 비트 마스크 적용
        t_mode <<= 3; // 비트 위치 조정
        rx_buf |= t_mode; // 새로운 모드 적용
        // 업데이트된 값 쓰기
        if (pga302_generic_write(hi2c, temp_slave_address, PGA302_REG_CTRL_STATUS_T_GAIN_SELECT, &rx_buf, 1) != 0) return -1;
        return 0; // 성공
    }
    return -1; // 잘못된 모드
}

// pga302_set_t_mux_ctrl: 온도 MUX 제어 설정
// 매개변수:
// - hi2c: I2C 핸들
// - slave_address: 슬레이브 주소
// - t_mux_ctrl: MUX 제어 값 (외부/내부 온도, 테스트 등)
// 반환값: 0 (성공), -1 (잘못된 MUX 값 또는 I2C 오류)
int pga302_set_t_mux_ctrl(I2C_HandleTypeDef *hi2c, uint8_t slave_address, uint8_t t_mux_ctrl)
{
    if (t_mux_ctrl <= PGA302_SET_T_MUX_CTRL_ITEMP) { // 유효한 MUX 값인지 확인
        uint8_t rx_buf; // 현재 레지스터 값 저장
        uint8_t temp_slave_address = slave_address; // 임시 슬레이브 주소
        // 제어/상태 페이지 설정
        if (pga302_set_memory_page_slave_addr(hi2c, &temp_slave_address, PGA302_SET_MEMORY_PAGE_CONTROL_AND_STATUS_REG) != 0) return -1;
        // 현재 온도 게인 레지스터 읽기 (MUX 제어는 동일 레지스터에 저장)
        if (pga302_generic_read(hi2c, temp_slave_address, PGA302_REG_CTRL_STATUS_T_GAIN_SELECT, &rx_buf, 1) != 0) return -1;
        rx_buf &= PGA302_T_MUX_CTRL_BIT_MASK; // 기존 비트 마스크 적용
        t_mux_ctrl <<= 4; // 비트 위치 조정
        rx_buf |= t_mux_ctrl; // 새로운 MUX 값 적용
        // 업데이트된 값 쓰기
        if (pga302_generic_write(hi2c, temp_slave_address, PGA302_REG_CTRL_STATUS_T_GAIN_SELECT, &rx_buf, 1) != 0) return -1;
        return 0; // 성공
    }
    return -1; // 잘못된 MUX 값
}

// pga302_itemp_ctrl: 온도 센서 전류 제어 설정
// 매개변수:
// - hi2c: I2C 핸들
// - slave_address: 슬레이브 주소
// - itemp_ctrl: 전류 제어 값 (50μA~1000μA 또는 끄기)
// 반환값: 0 (성공), -1 (잘못된 전류 값 또는 I2C 오류)
int pga302_itemp_ctrl(I2C_HandleTypeDef *hi2c, uint8_t slave_address, uint8_t itemp_ctrl)
{
    if (itemp_ctrl < 5) { // 유효한 전류 제어 값인지 확인
        uint8_t rx_buf; // 현재 레지스터 값 저장
        uint8_t temp_slave_address = slave_address; // 임시 슬레이브 주소
        // 제어/상태 페이지 설정
        if (pga302_set_memory_page_slave_addr(hi2c, &temp_slave_address, PGA302_SET_MEMORY_PAGE_CONTROL_AND_STATUS_REG) != 0) return -1;
        // 현재 온도 제어 레지스터 읽기
        if (pga302_generic_read(hi2c, temp_slave_address, PGA302_REG_CTRL_STATUS_TEMP_CTRL, &rx_buf, 1) != 0) return -1;
        rx_buf &= PGA302_ITEMP_CTRL_BIT_MASK; // 기존 비트 마스크 적용
        itemp_ctrl <<= 4; // 비트 위치 조정
        rx_buf |= itemp_ctrl; // 새로운 전류 값 적용
        // 업데이트된 값 쓰기
        if (pga302_generic_write(hi2c, temp_slave_address, PGA302_REG_CTRL_STATUS_TEMP_CTRL, &rx_buf, 1) != 0) return -1;
        return 0; // 성공
    }
    return -1; // 잘못된 전류 값
}

// pga302_set_offset: 오프셋 보상 설정
// 매개변수:
// - hi2c: I2C 핸들
// - slave_address: 슬레이브 주소
// - offset_cancel_val: 오프셋 값 (0~54.75mV, 16단계)
// - offset_cancel_sel: 오프셋 선택 (VINP-N 또는 VINP-P)
// 반환값: 0 (성공), -1 (잘못된 오프셋 값 또는 I2C 오류)
int pga302_set_offset(I2C_HandleTypeDef *hi2c, uint8_t slave_address, uint8_t offset_cancel_val, uint8_t offset_cancel_sel)
{
    if (offset_cancel_val < 16 && offset_cancel_sel < 2) { // 유효한 오프셋 값과 선택인지 확인
        uint8_t rx_buf; // 현재 레지스터 값 저장
        uint8_t temp_slave_address = slave_address; // 임시 슬레이브 주소
        // 제어/상태 페이지 설정
        if (pga302_set_memory_page_slave_addr(hi2c, &temp_slave_address, PGA302_SET_MEMORY_PAGE_CONTROL_AND_STATUS_REG) != 0) return -1;
        // 현재 온도 제어 레지스터 읽기 (오프셋은 동일 레지스터에 저장)
        if (pga302_generic_read(hi2c, temp_slave_address, PGA302_REG_CTRL_STATUS_TEMP_CTRL, &rx_buf, 1) != 0) return -1;
        rx_buf &= PGA302_OFFSET_BIT_MASK; // 기존 비트 마스크 적용
        offset_cancel_sel <<= 4; // 오프셋 선택 비트 위치 조정
        rx_buf |= offset_cancel_sel; // 오프셋 선택 적용
        rx_buf |= offset_cancel_val; // 오프셋 값 적용
        // 업데이트된 값 쓰기
        if (pga302_generic_write(hi2c, temp_slave_address, PGA302_REG_CTRL_STATUS_TEMP_CTRL, &rx_buf, 1) != 0) return -1;
        return 0; // 성공
    }
    return -1; // 잘못된 오프셋 값 또는 선택
}

// pga302_get_p_adc_data: 압력 ADC 데이터 읽기
// 매개변수:
// - hi2c: I2C 핸들
// - slave_address: 슬레이브 주소
// 반환값: 16비트 압력 ADC 데이터 (오류 시 0)
int16_t pga302_get_p_adc_data(I2C_HandleTypeDef *hi2c, uint8_t slave_address)
{
    uint8_t lsb, msb; // LSB와 MSB 데이터
    int16_t result; // 최종 16비트 데이터
    uint8_t temp_slave_address = slave_address; // 임시 슬레이브 주소
    // 테스트 레지스터 페이지 설정
    if (pga302_set_memory_page_slave_addr(hi2c, &temp_slave_address, PGA302_SET_MEMORY_PAGE_TEST_REG) != 0) return 0;
    // 압력 ADC 데이터 LSB 읽기
    if (pga302_generic_read(hi2c, temp_slave_address, PGA302_REG_TEST_PADC_DATA_1, &lsb, 1) != 0) return 0;
    // 압력 ADC 데이터 MSB 읽기
    if (pga302_generic_read(hi2c, temp_slave_address, PGA302_REG_TEST_PADC_DATA_2, &msb, 1) != 0) return 0;
    result = msb; // MSB를 상위 8비트로 설정
    result <<= 8; // 8비트 왼쪽 시프트
    result |= lsb; // LSB를 하위 8비트로 결합
    return result; // 16비트 데이터 반환
}

// pga302_get_t_adc_data: 온도 ADC 데이터 읽기
// 매개변수:
// - hi2c: I2C 핸들
// - slave_address: 슬레이브 주소
// 반환값: 16비트 온도 ADC 데이터 (오류 시 0)
int16_t pga302_get_t_adc_data(I2C_HandleTypeDef *hi2c, uint8_t slave_address)
{
    uint8_t lsb, msb; // LSB와 MSB 데이터
    int16_t result; // 최종 16비트 데이터
    uint8_t temp_slave_address = slave_address; // 임시 슬레이브 주소
    // 테스트 레지스터 페이지 설정
    if (pga302_set_memory_page_slave_addr(hi2c, &temp_slave_address, PGA302_SET_MEMORY_PAGE_TEST_REG) != 0) return 0;
    // 온도 ADC 데이터 LSB 읽기
    if (pga302_generic_read(hi2c, temp_slave_address, PGA302_REG_TEST_TADC_DATA_1, &lsb, 1) != 0) return 0;
    // 온도 ADC 데이터 MSB 읽기
    if (pga302_generic_read(hi2c, temp_slave_address, PGA302_REG_TEST_TADC_DATA_2, &msb, 1) != 0) return 0;
    result = msb; // MSB를 상위 8비트로 설정
    result <<= 8; // 8비트 왼쪽 시프트
    result |= lsb; // LSB를 하위 8비트로 결합
    return result; // 16비트 데이터 반환
}

STM32CubeMX 설정

I2C 설정 (I2C Configuration):

  • I2C1 활성화 (SCL: PB6, SDA: PB7) (Enable I2C1 (SCL: PB6, SDA: PB7)).
  • 속도: 100kHz (타이밍 값: 0x10808BDF, 48MHz 클럭 기준) 또는 400kHz (0x00D07BFF) (Speed: 100kHz (timing value: 0x10808BDF, based on 48MHz clock) or 400kHz (0x00D07BFF)).
  • 주소 모드: 7비트, 나머지 설정은 기본값 (Address mode: 7-bit, other settings at default).

GPIO 설정 (선택적) (GPIO Configuration (Optional)):

  • PA0을 입력 모드로 설정 (풀업/풀다운 없음) (Set PA0 to input mode (no pull-up/pull-down)).
  • 사용하지 않을 경우 pga302_init 호출 시 an_port=NULL, an_pin=GPIO_PIN_RESET으로 설정 (If not used, set an_port=NULL and an_pin=GPIO_PIN_RESET when calling pga302_init).

클럭 설정 (Clock Configuration):

  • 시스템 클럭: 48MHz (I2C 타이밍 값 기준) (System clock: 48MHz (based on I2C timing values)).
  • I2C 클럭 활성화: __HAL_RCC_I2C1_CLK_ENABLE() (Enable I2C clock: __HAL_RCC_I2C1_CLK_ENABLE()).

프로젝트 설정 (Project Configuration):

  • STM32CubeMX로 프로젝트 생성 후 stm32l4xx_hal.h 포함 (Generate project with STM32CubeMX and include stm32l4xx_hal.h).
  • pga302.h와 pga302.c를 프로젝트에 추가 (Add pga302.h and pga302.c to the project).

사용 예제

다음은 드라이버를 사용하여 PGA302를 초기화하고 압력 및 온도 ADC 데이터를 읽는 예제 코드입니다 (The following is example code for initializing the PGA302 and reading pressure and temperature ADC data using the driver).

#include "pga302.h"

I2C_HandleTypeDef hi2c1; // 전역 I2C 핸들 선언

// 시스템 클럭 설정 함수 (STM32CubeMX에서 생성)
void SystemClock_Config(void); // 사용자 정의 필요

int main(void)
{
    HAL_Init(); // HAL 라이브러리 초기화
    SystemClock_Config(); // 시스템 클럭 설정 (48MHz 기준)

    // I2C 초기화
    hi2c1.Instance = I2C1; // I2C1 포트 사용
    hi2c1.Init.Timing = 0x10808BDF; // 100kHz, 48MHz 클럭 기준
    hi2c1.Init.OwnAddress1 = 0; // 마스터 모드
    hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT; // 7비트 주소
    hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE; // 듀얼 주소 비활성화
    hi2c1.Init.OwnAddress2 = 0; // 두 번째 주소 사용 안 함
    hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE; // 일반 호출 비활성화
    hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE; // 클럭 스트레칭 활성화
    if (HAL_I2C_Init(&hi2c1) != HAL_OK) {
        while (1); // I2C 초기화 실패 시 무한 루프
    }

    // PGA302 초기화 (PA0 사용)
    if (pga302_init(&hi2c1, 100000, PGA302_SET_DEV_ADDR, GPIOA, GPIO_PIN_0) != 0) {
        while (1); // 초기화 실패 시 무한 루프
    }

    // PGA302 기본 설정 적용
    if (pga302_Config(&hi2c1, PGA302_SET_DEV_ADDR) != 0) {
        while (1); // 설정 실패 시 무한 루프
    }

    // 메인 루프
    while (1) {
        // 압력 ADC 데이터 읽기
        int16_t p_adc = pga302_get_p_adc_data(&hi2c1, PGA302_SET_DEV_ADDR);
        // 온도 ADC 데이터 읽기
        int16_t t_adc = pga302_get_t_adc_data(&hi2c1, PGA302_SET_DEV_ADDR);
        // 데이터 처리 (예: 시리얼 출력, 디스플레이 등)
        HAL_Delay(1000); // 1초 대기
    }
}

코드 구현 상세 설명

  1. 초기화 (pga302_init) (Initialization (pga302_init)):
    •   I2C1을 설정하고, 선택적 아날로그 핀(PA0)을 초기화합니다 (Configures I2C1 and initializes the optional analog pin (PA0)).
    •   I2C 속도는 100kHz(0x10808BDF) 또는 400kHz(0x00D07BFF)로 설정됩니다 (I2C speed is set to 100kHz (0x10808BDF) or 400kHz (0x00D07BFF)).
    •   성공 시 0, 실패 시 -1을 반환합니다 (Returns 0 on success, -1 on failure).
  2. 기본 설정 (pga302_Config) (Default Configuration (pga302_Config)):
    •   소프트 리셋, 디지털 인터페이스 액세스, 압력/온도 게인(200V/V), 차동 온도 모드, 내부 온도 센서 설정을 순차적으로 적용합니다 (Applies soft reset, digital interface access, pressure/temperature gain (200V/V), differential temperature mode, and internal temperature sensor settings sequentially).
    •   각 설정 사이에 HAL_Delay(100)로 100ms 지연을 추가합니다 (Adds a 100ms delay with HAL_Delay(100) between each setting).
    •   hi2c와 slave_address를 인자로 받아 전역 변수 없이 동작합니다 (Operates without global variables by taking hi2c and slave_address as arguments).
    •   성공 시 0, 실패 시 -1을 반환합니다 (Returns 0 on success, -1 on failure).
  3. I2C 읽기/쓰기 (pga302_generic_read, pga302_generic_write) (I2C Read/Write (pga302_generic_read, pga302_generic_write)):
    •   HAL 라이브러리의 HAL_I2C_Master_Transmit와 HAL_I2C_Master_Receive를 사용합니다 (Uses HAL_I2C_Master_Transmit and HAL_I2C_Master_Receive from the HAL library).
    •   슬레이브 주소는 7비트로 왼쪽 시프트(<< 1) 처리합니다 (The slave address is 7-bit and left-shifted (<< 1)).
    •   성공 시 0, 실패 시 -1을 반환합니다 (Returns 0 on success, -1 on failure).
  4. EEPROM 및 테스트 페이지 접근 (EEPROM and Test Page Access):
    •   pga302_generic_eeprom_read/write와 pga302_generic_test_page_read/write는 메모리 페이지 설정 후 읽기/쓰기를 수행합니다 (pga302_generic_eeprom_read/write and pga302_generic_test_page_read/write perform read/write after setting the memory page).
    •   페이지 설정은 pga302_set_memory_page_slave_addr로 처리합니다 (Page setting is handled by pga302_set_memory_page_slave_addr).
  5. 설정 함수 (Configuration Functions):
    •   pga302_set_p_gain, pga302_set_t_gain: 압력 및 온도 게인 설정(1.33~200V/V) (pga302_set_p_gain, pga302_set_t_gain: Set pressure and temperature gain (1.33~200V/V)).
    •   pga302_set_temp_mode: 단일/차동 온도 모드 설정 (pga302_set_temp_mode: Set single-ended/differential temperature mode).
    •   pga302_set_t_mux_ctrl: 온도 MUX 제어(외부/내부 센서 등) (pga302_set_t_mux_ctrl: Temperature MUX control (external/internal sensor, etc.)).
    •   pga302_itemp_ctrl: 전류 제어(50μA~1000μA 또는 끄기) (pga302_itemp_ctrl: Current control (50μA~1000μA or off)).
    •   pga302_set_offset: 오프셋 조정(0~54.75mV) (pga302_set_offset: Offset adjustment (0~54.75mV)).
    •   모든 함수는 성공 시 0, 실패 시 -1을 반환합니다 (All functions return 0 on success, -1 on failure).
  6. 데이터 읽기 (Data Reading):
    •   pga302_get_p_adc_data, pga302_get_t_adc_data: 16비트 압력 및 온도 ADC 데이터를 읽어 반환합니다 (pga302_get_p_adc_data, pga302_get_t_adc_data: Read and return 16-bit pressure and temperature ADC data).
    •   오류 발생 시 0을 반환합니다 (데이터 무효) (Returns 0 on error (invalid data)).

주의사항 (Precautions)

  • I2C 타이밍 (I2C Timing): 0x10808BDF(100kHz)와 0x00D07BFF(400kHz)는 48MHz 클럭 기준입니다. STM32CubeMX로 시스템 클럭에 맞게 조정하세요 (0x10808BDF (100kHz) and 0x00D07BFF (400kHz) are based on a 48MHz clock. Adjust with STM32CubeMX for the system clock).
  • 아날로그 핀 (Analog Pin): 선택적이며, 사용하지 않을 경우 pga302_init 호출 시 an_port=NULL, an_pin=GPIO_PIN_RESET으로 설정하세요 (Optional; set an_port=NULL and an_pin=GPIO_PIN_RESET in pga302_init if not used).
  • 타임아웃 (Timeout): HAL_MAX_DELAY는 단순화를 위해 사용됩니다. 실제 프로젝트에서는 적절한 타임아웃 값(예: 100ms)을 지정하는 것이 권장됩니다 (HAL_MAX_DELAY is used for simplicity. In actual projects, specify an appropriate timeout value (e.g., 100ms)).
  • 다중 장치 (Multiple Devices): 여러 PGA302 장치를 사용할 경우, 각 함수 호출 시 적절한 slave_address를 전달하세요 (For multiple PGA302 devices, pass the appropriate slave_address in each function call).
  • 에러 처리 (Error Handling): 반환 값(0 = 성공, -1 = 오류)을 확인하여 I2C 통신 오류를 처리하세요 (Check return values (0 = success, -1 = error) to handle I2C communication errors).
  • 지연 관리 (Delay Management): pga302_Config는 내부적으로 HAL_Delay(100)을 사용합니다. 추가 지연이 필요한 경우 호출자가 HAL_Delay()로 관리하세요 (pga302_Config uses HAL_Delay(100) internally. If additional delays are needed, the caller should manage them with HAL_Delay()).

디버깅 팁 (Debugging Tips)

  • I2C 통신 실패 시, STM32CubeMX에서 I2C 핀과 클럭 설정을 확인하세요 (If I2C communication fails, check I2C pin and clock settings in STM32CubeMX).
  • pga302_generic_read/write의 반환 값을 로깅하여 오류 원인을 파악하세요 (Log the return values of pga302_generic_read/write to identify error causes).
  • PGA302 데이터시트와 레지스터 맵을 참조하여 설정 값을 검증하세요 (Refer to the PGA302 datasheet and register map to verify settings).
  • 아날로그 입력(PA0) 사용 시, GPIO 상태를 모니터링하여 올바른 입력을 확인하세요 (When using the analog input (PA0), monitor the GPIO state to confirm correct input).

참고 (References)

결론 (Conclusion)

이 드라이버는 STM32 에서 PGA302를 완전히 독립적인 함수 호출로 제어하며, 상세한 주석과 함께 코드 가독성과 유지보수성을 높였습니다 (This driver controls the PGA302 on the STM32 with fully independent function calls, enhancing code readability and maintainability with detailed comments). PGA302의 사양은 데이터시트를 기반으로 정확히 반영되었으며, 추가 기능(예: 특정 센서 보정)이나 수정이 필요하면 pga302.h와 pga302.c를 확장할 수 있습니다 (The PGA302 specifications are accurately reflected based on the datasheet, and additional features (e.g., specific sensor calibration) or modifications can be extended in pga302.h and pga302.c).

 

pga302.pdf
1.65MB

반응형