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)를 사용해야 합니다.
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 설정:
- 새 프로젝트 생성: STM32L432KC 선택.
- 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).
- Clock Configuration: HCLK 최소 4MHz 이상 (I2C 클럭 소스).
- Project Manager: HAL 라이브러리 생성.
- 코드 생성 후 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 읽기 절차
- 파워온 및 초기화: ZSSC3123 전원 공급 후 200ms 대기 (POR + 스타트업 시간, 섹션 10.1).
- Command Mode 진입:
- 읽기 명령 전송:
- I2C 시작 + 주소(0x50) + 명령 바이트(0x00 | 워드 주소) + I2C 정지.
- 예: 워드 0x02 (ZMDI_Config) 읽기 → 명령 0x02.
- 데이터 페치 (DF):
- I2C 시작 + 주소(0x51) + 2바이트 읽기 (16비트 데이터) + I2C 정지.
- 응답: 첫 바이트(상태) + 데이터 MSB + 데이터 LSB (섹션 11.3, 그림 26 참조).
- 상태 확인: 응답 첫 바이트에서 Busy 비트(0이면 완료) 확인.
5. EEPROM 쓰기 절차
- 읽기와 유사: Command Mode 불필요.
- Command Mode 진입:
- 쓰기 명령 전송:
- I2C 시작 + 주소(0x50) + 명령 바이트(0x40 | 워드 주소) + 데이터 MSB + 데이터 LSB + I2C 정지.
- 예: 워드 0x02에 0xABCD 쓰기 → 명령 0x42 + 0xAB + 0xCD.
- 쓰기 완료 대기: 10ms 이상 (데이터시트 섹션 5: tWRI_EEP).
- 검증: 쓰기 후 동일 워드 읽기하여 확인.
- 주의: 쓰기 후 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.3~5.5V) 인가 후 200ms 이상 대기(Startup 시간 tSTAR:4.25~173ms, 섹션 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의 범위, 해상도, 센서 타입을 정의합니다. 기본값으로 동작 가능하지만, 센서 용량(22~60pF)에 맞춰야 정확한 Raw Data 수집 가능(섹션9.2.1, Table 59).
- 주요 설정 워드 (섹션 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).
- ZMDI_Config (워드 02H): 업데이트 모드(Continuous 또는 Sleep), Power_Down_Period (저전력 주기, Table 11), 출력 모드(I2C 선택), Fast_Startup 비트.
- 설정 절차:
- 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.72~88ms, Table 10-15,해상도/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 (싱글 엔디드).
- Update Mode (Continuous): 자동 측정. I2C로 Data Fetch (DF) 명령(0x00) 전송 → 상태 + Raw Capacitance (14-bit) + Raw Temperature (14-bit) 수신 (그림 19, 섹션 10.6.4).
- 주의: 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"
// ZSSC3123 I2C 기본 설정 (데이터시트 섹션 10.6.1)
#define ZSSC3123_I2C_ADDR 0x28 // 7-bit 슬레이브 주소 (기본값, 설정에 따라 변경 가능)
#define EEPROM_NUM_WORDS 0x20 // EEPROM 워드 수: 0x00 ~ 0x1F (32 워드, 섹션 12)
#define EEPROM_MAX_USER_ADDR 0x1C // 사용자 접근 가능 최대 주소 (0x1D~0x1F는 Reserved, 섹션 12)
#define EEPROM_READ_DELAY_US 100 // EEPROM 읽기 응답 시간 (typical, 100μs, 섹션 12)
#define EEPROM_WRITE_DELAY_MS 12 // EEPROM 쓰기 응답 시간 (typical, 12ms, 섹션 12)
#define MODE_CHECK_TIMEOUT_MS 2 // Command Mode 확인 타임아웃 (사용자 정의)
#define NORMAL_MODE_STARTUP_MS 173 // Normal Mode 초기화 대기 시간 (tSTA 최대 173ms, 섹션 10.1)
#define DF_TIMEOUT_MS 20 // Data Fetch 타임아웃 (섹션 10.6.4)
#define SLEEP_MODE_MEAS_DELAY_MS 19 // Sleep Mode 측정 대기 시간 (14비트 기준 18.5ms + 여유, 섹션 10.3.2)
#define DATA_RESOLUTION_BITS 14 // 데이터 해상도 (8~14비트, 기본 14비트, 섹션 9.2.1)
// VDD 제어 GPIO 설정 (사용자 하드웨어에 맞게 수정 필요)
#define VDD_CONTROL_GPIO_PORT GPIOA // VDD 제어 GPIO 포트 (예: GPIOA)
#define VDD_CONTROL_GPIO_PIN GPIO_PIN_0 // VDD 제어 GPIO 핀 (예: PA0)
extern I2C_HandleTypeDef hi2c1; // STM32CubeMX에서 생성한 I2C 핸들러
// 사용자 정의 에러 코드 (데이터시트 표 26, 27 참조)
typedef enum {
HAL_MODE_ERROR = HAL_ERROR + 1, // Command Mode 진입 실패
HAL_DIAG_ERROR // Diagnostic 오류 (EEPROM ECC, 센서 오류 등)
} Custom_HAL_StatusTypeDef;
// VDD 전원 OFF/ON 함수
// 데이터시트 섹션 10.1, 11: Command Mode 진입을 위해 Power-On Reset(POR) 필요
HAL_StatusTypeDef ZSSC3123_Power_Cycle(void) {
// VDD를 OFF로 설정 (로드 스위치 OFF)
HAL_GPIO_WritePin(VDD_CONTROL_GPIO_PORT, VDD_CONTROL_GPIO_PIN, GPIO_PIN_RESET);
HAL_Delay(10); // 안정화 대기 (10ms, 사용자 정의, 데이터시트 그림 11 참조)
// VDD를 ON으로 설정 (POR 트리거)
HAL_GPIO_WritePin(VDD_CONTROL_GPIO_PORT, VDD_CONTROL_GPIO_PIN, GPIO_PIN_SET);
HAL_Delay(1); // POR 안정화 대기 (짧은 시간, 섹션 10.1)
return HAL_OK;
}
// Command Mode 확인 함수
// 데이터시트 섹션 11: Get Revision 명령(0xB0 00 00)은 Command Mode에서만 응답
HAL_StatusTypeDef ZSSC3123_Check_Command_Mode(void) {
uint8_t cmd_buf[3] = {0xB0, 0x00, 0x00}; // Get Revision 명령 (섹션 11.2, 표 28)
uint8_t rx_buf[3]; // 상태(1) + 데이터(2)
// I2C 명령 전송
if (HAL_I2C_Master_Transmit(&hi2c1, ZSSC3123_I2C_ADDR << 1, cmd_buf, 3, MODE_CHECK_TIMEOUT_MS) != HAL_OK) {
return HAL_MODE_ERROR; // I2C 전송 실패
}
HAL_Delay(EEPROM_READ_DELAY_US / 1000); // 100μs 대기 (섹션 12)
// 응답 수신
if (HAL_I2C_Master_Receive(&hi2c1, (ZSSC3123_I2C_ADDR << 1) | 0x01, rx_buf, 3, MODE_CHECK_TIMEOUT_MS) != HAL_OK) {
return HAL_MODE_ERROR; // I2C 수신 실패
}
// 상태 비트 확인 (표 26: Valid=1, Busy=0; 표 27: Diagnostic=0)
if (!(rx_buf[0] & 0x40) || (rx_buf[0] & 0x80) || (rx_buf[0] & 0x0F)) {
return HAL_MODE_ERROR; // Command Mode 아님 또는 오류
}
return HAL_OK;
}
// Command Mode 진입 함수
// 데이터시트 섹션 11: Start_CM(0xA0 00 00)은 POR 직후 Command Window에서 전송
HAL_StatusTypeDef ZSSC3123_Enter_Command_Mode(void) {
uint8_t cmd_buf[3] = {0xA0, 0x00, 0x00}; // Start_CM 명령 (섹션 11.2, 표 28)
// VDD 전원 사이클 실행 (POR 트리거)
if (ZSSC3123_Power_Cycle() != HAL_OK) {
return HAL_ERROR; // 전원 제어 실패
}
// Start_CM 명령 즉시 전송 (Command Window 내)
if (HAL_I2C_Master_Transmit(&hi2c1, ZSSC3123_I2C_ADDR << 1, cmd_buf, 3, MODE_CHECK_TIMEOUT_MS) != HAL_OK) {
return HAL_ERROR; // I2C 전송 실패
}
// Command Mode 진입 확인
if (ZSSC3123_Check_Command_Mode() != HAL_OK) {
return HAL_MODE_ERROR; // Command Mode 진입 실패
}
return HAL_OK;
}
// Normal Operation Mode 전환 함수
// 데이터시트 섹션 10.1: Start_NOM(0x80 00 00)으로 Normal Mode 진입, tSTA 대기
HAL_StatusTypeDef ZSSC3123_Enter_Normal_Mode(void) {
uint8_t cmd_buf[3] = {0x80, 0x00, 0x00}; // Start_NOM 명령 (섹션 11.2, 표 28)
// Start_NOM 명령 전송
if (HAL_I2C_Master_Transmit(&hi2c1, ZSSC3123_I2C_ADDR << 1, cmd_buf, 3, HAL_MAX_DELAY) != HAL_OK) {
return HAL_ERROR; // I2C 전송 실패
}
// 초기화 완료 대기 (tSTA 최대 173ms, 섹션 10.1)
HAL_Delay(NORMAL_MODE_STARTUP_MS);
return HAL_OK;
}
// Revision 읽기 함수
// 데이터시트 섹션 11.2: Get Revision(0xB0 00 00)은 Command Mode에서만 동작
HAL_StatusTypeDef ZSSC3123_Get_Revision(uint16_t *revision) {
// Command Mode 확인
if (ZSSC3123_Check_Command_Mode() != HAL_OK) {
return HAL_MODE_ERROR; // Command Mode 아님
}
uint8_t cmd_buf[3] = {0xB0, 0x00, 0x00}; // Get Revision 명령
uint8_t rx_buf[3]; // 상태(1) + Revision(2)
// 명령 전송
if (HAL_I2C_Master_Transmit(&hi2c1, ZSSC3123_I2C_ADDR << 1, cmd_buf, 3, HAL_MAX_DELAY) != HAL_OK) {
return HAL_ERROR; // I2C 전송 실패
}
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; // I2C 수신 실패
}
// 상태 비트 확인 (표 26: Valid=1, Busy=0; 표 27: Diagnostic=0)
if ((rx_buf[0] & 0x80) || !(rx_buf[0] & 0x40) || (rx_buf[0] & 0x0F)) {
return HAL_DIAG_ERROR; // Diagnostic 오류
}
*revision = (rx_buf[1] << 8) | rx_buf[2]; // 16비트 Revision 값
return HAL_OK;
}
// EEPROM 특정 주소 읽기 함수
// 데이터시트 섹션 12: 주소 0x00~0x1F 직접 지정
HAL_StatusTypeDef ZSSC3123_EEPROM_Read(uint8_t addr, uint16_t *data) {
if (addr > 0x1F) return HAL_ERROR; // 주소 범위 초과 (섹션 12)
// Command Mode 확인 및 진입
if (ZSSC3123_Check_Command_Mode() != HAL_OK) {
if (ZSSC3123_Enter_Command_Mode() != HAL_OK) {
return HAL_MODE_ERROR; // Command Mode 진입 실패
}
}
uint8_t cmd = addr; // 직접 주소 지정 (0x00~0x1F, 표 28)
uint8_t rx_buf[3]; // 상태(1) + 데이터(2)
// 명령 전송
if (HAL_I2C_Master_Transmit(&hi2c1, ZSSC3123_I2C_ADDR << 1, &cmd, 1, HAL_MAX_DELAY) != HAL_OK) {
return HAL_ERROR; // I2C 전송 실패
}
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; // I2C 수신 실패
}
// 상태 비트 확인 (표 26, 27)
if ((rx_buf[0] & 0x80) || !(rx_buf[0] & 0x40) || (rx_buf[0] & 0x0F)) {
return HAL_DIAG_ERROR; // Diagnostic 오류
}
*data = (rx_buf[1] << 8) | rx_buf[2]; // 16비트 데이터
return HAL_OK;
}
// EEPROM 특정 주소 쓰기 함수
// 데이터시트 섹션 12: 주소 0x40~0x5F(주소+0x40)로 쓰기
HAL_StatusTypeDef ZSSC3123_EEPROM_Write(uint8_t addr, uint16_t data) {
if (addr > 0x1F || addr > EEPROM_MAX_USER_ADDR) {
return HAL_ERROR; // 주소 범위 초과 또는 Reserved 영역 (섹션 12)
}
// Command Mode 확인 및 진입
if (ZSSC3123_Check_Command_Mode() != HAL_OK) {
if (ZSSC3123_Enter_Command_Mode() != HAL_OK) {
return HAL_MODE_ERROR; // Command Mode 진입 실패
}
}
uint8_t tx_buf[3] = {0x40 | addr, (data >> 8) & 0xFF, data & 0xFF}; // 쓰기 명령 (표 28)
// 데이터 전송
if (HAL_I2C_Master_Transmit(&hi2c1, ZSSC3123_I2C_ADDR << 1, tx_buf, 3, HAL_MAX_DELAY) != HAL_OK) {
return HAL_ERROR; // I2C 전송 실패
}
HAL_Delay(EEPROM_WRITE_DELAY_MS); // 쓰기 완료 대기 (12ms, 섹션 12)
// 쓰기 검증
uint16_t read_data;
if (ZSSC3123_EEPROM_Read(addr, &read_data) != HAL_OK || read_data != data) {
return HAL_ERROR; // 검증 실패
}
return HAL_OK;
}
// 전체 EEPROM 읽기 함수
// 데이터시트 섹션 12: 모든 워드(0x00~0x1F) 순차 읽기
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 쓰기 함수
// 데이터시트 섹션 12: Reserved 영역(0x1D~0x1F) 제외하고 쓰기
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;
}
// 초기 설정 함수
// 데이터시트 섹션 12: EEPROM 설정 후 Normal Mode로 전환 (예시 설정: Continuous Mode, 14비트)
HAL_StatusTypeDef ZSSC3123_Initialize_Settings(void) {
// Command Mode 진입
if (ZSSC3123_Enter_Command_Mode() != HAL_OK) {
return HAL_ERROR; // Command Mode 진입 실패
}
// ZMDI_Config (워드 0x02): Continuous Mode, Power_Down_Period=0 (표 29)
if (ZSSC3123_EEPROM_Write(0x02, 0x0000) != HAL_OK) {
return HAL_ERROR; // EEPROM 쓰기 실패
}
// C_Config (워드 0x06): 싱글 엔디드, 14비트, Mult1, 기본 오프셋/참조 (표 30)
if (ZSSC3123_EEPROM_Write(0x06, 0xF000) != HAL_OK) {
return HAL_ERROR; // EEPROM 쓰기 실패
}
// T_Config (워드 0x11): 온도 설정 기본 (표 31)
if (ZSSC3123_EEPROM_Write(0x11, 0x0000) != HAL_OK) {
return HAL_ERROR; // EEPROM 쓰기 실패
}
// Cust_Config (워드 0x1C): 기본 설정 (표 32)
if (ZSSC3123_EEPROM_Write(0x1C, 0x0000) != HAL_OK) {
return HAL_ERROR; // EEPROM 쓰기 실패
}
// Normal Mode 전환
if (ZSSC3123_Enter_Normal_Mode() != HAL_OK) {
return HAL_ERROR; // Normal Mode 전환 실패
}
return HAL_OK;
}
// Raw Data 수집 함수
// 데이터시트 섹션 10.6.4: Normal Mode에서 Data Fetch(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, 그림 19)
uint8_t rx_buf[5]; // 상태(1) + Capacitance(2) + Temperature(2)
// 초기 설정 수행
if (ZSSC3123_Initialize_Settings() != HAL_OK) {
return HAL_ERROR; // 초기화 실패
}
// Normal Mode 확인 (Command Mode이면 전환)
if (ZSSC3123_Check_Command_Mode() == HAL_OK) {
if (ZSSC3123_Enter_Normal_Mode() != HAL_OK) {
return HAL_ERROR; // Normal Mode 전환 실패
}
}
// DF 명령 전송 (Update Mode 가정: 연속 측정)
if (HAL_I2C_Master_Transmit(&hi2c1, ZSSC3123_I2C_ADDR << 1, &df_cmd, 1, DF_TIMEOUT_MS) != HAL_OK) {
return HAL_ERROR; // I2C 전송 실패
}
// 데이터 수신
if (HAL_I2C_Master_Receive(&hi2c1, (ZSSC3123_I2C_ADDR << 1) | 0x01, rx_buf, 5, DF_TIMEOUT_MS) != HAL_OK) {
return HAL_ERROR; // I2C 수신 실패
}
// 상태 비트 확인 (표 16: Valid=1, Busy=0, Diagnostic=0)
if ((rx_buf[0] & 0xC0) != 0x40 || (rx_buf[0] & 0x0F)) {
return HAL_DIAG_ERROR; // Diagnostic 오류
}
// 16비트 데이터 추출 및 해상도 정렬 (14비트 기준, 섹션 9.2.1)
uint16_t temp_cap = (rx_buf[1] << 8) | rx_buf[2];
uint16_t temp_temp = (rx_buf[3] << 8) | rx_buf[4];
*raw_capacitance = temp_cap >> (16 - DATA_RESOLUTION_BITS); // 상위 14비트 추출
*raw_temperature = temp_temp >> (16 - DATA_RESOLUTION_BITS); // 상위 14비트 추출
return HAL_OK;
}
// Update Mode에서 센서 데이터 읽기 함수
// 데이터시트 섹션 10.3.1: Continuous Update Mode에서 DF로 데이터 읽기
HAL_StatusTypeDef ZSSC3123_Read_Sensor_Data_Update_Mode(uint16_t *capacitance, uint16_t *temperature) {
uint8_t df_cmd = 0x00; // Data Fetch 명령 (섹션 10.6.4, 그림 19)
uint8_t rx_buf[5]; // 상태(1) + Capacitance(2) + Temperature(2)
// Normal Mode 확인 및 진입
if (ZSSC3123_Check_Command_Mode() == HAL_OK) {
if (ZSSC3123_Enter_Normal_Mode() != HAL_OK) {
return HAL_ERROR; // Normal Mode 전환 실패
}
}
// DF 명령 전송
if (HAL_I2C_Master_Transmit(&hi2c1, ZSSC3123_I2C_ADDR << 1, &df_cmd, 1, HAL_MAX_DELAY) != HAL_OK) {
return HAL_ERROR; // I2C 전송 실패
}
// 데이터 수신
if (HAL_I2C_Master_Receive(&hi2c1, (ZSSC3123_I2C_ADDR << 1) | 0x01, rx_buf, 5, HAL_MAX_DELAY) != HAL_OK) {
return HAL_ERROR; // I2C 수신 실패
}
// 상태 비트 확인 (표 16: Valid=1, Busy=0, Diagnostic=0)
if ((rx_buf[0] & 0xC0) != 0x40 || (rx_buf[0] & 0x0F)) {
return HAL_DIAG_ERROR; // Diagnostic 오류
}
// 16비트 데이터 추출 및 해상도 정렬 (14비트 기준, 섹션 9.2.1)
uint16_t temp_cap = (rx_buf[1] << 8) | rx_buf[2];
uint16_t temp_temp = (rx_buf[3] << 8) | rx_buf[4];
*capacitance = temp_cap >> (16 - DATA_RESOLUTION_BITS); // 상위 14비트 추출
*temperature = temp_temp >> (16 - DATA_RESOLUTION_BITS); // 상위 14비트 추출
return HAL_OK;
}
// Sleep Mode에서 센서 데이터 읽기 함수
// 데이터시트 섹션 10.3.2: Measurement Request(MR)로 측정 후 DF로 데이터 읽기
HAL_StatusTypeDef ZSSC3123_Read_Sensor_Data_Sleep_Mode(uint16_t *capacitance, uint16_t *temperature) {
uint8_t df_cmd = 0x00; // Data Fetch 명령 (섹션 10.6.4, 그림 19)
uint8_t rx_buf[5]; // 상태(1) + Capacitance(2) + Temperature(2)
// Normal Mode 확인 및 진입
if (ZSSC3123_Check_Command_Mode() == HAL_OK) {
if (ZSSC3123_Enter_Normal_Mode() != HAL_OK) {
return HAL_ERROR; // Normal Mode 전환 실패
}
}
// Measurement Request(MR) 전송 (빈 쓰기, 섹션 10.6.5, 그림 21)
if (HAL_I2C_Master_Transmit(&hi2c1, ZSSC3123_I2C_ADDR << 1, NULL, 0, HAL_MAX_DELAY) != HAL_OK) {
return HAL_ERROR; // I2C 전송 실패
}
// 측정 완료 대기 (14비트 기준 18.5ms + 여유, 섹션 10.3.2)
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; // I2C 전송 실패
}
// 데이터 수신
if (HAL_I2C_Master_Receive(&hi2c1, (ZSSC3123_I2C_ADDR << 1) | 0x01, rx_buf, 5, HAL_MAX_DELAY) != HAL_OK) {
return HAL_ERROR; // I2C 수신 실패
}
// 상태 비트 확인 (표 16: Valid=1, Busy=0, Diagnostic=0)
if ((rx_buf[0] & 0xC0) != 0x40 || (rx_buf[0] & 0x0F)) {
return HAL_DIAG_ERROR; // Diagnostic 오류
}
// 16비트 데이터 추출 및 해상도 정렬 (14비트 기준, 섹션 9.2.1)
uint16_t temp_cap = (rx_buf[1] << 8) | rx_buf[2];
uint16_t temp_temp = (rx_buf[3] << 8) | rx_buf[4];
*capacitance = temp_cap >> (16 - DATA_RESOLUTION_BITS); // 상위 14비트 추출
*temperature = temp_temp >> (16 - DATA_RESOLUTION_BITS); // 상위 14비트 추출
return HAL_OK;
}