본문 바로가기
카테고리 없음

[ZSSC3123] STM32L432KC로 센서 데이터 읽기 및 EEPROM 읽기 쓰기 코드 구현

by linuxgo 2025. 8. 13.
반응형

ZSSC3123 데이터시트("REN_ZSSC3123-Datasheet_DST_20211119.pdf")를 기반으로, STM32L432KC 마이크로컨트롤러의 I2C 인터페이스를 이용해 ZSSC3123의 EEPROM을 읽고 쓰는 상세한 절차입니다. 데이터시트의 관련 섹션(주로 섹션 10.6: I2C 특징 및 타이밍, 섹션 11: 명령 모드, 섹션 12: EEPROM)을 참고했습니다. ZSSC3123는 I2C 슬레이브로 작동하며, 기본 슬레이브 주소는 0x28(7비트 주소, 데이터시트 섹션 10.6.1 참조)입니다. EEPROM은 16비트 워드(총 29개 워드, 0x00 ~ 0x1F)로 구성되어 있으며, 읽기/쓰기를 위해 명령 모드(Command Mode)를 사용해야 합니다.

이 절차는 STM32CubeIDE와 HAL(Hardware Abstraction Layer) 라이브러리를 기반으로 설명합니다. 실제 구현 시 STM32CubeMX로 프로젝트를 생성하고, HAL_I2C 함수를 사용하세요. 코드 예시는 간단한 의사코드 형태로 제공하며, 실제로 컴파일/테스트하세요. 오류 처리(예: I2C 에러, 타임아웃)는 필수로 추가하세요.

1. 준비 단계: 하드웨어 연결

ZSSC3123와 STM32L432KC를 연결하세요. 데이터시트 섹션 1~2(핀 배치 및 설명), 섹션 14(애플리케이션 예시) 참조.

  • 필수 핀 연결:
    • ZSSC3123 VDD (핀 7) → STM32L432KC 3.3V 또는 5V 공급 (VSUPPLY: 2.3~5.5V, 0.1μF 커패시터로 GND 연결).
    • ZSSC3123 VSS (핀 3,5,11) → STM32L432KC GND.
    • ZSSC3123 VCORE (핀 1) → 0.1μF 커패시터로 GND 연결 (업데이트 모드: 90~330nF 추천).
    • ZSSC3123 SDA/MISO (핀 12) → STM32L432KC I2C SDA 핀 (예: PB7 또는 PA10, 풀업 저항 1~2.2kΩ 추가, 데이터시트 섹션 4 참조).
    • ZSSC3123 SCL/SCLK (핀 13) → STM32L432KC I2C SCL 핀 (예: PB6 또는 PA9, 풀업 저항 1~2.2kΩ 추가).
    • ZSSC3123 SS (핀 14) → 사용 안 함 (I2C 모드에서 플로팅).
    • 센서 입력 (C0/CC 등): 테스트 목적이라면 더미 커패시터 연결 (2~260pF 범위).
  • 기타 팁:
    • I2C 버스 속도: 최대 400kHz (데이터시트 섹션 10.6.1, 표 21 참조: tSCL 최소 2.5μs).
    • STM32L432KC I2C 핀: Nucleo 보드 사용 시 PB6(SCL)/PB7(SDA) 추천.
    • 전원: ZSSC3123 POR(Power-On-Reset) 후 4.25~173ms 대기 (섹션 10.1).
    • 테스트: Evaluation Kit(데이터시트 섹션 Description 참조)로 먼저 검증.

2. STM32L432KC 소프트웨어 설정

STM32CubeMX로 프로젝트 생성 후 HAL_I2C를 활성화하세요.

  • STM32CubeMX 설정:
    1. 새 프로젝트 생성: STM32L432KC 선택.
    2. Pinout & Configuration → Connectivity → I2C1 (또는 I2C2) 활성화.
      • Mode: I2C.
      • Parameter Settings: I2C Speed Mode = Standard Mode (100kHz) 또는 Fast Mode (400kHz).
      • GPIO Settings: SDA/SCL 핀 풀업 활성화 (External Pull-up).
    3. Clock Configuration: HCLK 최소 4MHz 이상 (I2C 클럭 소스).
    4. Project Manager: HAL 라이브러리 생성.
    5. 코드 생성 후 STM32CubeIDE 열기.

3. ZSSC3123 I2C 프로토콜 개용

ZSSC3123는 Normal Operation Mode와 Command Mode를 가집니다. EEPROM 접근은 Command Mode에서만 가능 (데이터시트 섹션 11).

  • I2C 기본:
    • 슬레이브 주소: 0x28 (쓰기: 0x50, 읽기: 0x51).
    • 응답: 명령 후 데이터 페치(DF)로 결과 읽기.
    • 타이밍: tSCLH/tSCLL 최소 1.3μs (표 21 참조).
  • Command Mode 들어가기: Normal Mode에서 Command Mode로 전환 (명령 0xA0표 25 참조).
    • EEPROM 읽기: 명령 0x00 ~ 0x1F
    • EEPROM 쓰기: 명령 0x40 ~ 0x5F
    • 쓰기 후: EEPROM 쓰기 시간(tWRI_EEP: 10ms 이상 대기, 섹션 5 참조). 쓰기 사이클 100k회 제한 (섹션 5).
  • 명령 응답 확인: 응답 비트 (표 26: Busy, Valid 등) 확인. 진단 비트 (표 27)로 오류 체크.

4. EEPROM 읽기 절차

  1. 파워온 및 초기화: ZSSC3123 전원 공급 후 200ms 대기 (POR + 스타트업 시간, 섹션 10.1).
  2. Command Mode 진입:
  3. 읽기 명령 전송:
    • I2C 시작 + 주소(0x50) + 명령 바이트(0x00 | 워드 주소) + I2C 정지.
    • 예: 워드 0x02 (ZMDI_Config) 읽기 → 명령 0x02.
  4. 데이터 페치 (DF):
    • I2C 시작 + 주소(0x51) + 2바이트 읽기 (16비트 데이터) + I2C 정지.
    • 응답: 첫 바이트(상태) + 데이터 MSB + 데이터 LSB (섹션 11.3, 그림 26 참조).
  5. 상태 확인: 응답 첫 바이트에서 Busy 비트(0이면 완료) 확인.

5. EEPROM 쓰기 절차

  1. 읽기와 유사: Command Mode 불필요.
  2. Command Mode 진입:
  3. 쓰기 명령 전송:
    • I2C 시작 + 주소(0x50) + 명령 바이트(0x40 | 워드 주소) + 데이터 MSB + 데이터 LSB + I2C 정지.
    • 예: 워드 0x02에 0xABCD 쓰기 → 명령 0x42 + 0xAB + 0xCD.
  4. 쓰기 완료 대기: 10ms 이상 (데이터시트 섹션 5: tWRI_EEP).
  5. 검증: 쓰기 후 동일 워드 읽기하여 확인.
  6. 주의: 쓰기 후 EEPROM 오류 검출 (섹션 10.4.1: ECC 사용). 고객 영역(예: Cust_Config, 워드 0x1C)만 쓰기 추천.

6. 추가 팁 및 디버깅

  • 전체 EEPROM 맵: 섹션 12, 표 28 참조 (워드 0x00~0x1F: 보정 계수 등).
  • 오류 처리: HAL_I2C_GetError() 사용. ZSSC3123 상태 비트(표 26~27) 확인 (예: Valid 비트 ==1).
  • 테스트 시퀀스: 먼저 Normal Mode에서 데이터 페치(DF 명령 0x00) 테스트 (섹션 10.6.4).
  • 저전력 고려: 쓰기 후 슬립 모드 전환 (섹션 10.3.2).
  • 문제 발생 시: 데이터시트 섹션 10.4(진단), 섹션 15(ESD) 확인. STM32 HAL 문서 참조.
  • 캘리브레이션: EEPROM 쓰기 후 센서 보정 필요 (섹션 13).
  •  

ZSSC3123 Raw Data 수집 전 설정 및 수집 절차

ZSSC3123 데이터시트(REN_ZSSC3123-Datasheet_DST_20211119.pdf)를 기반으로 분석한 결과, Raw Data(원시 데이터)는 Capacitance-to-Digital Converter (CDC)에서 생성되는 보정되지 않은 디지털 값(ZCDC, 섹션 9.2.1 참조)으로, 센서 용량(C0/C1)을 직접 변환한 결과입니다. 이는 보정 알고리즘(섹션 13) 적용 전 값으로, 캘리브레이션 테스트나 디버깅 시 유용합니다. Raw Data를 읽기 전에 반드시 초기 설정이 필요하며, 이는 EEPROM 프로그래밍과 모드 전환을 포함합니다. 설정을 하지 않으면 기본값(EEPROM 초기 상태)으로 동작하지만, 센서 범위나 해상도가 맞지 않아 유효한 데이터가 나오지 않을 수 있습니다.

아래는 Raw Data 수집 전 필수 설정 단계입니다. 이는 데이터시트 섹션 9(회로 설명), 섹션 10(Normal Operation Mode), 섹션 11(Command Mode), 섹션 12(EEPROM)를 기반으로 한 절차입니다. I2C 인터페이스를 가정하며, STM32L432KC 같은 MCU에서 구현 가능합니다. 설정 후 Normal Operation Mode에서 Raw Data를 수집합니다.

1. Power-On 및 초기화 (Power-On Sequence)

ZSSC3123는 Power-On Reset (POR, VPOR ~1.7V, 섹션 5) 후 자동으로 EEPROM을 로드하고 Normal Operation Mode로 들어갑니다. 하지만 Raw Data를 위한 맞춤 설정을 위해 Command Mode로 진입해야 합니다.

  • 설정 절차:
    • 공급 전압(VSUPPLY: 2.35.5V) 인가 후 200ms 이상 대기 (스타트업 시간 tSTA: 4.25173ms, 섹션 5 및 섹션 10.1 참조. Fast_Startup 비트가 1이면 3ms Command Window, 0이면 10ms).
    • Ready 핀(핀 10)이 High가 될 때까지 대기 (변환 완료 신호, 섹션 10.6.6).
  • 주의: 초기 EEPROM은 공장 기본값(예: Mult1, 14-bit 해상도)으로, 센서에 맞지 않을 수 있음.

2. Command Mode 진입 (Start_CM)

EEPROM 설정(센서 구성)은 Command Mode에서만 가능합니다 (섹션 11). Normal Mode에서는 측정만 가능.

  • 설정 절차:
    • Power-On 직후 Command Window 내에 I2C로 Start_CM 명령(0xA0 00 00) 전송 (Table 25, 섹션 11.2).
    • 응답 시간: 100μs (섹션 Table 25).
    • 확인: Data Fetch (DF)로 상태 바이트 읽기 (Table 26: Busy 비트 0, Valid 비트 1 확인).
  • 오류 처리: Window 초과 시 실패 (재 Power-On 필요). Fast_Startup 비트(EEPROM 워드 02H, Table 29)를 1로 설정해 Window를 3ms로 단축 가능.

3. EEPROM 설정 (필수 구성 등록 프로그래밍)

Raw Data의 범위, 해상도, 센서 타입을 정의합니다. 기본값으로 동작 가능하지만, 센서 용량(2

260pF)에 맞춰야 정확한 Raw Data 수집 가능 (섹션 9.2.1, Table 5

9).

  • 주요 설정 워드 (섹션 12, Table 28~32):
    • ZMDI_Config (워드 02H): 업데이트 모드(Continuous 또는 Sleep), Power_Down_Period (저전력 주기, Table 11), 출력 모드(I2C 선택), Fast_Startup 비트.
      • 예: Continuous Update Mode로 설정 (Power_Down_Period = 0, 비트 필드 Table 29).
    • C_Config (워드 06H): CDC 설정 - CDC_Mult (용량 범위: 1/2/4/8, Table 5), CDC_Reference/Offset (참조/오프셋 트림, Equation 1~7), 해상도(8/10/12/14-bit, Table 10), 센서 타입(싱글/디퍼런셜, 비트 Table 30).
      • 예: Mult1 (2~10pF), 14-bit 해상도, 싱글 엔디드 센서.
    • T_Config (워드 11H): 온도 측정 설정 (Raw Data에 온도 보상 필요 시, Table 31).
    • Cust_Config (워드 1CH): 고객 맞춤 (알람 등, Table 32).
  • 설정 절차:
    • I2C로 EEPROM Write 명령(0x40 | 주소 + 데이터 2바이트) 전송 (Table 25).
    • 응답 시간: 12ms per 쓰기.
    • 확인: EEPROM Read (주소 직접 명령)로 검증.
    • 주의: 쓰기 사이클 100k회 제한 (섹션 5). Reserved 워드(0x1D~0x1F) 피함.
  • 권장 초기 설정 예시 (Mult1, 14-bit, Continuous Mode):
    • ZMDI_Config: 0x0000 (기본, 업데이트 레이트 최적화).
    • C_Config: 비트 [15:14]=00 (싱글 엔디드), [13:12]=11 (14-bit), [11:10]=00 (Mult1), [9:7]=000 (오프셋 0), [6:4]=111 (참조 최대).

4. Normal Operation Mode 전환 (Start_NOM)

설정 후 Normal Mode로 전환해야 Raw Data 측정이 시작됩니다 (섹션 10).

  • 설정 절차:
    • I2C로 Start_NOM 명령(0x80 00 00) 전송 (Table 25).
    • 초기 측정 사이클 대기 (tRESP_UP: 0.7288ms, Table 1015, 해상도/Mult에 의존).
    • Ready 핀 High 확인.

5. Raw Data 수집 (Normal Operation Mode에서)

위 설정 후에야 유효한 Raw Data(ZCDC)가 생성됩니다. Raw Data는 보정 전 값으로, I2C/SPI로 페치.

  • 수집 절차 (섹션 10.6):
    • Update Mode (Continuous): 자동 측정. I2C로 Data Fetch (DF) 명령(0x00) 전송 → 상태 + Raw Capacitance (14-bit) + Raw Temperature (14-bit) 수신 (그림 19, 섹션 10.6.4).
      • 패킷: 상태 바이트 + Capacitance MSB/LSB + Temperature MSB/LSB.
    • Sleep Mode: Measurement Request (MR) 명령(0x40) 전송 → 측정 후 DF로 Raw Data 페치 (그림 21, 섹션 10.6.5).
    • 응답 시간: 해상도에 따라 0.7ms(8-bit)~18.5ms(14-bit, Table 10).
    • Raw Data 해석: ZCDC = 2^RES * ZSENSOR (Equation 2, RES=해상도). 센서 비율 ZSENSOR = (C0 - COFF)/CREF (싱글 엔디드).
  • 주의: Raw Data는 보정되지 않음 (오프셋/온도 드리프트 포함). 캘리브레이션 후 corrected 값 사용 추천 (섹션 13).
  • 오류 확인: 상태 비트(Table 16: Valid/Ready), 진단(Table 17~18: EEPROM 오류 등).

추가 팁 및 주의사항

  • 전체 흐름: Power-On → Start_CM → EEPROM 설정/쓰기 → Start_NOM → Raw Data 페치 반복.
  • 테스트: Evaluation Kit 사용 (섹션 Description). 센서 연결(C0/CC) 후 기본 Raw Data 확인.
  • 저전력 고려: Sleep Mode 선택 시 MR로만 수집 (섹션 10.3.2, 전류 1μA).
  • 문제 발생 시: 데이터시트 섹션 10.4(진단) 참조. I2C 타이밍 준수 (Table 21).
#include "stm32l4xx_hal.h"

#define ZSSC3123_I2C_ADDR       0x28  // 7-bit 슬레이브 주소
#define EEPROM_NUM_WORDS        0x20   // 0x00 ~ 0x1F (32 워드)
#define EEPROM_MAX_USER_ADDR    0x1C   // 사용자 안전 영역 최대 (Reserved 0x1D~0x1F)
#define CMD_WINDOW_DELAY_MS     1      // Command Window 대기
#define EEPROM_READ_DELAY_US    100    // 읽기 응답 시간 (typical)
#define EEPROM_WRITE_DELAY_MS   12     // 쓰기 응답 시간 (typical)
#define MODE_CHECK_TIMEOUT_MS   2      // 모드 확인 타임아웃
#define NORMAL_MODE_STARTUP_MS  200    // Normal Mode 초기화 대기 (tSTA max ~173ms + margin)
#define DF_TIMEOUT_MS           20     // Data Fetch 타임아웃
#define SLEEP_MODE_MEAS_DELAY_MS 20   // Sleep Mode 측정 대기 예시 (해상도에 따라 조정)
#define DATA_RESOLUTION_BITS    14     // 데이터 해상도 (8~14비트, 최대 14비트 가정)

extern I2C_HandleTypeDef hi2c1;  // STM32CubeMX 생성 핸들러

// 에러 코드 정의 (사용자 정의)
typedef enum {
    HAL_MODE_ERROR = HAL_ERROR + 1  // Command Mode 아님
} Custom_HAL_StatusTypeDef;

// Command Mode 확인 함수 (Get Revision 시도로 확인: Command Mode에서만 성공)
HAL_StatusTypeDef ZSSC3123_Check_Command_Mode(void) {
    uint16_t dummy_rev;
    uint8_t cmd_buf[3] = {0xB0, 0x00, 0x00};
    uint8_t rx_buf[3];

    if (HAL_I2C_Master_Transmit(&hi2c1, ZSSC3123_I2C_ADDR << 1, cmd_buf, 3, MODE_CHECK_TIMEOUT_MS) != HAL_OK) {
        return HAL_MODE_ERROR;  // 전송 실패: 모드 오류 또는 통신 문제
    }

    HAL_Delay(EEPROM_READ_DELAY_US / 1000);

    if (HAL_I2C_Master_Receive(&hi2c1, (ZSSC3123_I2C_ADDR << 1) | 0x01, rx_buf, 3, MODE_CHECK_TIMEOUT_MS) != HAL_OK) {
        return HAL_MODE_ERROR;  // DF 실패: Command Mode 아님
    }

    // 상태 확인 (성공 시 Valid 비트 1)
    if (!(rx_buf[0] & 0x40)) {
        return HAL_MODE_ERROR;  // Invalid: Command Mode 아님
    }

    return HAL_OK;
}

// Command Mode 진입 (Start_CM: A0 00 00) - Window 초과 시 실패 처리
HAL_StatusTypeDef ZSSC3123_Enter_Command_Mode(void) {
    uint8_t cmd_buf[3] = {0xA0, 0x00, 0x00};

    HAL_Delay(CMD_WINDOW_DELAY_MS);  // Power-On 후 즉시 호출 추천

    if (HAL_I2C_Master_Transmit(&hi2c1, ZSSC3123_I2C_ADDR << 1, cmd_buf, 3, HAL_MAX_DELAY) != HAL_OK) {
        return HAL_ERROR;
    }

    // 모드 확인 (Get Revision으로 검증)
    if (ZSSC3123_Check_Command_Mode() != HAL_OK) {
        return HAL_MODE_ERROR;  // 진입 실패 (Window 초과 등)
    }

    return HAL_OK;
}

// Normal Operation Mode 전환 (Start_NOM: 80 00 00)
HAL_StatusTypeDef ZSSC3123_Enter_Normal_Mode(void) {
    uint8_t cmd_buf[3] = {0x80, 0x00, 0x00};

    if (HAL_I2C_Master_Transmit(&hi2c1, ZSSC3123_I2C_ADDR << 1, cmd_buf, 3, HAL_MAX_DELAY) != HAL_OK) {
        return HAL_ERROR;
    }

    HAL_Delay(NORMAL_MODE_STARTUP_MS);  // 초기 측정 사이클 대기 (tSTA + margin)

    return HAL_OK;  // 초기 측정 시간 별도 대기 (섹션 10.1)
}

// Get Revision (B0 00 00)
HAL_StatusTypeDef ZSSC3123_Get_Revision(uint16_t *revision) {
    // 모드 확인
    if (ZSSC3123_Check_Command_Mode() != HAL_OK) {
        return HAL_MODE_ERROR;
    }

    uint8_t cmd_buf[3] = {0xB0, 0x00, 0x00};
    uint8_t rx_buf[3];  // 상태 + 데이터 2바이트

    if (HAL_I2C_Master_Transmit(&hi2c1, ZSSC3123_I2C_ADDR << 1, cmd_buf, 3, HAL_MAX_DELAY) != HAL_OK) {
        return HAL_ERROR;
    }

    HAL_Delay(EEPROM_READ_DELAY_US / 1000);  // 100μs 대기

    if (HAL_I2C_Master_Receive(&hi2c1, (ZSSC3123_I2C_ADDR << 1) | 0x01, rx_buf, 3, HAL_MAX_DELAY) != HAL_OK) {
        return HAL_ERROR;
    }

    // 상태 확인 (Table 26: Busy 0, Valid 1; Table 27: Diagnostic)
    if ((rx_buf[0] & 0x80) || !(rx_buf[0] & 0x40) || (rx_buf[0] & 0x0F)) {
        return HAL_ERROR;  // 오류 (Diagnostic 비트 확인)
    }

    *revision = (rx_buf[1] << 8) | rx_buf[2];
    return HAL_OK;
}

// 특정 주소 EEPROM 읽기 (Command Byte: addr 직접, 00~1F)
HAL_StatusTypeDef ZSSC3123_EEPROM_Read(uint8_t addr, uint16_t *data) {
    if (addr > 0x1F) return HAL_ERROR;

    // 모드 확인 (Command Mode 아니면 에러)
    if (ZSSC3123_Check_Command_Mode() != HAL_OK) {
        // 자동 진입 시도 (Power-On 상태 가정)
        if (ZSSC3123_Enter_Command_Mode() != HAL_OK) {
            return HAL_MODE_ERROR;
        }
    }

    uint8_t cmd = addr;  // 직접 주소 (00~1F)
    uint8_t rx_buf[3];

    if (HAL_I2C_Master_Transmit(&hi2c1, ZSSC3123_I2C_ADDR << 1, &cmd, 1, HAL_MAX_DELAY) != HAL_OK) {
        return HAL_ERROR;
    }

    HAL_Delay(EEPROM_READ_DELAY_US / 1000);  // 100μs 대기

    if (HAL_I2C_Master_Receive(&hi2c1, (ZSSC3123_I2C_ADDR << 1) | 0x01, rx_buf, 3, HAL_MAX_DELAY) != HAL_OK) {
        return HAL_ERROR;
    }

    // 상태 확인
    if ((rx_buf[0] & 0x80) || !(rx_buf[0] & 0x40) || (rx_buf[0] & 0x0F)) {
        return HAL_ERROR;
    }

    *data = (rx_buf[1] << 8) | rx_buf[2];
    return HAL_OK;
}

// 특정 주소 EEPROM 쓰기 (Command Byte: 40~5F)
HAL_StatusTypeDef ZSSC3123_EEPROM_Write(uint8_t addr, uint16_t data) {
    if (addr > 0x1F || addr > EEPROM_MAX_USER_ADDR) {
        return HAL_ERROR;  // Reserved 에러
    }

    // 모드 확인 (Command Mode 아니면 에러)
    if (ZSSC3123_Check_Command_Mode() != HAL_OK) {
        // 자동 진입 시도
        if (ZSSC3123_Enter_Command_Mode() != HAL_OK) {
            return HAL_MODE_ERROR;
        }
    }

    uint8_t tx_buf[3] = {0x40 | addr, (data >> 8) & 0xFF, data & 0xFF};

    if (HAL_I2C_Master_Transmit(&hi2c1, ZSSC3123_I2C_ADDR << 1, tx_buf, 3, HAL_MAX_DELAY) != HAL_OK) {
        return HAL_ERROR;
    }

    HAL_Delay(EEPROM_WRITE_DELAY_MS);  // 12ms 대기

    // 검증 (읽기 호출)
    uint16_t read_data;
    if (ZSSC3123_EEPROM_Read(addr, &read_data) != HAL_OK || read_data != data) {
        return HAL_ERROR;
    }

    return HAL_OK;
}

// 전체 EEPROM 읽기
HAL_StatusTypeDef ZSSC3123_EEPROM_Read_All(uint16_t *buffer) {
    for (uint8_t addr = 0x00; addr < EEPROM_NUM_WORDS; addr++) {
        if (ZSSC3123_EEPROM_Read(addr, &buffer[addr]) != HAL_OK) {
            return HAL_ERROR;
        }
    }
    return HAL_OK;
}

// 전체 EEPROM 쓰기 (Reserved 스킵)
HAL_StatusTypeDef ZSSC3123_EEPROM_Write_All(const uint16_t *buffer) {
    for (uint8_t addr = 0x00; addr < EEPROM_NUM_WORDS; addr++) {
        if (addr > EEPROM_MAX_USER_ADDR) continue;  // Reserved 스킵
        if (ZSSC3123_EEPROM_Write(addr, buffer[addr]) != HAL_OK) {
            return HAL_ERROR;
        }
    }
    return HAL_OK;
}

// Raw Data 읽기 전 초기 설정 함수 (Command Mode 진입 + EEPROM 예시 설정 + Normal Mode 전환)
HAL_StatusTypeDef ZSSC3123_Initialize_Settings(void) {
    // 1. Command Mode 진입 (Power-On 후 호출 가정)
    if (ZSSC3123_Enter_Command_Mode() != HAL_OK) {
        return HAL_ERROR;
    }

    // 2. EEPROM 설정 (예시: Mult1, 14-bit 해상도, Continuous Update Mode)
    // ZMDI_Config (워드 02H): Continuous Mode, Power_Down_Period=0
    if (ZSSC3123_EEPROM_Write(0x02, 0x0000) != HAL_OK) {  // 기본 예시 값 (Table 29 조정)
        return HAL_ERROR;
    }

    // C_Config (워드 06H): 싱글 엔디드, 14-bit, Mult1, 오프셋/참조 기본
    if (ZSSC3123_EEPROM_Write(0x06, 0xF000) != HAL_OK) {  // 예시: 비트 [15:0] = 1111 0000 0000 0000 (Table 30 조정)
        return HAL_ERROR;
    }

    // T_Config (워드 11H): 온도 설정 기본
    if (ZSSC3123_EEPROM_Write(0x11, 0x0000) != HAL_OK) {  // 예시 값 (Table 31)
        return HAL_ERROR;
    }

    // Cust_Config (워드 1CH): 기본
    if (ZSSC3123_EEPROM_Write(0x1C, 0x0000) != HAL_OK) {
        return HAL_ERROR;
    }

    // 3. Normal Mode 전환
    if (ZSSC3123_Enter_Normal_Mode() != HAL_OK) {
        return HAL_ERROR;
    }

    return HAL_OK;
}

// Raw Data 수집 함수 (Normal Mode에서 DF 명령으로 Capacitance/Temperature Raw 값 페치)
HAL_StatusTypeDef ZSSC3123_Read_Raw_Data(uint16_t *raw_capacitance, uint16_t *raw_temperature) {
    uint8_t df_cmd = 0x00;  // Data Fetch 명령 (섹션 10.6.4)
    uint8_t rx_buf[5];  // 상태(1) + Capacitance(2) + Temperature(2) (그림 19 참조)

    // 초기 설정 확인 및 수행 (Raw Data 읽기 전 설정 자동 호출)
    if (ZSSC3123_Initialize_Settings() != HAL_OK) {
        return HAL_ERROR;
    }

    // Normal Mode 확인 (Command Mode이면 전환)
    if (ZSSC3123_Check_Command_Mode() == HAL_OK) {
        // Command Mode이면 Normal Mode로 전환
        if (ZSSC3123_Enter_Normal_Mode() != HAL_OK) {
            return HAL_ERROR;
        }
    }

    // DF 명령 전송 (Update Mode 가정: Continuous 측정)
    if (HAL_I2C_Master_Transmit(&hi2c1, ZSSC3123_I2C_ADDR << 1, &df_cmd, 1, DF_TIMEOUT_MS) != HAL_OK) {
        return HAL_ERROR;
    }

    // 데이터 페치
    if (HAL_I2C_Master_Receive(&hi2c1, (ZSSC3123_I2C_ADDR << 1) | 0x01, rx_buf, 5, DF_TIMEOUT_MS) != HAL_OK) {
        return HAL_ERROR;
    }

    // 상태 확인 (Table 16: Valid 비트 등)
    if ((rx_buf[0] & 0xC0) != 0x40) {  // 예시: Valid 1, Busy 0
        return HAL_ERROR;
    }

    uint16_t temp_cap = (rx_buf[1] << 8) | rx_buf[2];  // 16비트 임시 값
    uint16_t temp_temp = (rx_buf[3] << 8) | rx_buf[4];

    // 14비트 정렬 (상위 14비트 추출, 하위 2비트 0 패딩 가정으로 오른쪽 shift)
    *raw_capacitance = temp_cap >> (16 - DATA_RESOLUTION_BITS);  // 14비트로 shift 정렬
    *raw_temperature = temp_temp >> (16 - DATA_RESOLUTION_BITS);  // 14비트로 shift 정렬

    return HAL_OK;
}

// Update Mode에서 센서 데이터 읽기 (연속 모드)
HAL_StatusTypeDef ZSSC3123_Read_Sensor_Data_Update_Mode(uint16_t *capacitance, uint16_t *temperature) {
    uint8_t df_cmd = 0x00;  // DF 명령
    uint8_t rx_buf[5];      // 상태 + 데이터

    // Normal Mode 확인 및 진입 (Update Mode 가정)
    if (ZSSC3123_Check_Command_Mode() == HAL_OK) {
        ZSSC3123_Enter_Normal_Mode();  // Command Mode이면 전환
    }

    // DF 전송
    if (HAL_I2C_Master_Transmit(&hi2c1, ZSSC3123_I2C_ADDR << 1, &df_cmd, 1, HAL_MAX_DELAY) != HAL_OK) {
        return HAL_ERROR;
    }

    // 데이터 페치
    if (HAL_I2C_Master_Receive(&hi2c1, (ZSSC3123_I2C_ADDR << 1) | 0x01, rx_buf, 5, HAL_MAX_DELAY) != HAL_OK) {
        return HAL_ERROR;
    }

    // 상태 확인
    if ((rx_buf[0] & 0xC0) != 0x40) {  // Valid 1, Busy 0 예시
        return HAL_ERROR;
    }

    uint16_t temp_cap = (rx_buf[1] << 8) | rx_buf[2];
    uint16_t temp_temp = (rx_buf[3] << 8) | rx_buf[4];

    // 14비트 정렬 (상위 14비트 추출)
    *capacitance = temp_cap >> (16 - DATA_RESOLUTION_BITS);
    *temperature = temp_temp >> (16 - DATA_RESOLUTION_BITS);

    return HAL_OK;
}

// Sleep Mode에서 센서 데이터 읽기 (요청 기반)
HAL_StatusTypeDef ZSSC3123_Read_Sensor_Data_Sleep_Mode(uint16_t *capacitance, uint16_t *temperature) {
    uint8_t df_cmd = 0x00;  // DF 명령
    uint8_t rx_buf[5];

    // Normal Mode 확인 및 진입 (Sleep Mode 가정)
    if (ZSSC3123_Check_Command_Mode() == HAL_OK) {
        ZSSC3123_Enter_Normal_Mode();
    }

    // MR 전송 (빈 쓰기: 데이터 없이 주소만)
    if (HAL_I2C_Master_Transmit(&hi2c1, ZSSC3123_I2C_ADDR << 1, NULL, 0, HAL_MAX_DELAY) != HAL_OK) {
        return HAL_ERROR;
    }

    // 측정 대기 (예: 20ms, 실제는 해상도에 따라 조정 또는 Ready 핀 폴링)
    HAL_Delay(SLEEP_MODE_MEAS_DELAY_MS);

    // DF 전송
    if (HAL_I2C_Master_Transmit(&hi2c1, ZSSC3123_I2C_ADDR << 1, &df_cmd, 1, HAL_MAX_DELAY) != HAL_OK) {
        return HAL_ERROR;
    }

    // 데이터 페치
    if (HAL_I2C_Master_Receive(&hi2c1, (ZSSC3123_I2C_ADDR << 1) | 0x01, rx_buf, 5, HAL_MAX_DELAY) != HAL_OK) {
        return HAL_ERROR;
    }

    // 상태 확인
    if ((rx_buf[0] & 0xC0) != 0x40) {
        return HAL_ERROR;
    }

    uint16_t temp_cap = (rx_buf[1] << 8) | rx_buf[2];
    uint16_t temp_temp = (rx_buf[3] << 8) | rx_buf[4];

    // 14비트 정렬 (상위 14비트 추출)
    *capacitance = temp_cap >> (16 - DATA_RESOLUTION_BITS);
    *temperature = temp_temp >> (16 - DATA_RESOLUTION_BITS);

    return HAL_OK;
}
반응형