본 문서는 ZSC31050 센서의 I²C 인터페이스를 활용한 설정 및 작동 절차를 상세히 설명합니다. ZSC31050은 고정밀 압력 및 온도 측정을 위한 아날로그-디지털 혼합 신호 컨디셔닝 IC로, EEPROM과 RAM을 통해 유연한 설정이 가능합니다. 아래 절차는 센서의 초기화, 데이터 수집, 보정, 주기적 측정을 체계적으로 수행하며, 데이터 시트에 기반한 정확한 설정을 반영합니다. 명령 리스트와 주요 구성은 테이블로 상세하게 정리하였습니다. 본 문서 마지막에는 구현된 코드와 그 내용을 포함합니다.
1. 장치 초기화 및 I²C 인터페이스 설정
ZSC31050의 작동을 위해 마이크로컨트롤러(예: STM32L4 시리즈)와 센서 간의 I²C 인터페이스를 초기화합니다. 이 과정은 안정적인 통신을 보장하며, 하드웨어 및 소프트웨어 설정을 최적화합니다.
- 시스템 클럭 설정: 마이크로컨트롤러의 시스템 클럭을 80MHz로 설정하여 I²C 통신 속도(400kHz)와 동기화합니다. 이는 ZSC31050의 내부 오실레이터 주파수(fCLK)와 조화를 이루며, 타이밍 정확성을 보장합니다.
- I²C 핀 설정:
- 핀 할당: SCL(시리얼 클럭, PB6)과 SDA(시리얼 데이터, PB7)를 오픈 드레인 모드로 설정.
- 풀업 저항: 외부 또는 내부 풀업 저항(4.7kΩ 권장)을 사용하여 신호 안정성을 확보.
- 고속 전송: GPIO 속도를 매우 높은 속도(Very High Speed)로 설정, 대체 기능(AF4_I2C1)으로 I²C1 모듈과 연결.
- 클럭 활성화: GPIOB와 I2C1 모듈의 클럭을 활성화(__HAL_RCC_GPIOB_CLK_ENABLE, __HAL_RCC_I2C1_CLK_ENABLE).
- I²C 인터페이스 초기화:
- 주소 모드: 7비트 주소 모드 사용, ZSC31050의 기본 I²C 주소는 0x78(7비트, 8비트로 변환 시 0xF0).
- 타이밍 설정: 400kHz 통신을 위해 타이밍 레지스터를 0x00702991로 설정(80MHz 기준).
- 추가 설정: 듀얼 주소 비활성화, 일반 호출 비활성화, 클럭 스트레칭 활성화로 통신 안정성 강화.
- 동적 클럭 설정: CFGAPP:OSCF 비트(EEPROM 주소 0x18, 비트 6:5)를 읽어 내부 오실레이터 주파수(fCLK)를 설정. OSCF 값에 따라 fCLK는 1MHz(00), 2MHz(01 또는 10), 4MHz(11)로 조정되며, 기본값은 2MHz. 이 설정은 읽기/쓰기 타이밍을 동적으로 조정하는 데 사용됩니다.
- 오류 처리: 초기화 실패 시 오류 핸들러를 호출하여 LED 점멸 또는 UART를 통해 오류 메시지 출력(예: "I2C Initialization Failed").
- 타이밍 조정: 모든 I²C 명령의 실행 시간은 fCLK에 따라 조정되며, 기준 시간(2MHz)을 기반으로 스케일링(예: 1MHz일 경우 2배, 4MHz일 경우 0.5배).
이 단계는 ZSC31050과의 안정적인 I²C 통신을 위한 기반을 마련하며, 이후 명령 실행과 데이터 처리의 신뢰성을 보장합니다.
2. 명령 리스트 상세 설명
ZSC31050은 I²C 인터페이스를 통해 다양한 명령을 지원하여 센서의 동작 모드, 데이터 읽기/쓰기, EEPROM/RAM 관리 등을 제어합니다. 아래 테이블은 명령 리스트와 그 상세 설명을 정리한 것입니다.
명령어 | 코드 | 설명 | 실행 시간 (2MHz 기준) | 오류 코드 확인 |
---|---|---|---|---|
CMD_START_CM | 0x72 | Command Mode로 진입, 설정 및 데이터 조작 가능 | 50µs | 없음 |
CMD_START_CYC_EEP | 0x01 | EEPROM 기반 NOM 시작, EEPROM 설정으로 측정 | 350µs | 없음 |
CMD_START_CYC_RAM | 0x02 | RAM 기반 NOM 시작, RAM 설정으로 측정 | 220µs | 없음 |
CMD_READ_ZADC_P | 0xD1 | 원시 압력 데이터(Z_ADC_P) 읽기 | 50µs | 0xCAAA, 0xCF0F, 0xCCCC |
CMD_READ_ZCORR_P | 0xD8 | 보정된 압력 데이터(Z_CORR_P) 읽기 | 50µs | 0xCAAA, 0xCF0F, 0xCCCC |
CMD_READ_ZADC_T1 | 0xD2 | 원시 온도 1 데이터(Z_ADC_T1) 읽기 | 50µs | 0xCAAA, 0xCF0F, 0xCCCC |
CMD_READ_ZCORR_T1 | 0xD9 | 보정된 온도 1 데이터(Z_CORR_T1) 읽기 | 50µs | 0xCAAA, 0xCF0F, 0xCCCC |
CMD_READ_ZADC_T2 | 0xD3 | 원시 온도 2 데이터(Z_ADC_T2) 읽기 | 50µs | 0xCAAA, 0xCF0F, 0xCCCC |
CMD_READ_ZCORR_T2 | 0xDA | 보정된 온도 2 데이터(Z_CORR_T2) 읽기 | 50µs | 0xCAAA, 0xCF0F, 0xCCCC |
CMD_READ_EEP0 | 0x30~0x3F | EEPROM 주소 0x00~0x0F 읽기 | 50µs | 없음 |
CMD_READ_EEP1 | 0x40~0x4F | EEPROM 주소 0x10~0x1F 읽기 | 50µs | 없음 |
CMD_WRITE_EEP0 | 0xA0~0xAF | EEPROM 주소 0x00~0x0F 쓰기 | 12.5ms | 없음 |
CMD_WRITE_EEP1 | 0xB0~0xBF | EEPROM 주소 0x10~0x1F 쓰기 | 12.5ms | 없음 |
CMD_COPY_EEP2RAM | 0xC0 | EEPROM 데이터를 RAM으로 복사 | 130µs | 없음 |
CMD_COPY_RAM2EEP | 0xC3 | RAM 데이터를 EEPROM으로 복사 | 400ms | 0xCAAA (서명 오류) |
CMD_CLEAR_EEP | 0xCC | EEPROM 데이터 초기화 | 미지정 | 없음 |
CMD_GET_EEP_SIGN | 0xC8 | EEPROM 서명 읽기, 데이터 무결성 확인 | 50µs | 0xCAAA |
CMD_GEN_EEP_SIGN | 0xC9 | EEPROM 서명 생성 | 150µs | 없음 |
- 재시도 로직: 모든 I²C 전송/수신은 최대 3회 재시도를 포함하며, 각 시도 간 1ms 대기. 실패 시 오류 핸들러 호출.
- 타이밍 조정: 실행 시간은 fCLK(1MHz, 2MHz, 4MHz)에 따라 동적으로 조정. 예: 1MHz에서는 기준 시간의 2배, 4MHz에서는 0.5배.
- 오류 처리: 데이터 읽기 명령에서 반환된 값이 오류 코드(EEPROM_SIGN_ERROR: 0xCAAA, RAM_PARITY_ERROR: 0xCF0F, ADC_ERROR: 0xCCCC)일 경우 오류 핸들러 호출.
- 설명: 각 명령은 센서의 동작 모드 전환, 데이터 읽기/쓰기, 저장소 관리를 지원하며, 타이밍과 오류 처리는 시스템 안정성을 보장합니다.
3. ADC 및 센서 연결 설정
ZSC31050의 ADC와 센서 연결은 EEPROM 주소 0x16~0x1C(0x96~0x9C)에 저장된 구성 워드를 통해 설정됩니다. 아래 테이블은 각 워드의 비트별 설정과 설명을 정리한 것입니다.
주소 | 워드 | 값 | 비트 구성 | 설명 |
---|---|---|---|---|
0x96 | CFGCYC | 0x0048 | 15:10=000000 9:7=000 6:5=10 4:3=01 2=0 1=0 0=0 |
사용 안 함 교량 측정 횟수=1(npmc) IO1 출력=온도 1(ACOS2) OUT 출력=측정값(ACOS1) 공통 모드 전압 측정 비활성(CMVE) 온도 2 측정 비활성(T2E) 스타트업 ROM 체크 비활성(ROMCHE) |
0x97 | CFGSIF | 0x0034 | 15:9=0000000 8=0 7=0 6=0 5=1 4=1 3=0 2=1 1=0 0=0 |
대체 I²C 슬레이브 주소=0x00(SIFID2) 원와이어 통신 비활성(OWIE) 원와이어 시작 창 활성(OWIWIND) 온도 2 출력 비활성(SIFOUTT2) 온도 1 출력 활성(SIFOUTT1) 측정값 출력 활성(SIFOUTP) 대체 I²C 주소 비활성(SIFID2E) SPI 클럭 후행 엣지(SPICKE) SPI 클럭 저전위 유휴(SPICKP) I²C 통신 모드(SIFMD) |
0x98 | CFGAPP | 0x7625 | 15=0 14=1 13:12=11 11:10=01 9=1 8=0 7=0 6:5=01 4=0 3=0 2:1=10 0=1 |
브릿지 신호 극성=양(BSP) 사용 안 함, 항상 1 ADC 입력 범위=-1/2 VADC_REF ~ +1/2 VADC_REF(ADRAIN3, CFGTMP:TAM2=11 필요) IN3 참조=VDDA/2(IN3M, CFGTMP:TAM2=11 필요) 센서 연결 및 RAM 패리티 체크 비활성(SCCD) 센서 브릿지 여기=전압 공급(CSBE) 확장 제로 보상 비활성(XZCE) 오실레이터 주파수=2MHz(OSCF) 외부 클럭 비활성(ECLKE) ADC 참조 전압=VBR(ADREF) 아날로그 공급 전압=5.0V(VDC) 아날로그 공급 전압 제어 활성(VDCE) |
0x99 | CFGAFE | 0x9800 | 15:13=100 12=1 11:10=10 9=0 8:4=00000 3:0=0000 |
A/D 변환 해상도=13비트(RADC) A/D 변환 차수=2차(OADC) 측정값 ADC 입력 범위=-1/4 VADC_REF ~ +3/4 VADC_REF(ADRAPR) 확장 제로 보상 부호=음수(XZC, CFGAPP:XZCE=1 필요) 확장 제로 보상 값=0(XZC, CFGAPP:XZCE=1 필요) 측정값 아날로그 프론트엔드 게인=420(aIN_p) |
0x9A | CFGTMP | 0x0124 | 15:14=00 13:12=00 11=0 10=0 9:7=010 6:4=010 3:2=01 1:0=00 |
온도 2 아날로그 프론트엔드 게인=GT4 ≈ 5.65(GAINT2) 온도 1 아날로그 프론트엔드 게인=GT4 ≈ 5.65(GAINT1) 온도 2 외부 센서 극성=VSS(PETS2, CFGTMP:TAM2=01 or 10 필요) 온도 1 외부 센서 극성=VSS(PETS1) 온도 2 제로 포인트 조정(ZCT2) 온도 1 제로 포인트 조정(ZCT1) 온도 2 획득 모드=외부 다이오드(TAM2) 온도 1 획득 모드=내부 다이오드(TAM1) |
0x9B | CFGOUT | 0x8060 | 15:14=10 13:12=00 11:10=00 9=0 8=0 7=0 6:5=11 4=0 3:2=00 1:0=00 |
PWM 출력 해상도=11비트(PWMRES, PMIO1=10 또는 COS1=10 필요) PWM 출력 클럭 분주=fCLK/1(PTADWMD) PWM2/PWM1 출력 극성=하이 액티브(PWMPO) 사용 안 함 A/D 변환기 클럭 분주=fCLK/1(VFCCLKD) 알람 윈도우 모드=비활성(AWME) 알람 2/알람 1 출력 극성=하이 액티브(APO) IO2 출력 모드=비활성(PMIO2) IO1 출력 모드=비활성(PMIO1) OUT 포트 출력 모드=전압 출력(COS1) |
0x9C | ADJREF | 0x9248 | 15:13=100 12:10=100 9:7=100 6:4=010 3:0=1000 |
센서 브릿지 전류 조정=1배(CSB, CFGAPP:CSBE=1 필요) 아날로그 공급 전압 미세 조정=0%VDDA(VDCA, CFGAPP:VDCE 필요) 오실레이터 주파수 미세 조정=fCLK_NOM(OSCA, CFGAPP:OSCF와 연계) 바이어스 전류 조정=기본값(BCUR, 데이터 시트에서 xxx로 명시, 010으로 가정) 내부 밴드갭 전압 온도 특성 조정(VREF, CFGAPP:VDCE 및 VDC와 연계) |
- 설정 절차:
- Command Mode로 진입(CMD_START_CM, 0x72).
- CMD_WRITE_EEP1(0xB6~0xBC)을 사용하여 0x16~0x1C에 구성 워드를 기록. 각 쓰기 후 12.5ms 대기.
- 쓰기 완료 후 CMD_GEN_EEP_SIGN(0xC9, 150µs)으로 서명 생성, CMD_GET_EEP_SIGN(0xC8, 50µs)으로 무결성 확인. 서명 값이 0xCAAA일 경우 오류 처리.
- 의미: 이 설정은 ADC 해상도(13비트), 센서 연결(내부/외부 다이오드), 출력 포트(전압 출력), 오실레이터 주파수(2MHz), 전원 전압(5.0V)을 최적화하여 정확한 데이터 수집과 출력을 보장합니다.
4. 원시 센서 데이터 측정
원시 센서 데이터 측정은 ZSC31050의 ADC를 통해 압력 및 온도 데이터를 수집하여 하드웨어 연결과 기본 동작을 검증하는 단계입니다.
- Command Mode 진입: CMD_START_CM(0x72)을 전송하여 설정 모드로 전환, 50µs 대기.
- RAM 기반 NOM 시작: CMD_START_CYC_RAM(0x02)을 전송하여 RAM 설정으로 NOM 시작, 220µs 대기.
- 데이터 읽기:
- 압력 데이터: CMD_READ_ZADC_P(0xD1)을 전송하여 원시 압력 데이터(Z_ADC_P)를 수신. 16비트 데이터로 변환 후 오류 코드(0xCAAA, 0xCF0F, 0xCCCC) 확인.
- 온도 1 데이터: CMD_READ_ZADC_T1(0xD2)을 전송하여 원시 온도 1 데이터(Z_ADC_T1) 수신.
- 온도 2 데이터: CMD_READ_ZADC_T2(0xD3)을 전송하여 원시 온도 2 데이터(Z_ADC_T2) 수신.
- 타이밍: 각 읽기 명령 후 50µs 대기(fCLK=2MHz 기준, 동적 조정 적용).
- 출력: 데이터는 UART를 통해 출력(형식: "Z_ADC_P=0xXXXX, Z_ADC_T1=0xXXXX, Z_ADC_T2=0xXXXX"). 예: "Z_ADC_P=0x1234, Z_ADC_T1=0x5678, Z_ADC_T2=0x9ABC".
- 재시도 로직: I²C 전송/수신 실패 시 최대 3회 재시도, 각 시도 간 1ms 대기. 실패 시 오류 핸들러 호출(UART 메시지: "I2C Read Failed").
5. 보정 계수 EEPROM에 쓰기
보정 계수와 출력 제한 계수는 EEPROM 주소 0x10~0x15(0x80~0x95)에 기록되어 센서 데이터의 정확성을 높이고 출력 범위를 제한합니다. 아래 테이블은 계수와 설정 값을 정리한 것입니다.
주소 | 계수 | 값 | 설명 |
---|---|---|---|
0x80 | c0 | 0x0800 | 압력 오프셋, 측정값의 기준점 조정 |
0x81 | c1 | 0x2000 | 압력 게인, 측정값의 스케일링 조정 |
0x82 | c2 | 0x0000 | 압력 2차 비선형성 보정 |
0x83 | c3 | 0x0000 | 압력 3차 비선형성 보정 |
0x84 | c4 | 0x0000 | 교량 오프셋 1차 온도 계수 |
0x85 | c5 | 0x0000 | 교량 오프셋 2차 온도 계수 |
0x86 | c6 | 0x0000 | 게인 1차 온도 계수 |
0x87 | c7 | 0x0000 | 게인 2차 온도 계수 |
0x88 | lmin | 0x0000 | 출력 하한, 최소 출력 값 제한 |
0x89 | lmax | 0x07FF | 출력 상한, 최대 출력 값 제한 |
0x8A | t10 | 0x1000 | 온도 1 오프셋 |
0x8B | t11 | 0x2000 | 온도 1 게인 |
0x8C | t12 | 0x0000 | 온도 1 2차 비선형성 보정 |
0x8D | t20 | 0x1000 | 온도 2 오프셋 |
0x8E | t21 | 0x2000 | 온도 2 게인 |
0x8F | t22 | 0x0000 | 온도 2 2차 비선형성 보정 |
0x90 | Alarm 1 Threshold | 0x0000 | PWM1 하한 임계값 |
0x91 | Alarm 1 Hysteresis | 0x01FF | PWM1 상한 히스테리시스 |
0x92 | Alarm 1 Delay | 0x0000 | PWM1 온/오프 지연 |
0x93 | Alarm 2 Threshold | 0x0000 | 공통 모드 전압 하한 임계값 |
0x94 | Alarm 2 Hysteresis | 0xFFFF | 공통 모드 전압 상한 히스테리시스 |
0x95 | Alarm 2 Delay | 0x0000 | 공통 모드 전압 온/오프 지연 |
- 절차:
- Command Mode 진입(CMD_START_CM, 0x72, 50µs 대기).
- CMD_WRITE_EEP1(0xB0~0xC5)을 사용하여 0x10~0x15에 16비트 데이터를 순차적으로 기록. 각 쓰기 후 12.5ms 대기.
- 쓰기 완료 후 CMD_GEN_EEP_SIGN(0xC9, 150µs)으로 서명 생성, CMD_GET_EEP_SIGN(0xC8, 50µs)으로 무결성 확인. 서명 값이 0xCAAA일 경우 오류 핸들러 호출(UART 메시지: "EEPROM Signature Error").
6. NOM 전 최종 설정
NOM(Normal Operation Mode) 시작 전, EEPROM 데이터를 RAM으로 복사하고 최종 설정을 백업하여 안정적인 동작을 준비합니다.
- EEPROM→RAM 복사:
- CMD_COPY_EEP2RAM(0xC0)을 전송하여 EEPROM 데이터를 RAM으로 복사, 130µs 대기.
- 복사된 데이터는 CFGCYC, CFGSIF, CFGAPP, CFGAFE, CFGTMP, CFGOUT, ADJREF 및 보정 계수를 포함.
- RAM→EEPROM 백업:
- CMD_COPY_RAM2EEP(0xC3)을 전송하여 RAM 데이터를 EEPROM으로 백업, 400ms 대기.
- 백업 후 CMD_GEN_EEP_SIGN(0xC9, 150µs)과 CMD_GET_EEP_SIGN(0xC8, 50µs)을 호출하여 서명 생성/확인. 서명 오류(0xCAAA) 시 오류 핸들러 호출.
- 동적 클럭 확인: CFGAPP:OSCF(0x18, 비트 6:5)를 읽어 fCLK(1MHz, 2MHz, 4MHz)를 재확인하고, 모든 타이밍을 동적으로 조정.
7. 주기적 측정 수행
NOM 시작 후, ZSC31050은 주기적으로 보정된 데이터를 수집하여 애플리케이션에 제공합니다.
- RAM 기반 NOM 시작: CMD_START_CYC_RAM(0x02)을 전송하여 RAM 설정으로 NOM 시작, 220µs 대기.
- 주기적 데이터 읽기:
- 보정된 압력 데이터: CMD_READ_ZCORR_P(0xD8)을 호출하여 Z_CORR_P 수신.
- 보정된 온도 1 데이터: CMD_READ_ZCORR_T1(0xD9)을 호출하여 Z_CORR_T1 수신.
- 보정된 온도 2 데이터: CMD_READ_ZCORR_T2(0xDA)을 호출하여 Z_CORR_T2 수신.
- 타이밍: 각 읽기 명령 후 50µs 대기(fCLK=2MHz 기준). 측정 주기는 100ms.
- 출력: 데이터는 16비트로 변환되어 UART를 통해 출력(형식: "Z_CORR_P=0xXXXX, Z_CORR_T1=0xXXXX, Z_CORR_T2=0xXXXX").
- 오류 처리: 데이터가 오류 코드(0xCAAA, 0xCF0F, 0xCCCC)일 경우 오류 핸들러 호출(UART 메시지: "Data Read Error").
- 재시도 로직: I²C 전송/수신 실패 시 최대 3회 재시도, 각 시도 간 1ms 대기.
8. 구현 내용 및 코드
구현 내용
ZSC31050의 I²C 인터페이스 제어를 위한 코드는 STM32L4 시리즈 마이크로컨트롤러를 기반으로 작성되었으며, HAL(Hardware Abstraction Layer) 라이브러리를 사용하여 하드웨어 독립성을 확보합니다. 코드는 초기화, 명령 처리, ADC 설정, 보정 계수 저장, NOM 설정, 주기적 측정을 포함하며, 재시도 로직, 서명 생성/확인, RAM/EEPROM 관리, 동적 클럭 설정을 지원합니다.
- 구조:
- 헤더 및 정의: STM32 HAL 헤더와 ZSC31050 명령, 타이밍, 오류 코드를 정의. 예: ZSC31050_ADDR(0x78<<1), CMD_START_CM(0x72), BASE_READ_TIME(50µs).
- 주요 함수:
I2C1_Init
: I²C 인터페이스 초기화(400kHz, 7비트 주소, PB6/PB7 핀).ZSC31050_SetClockDynamic
: CFGAPP:OSCF를 읽어 fCLK 동적 설정(1MHz, 2MHz, 4MHz).ZSC31050_EnterCommandMode
: Command Mode 진입(CMD_START_CM).ZSC31050_ReadEEPROM_Single
/ZSC31050_WriteEEPROM_Single
: 단일 EEPROM 주소 읽기/쓰기.ZSC31050_ConfigureEEPROM
: ADC 및 센서 설정(0x96~0x9C) 기록.ZSC31050_WriteCalibrationCoefficients
: 보정 및 출력 제한 계수(0x80~0x95) 기록.ZSC31050_ReadRawData
: 원시 및 보정 데이터 읽기(Z_ADC_P, Z_CORR_P 등).ZSC31050_GenerateAndVerifySignature
: EEPROM 서명 생성/확인.ZSC31050_CopyEEPROMtoRAM
/ZSC31050_CopyRAMtoEEPROM
: RAM/EEPROM 데이터 복사.ZSC31050_StartNOM_RAM
: RAM 기반 NOM 시작.ZSC31050_PeriodicMeasurement
: 주기적 데이터 수집 및 출력.
- 오류 처리: I²C 전송/수신 실패 시 최대 3회 재시도, 오류 코드(0xCAAA, 0xCF0F, 0xCCCC) 확인, UART를 통한 오류 메시지 출력.
- 타이밍 조정: fCLK에 따라 동적 타이밍 스케일링(AdjustTiming 함수).
- 동작 흐름:
- 시스템 및 I²C 초기화.
- CFGAPP:OSCF를 읽어 fCLK 설정.
- EEPROM에 ADC 및 센서 설정(0x96~0x9C) 기록, 서명 확인.
- Command Mode 진입 후 원시 데이터 읽기.
- 보정 계수(0x80~0x95) 기록, 서명 확인.
- EEPROM→RAM 복사, RAM→EEPROM 백업.
- RAM 기반 NOM 시작, 주기적 측정(100ms 주기).
- 특징:
- 재시도 로직: I²C 통신 안정성을 위해 최대 3회 재시도.
- 서명 관리: EEPROM 쓰기 및 복사 후 서명 생성/확인으로 데이터 무결성 보장.
- 동적 클럭: CFGAPP:OSCF 기반 fCLK 설정으로 유연한 타이밍 조정.
- UART 출력: 원시 및 보정 데이터 출력으로 디버깅 용이성 제공.
구현 코드
#include "stm32l4xx_hal.h"
#include <stdio.h>
// I2C 핸들러 및 클럭 정의 (I2C handler and clock definitions)
I2C_HandleTypeDef hi2c1; // I2C1 인터페이스 핸들러 (I2C1 interface handler)
typedef enum {
FCLK_1MHZ = 1, // 1MHz 클럭 (1MHz clock)
FCLK_2MHZ = 2, // 2MHz 클럭 (2MHz clock)
FCLK_4MHZ = 4 // 4MHz 클럭 (4MHz clock)
} ZSC31050_Clock_t;
static ZSC31050_Clock_t fCLK = FCLK_2MHZ; // 기본 클럭: 2MHz (Default clock: 2MHz)
#define MAX_I2C_RETRIES 3 // 최대 재전송 횟수 (Maximum retry attempts)
// 명령 및 타이밍 정의 (Command and timing definitions)
#define ZSC31050_ADDR 0x78 << 1 // 7비트 주소 0x78을 8비트로 변환 (7-bit address 0x78 shifted to 8-bit)
#define CMD_START_CM 0x72 // Command Mode 시작 (Start Command Mode)
#define CMD_START_CYC_EEP 0x01 // EEPROM 기반 NOM 시작 (Start NOM with EEPROM)
#define CMD_START_CYC_RAM 0x02 // RAM 기반 NOM 시작 (Start NOM with RAM)
#define CMD_READ_ZADC_P 0xD1 // 압력 원시 데이터(Z_ADC_P) 읽기 (Read raw pressure data Z_ADC_P)
#define CMD_READ_ZCORR_P 0xD8 // 보정된 압력 데이터(Z_CORR_P) 읽기 (Read corrected pressure data Z_CORR_P)
#define CMD_READ_ZADC_T1 0xD2 // 온도1 원시 데이터(Z_ADC_T1) 읽기 (Read raw temperature1 data Z_ADC_T1)
#define CMD_READ_ZCORR_T1 0xD9 // 보정된 온도1 데이터(Z_CORR_T1) 읽기 (Read corrected temperature1 data Z_CORR_T1)
#define CMD_READ_ZADC_T2 0xD3 // 온도2 원시 데이터(Z_ADC_T2) 읽기 (Read raw temperature2 data Z_ADC_T2)
#define CMD_READ_ZCORR_T2 0xDA // 보정된 온도2 데이터(Z_CORR_T2) 읽기 (Read corrected temperature2 data Z_CORR_T2)
#define CMD_READ_EEP0 0x30 // EEPROM 주소 0x00~0x0F 읽기 (Read EEPROM addresses 0x00~0x0F)
#define CMD_READ_EEP1 0x40 // EEPROM 주소 0x10~0x1F 읽기 (Read EEPROM addresses 0x10~0x1F)
#define CMD_WRITE_EEP0 0xA0 // EEPROM 주소 0x00~0x0F 쓰기 (Write EEPROM addresses 0x00~0x0F)
#define CMD_WRITE_EEP1 0xB0 // EEPROM 주소 0x10~0x1F 쓰기 (Write EEPROM addresses 0x10~0x1F)
#define CMD_COPY_EEP2RAM 0xC0 // EEPROM 데이터를 RAM으로 복사 (Copy EEPROM to RAM)
#define CMD_COPY_RAM2EEP 0xC3 // RAM 데이터를 EEPROM으로 복사 (Copy RAM to EEPROM)
#define CMD_CLEAR_EEP 0xCC // EEPROM 지우기 (Clear EEPROM)
#define CMD_GET_EEP_SIGN 0xC8 // EEPROM 서명 읽기 (Read EEPROM signature)
#define CMD_GEN_EEP_SIGN 0xC9 // EEPROM 서명 생성 (Generate EEPROM signature)
#define EEPROM_SIGN_ERROR 0xCAAA // EEPROM 서명 오류 (EEPROM signature error)
#define RAM_PARITY_ERROR 0xCF0F // RAM 패리티 오류 (RAM parity error)
#define ADC_ERROR 0xCCCC // ADC 오류 (ADC error)
#define BASE_READ_TIME 50 // 읽기 시간 (µs, 2MHz 기준) (Read time in µs at 2MHz)
#define BASE_WRITE_TIME 12500 // 쓰기 시간 (µs) (Write time in µs)
#define BASE_SIGN_TIME 150 // 서명 생성/확인 시간 (Signature generation/verification time)
#define BASE_CYC_EEP_TIME 350 // EEPROM 기반 NOM 시작 시간 (Time to start NOM with EEPROM)
#define BASE_CYC_RAM_TIME 220 // RAM 기반 NOM 시작 시간 (Time to start NOM with RAM)
#define BASE_COPY_EEP2RAM 130 // EEPROM→RAM 복사 시간 (EEPROM to RAM copy time)
#define BASE_COPY_RAM2EEP 400000 // RAM→EEPROM 복사 시간 (RAM to EEPROM copy time)
// 타이밍 조정 (Timing adjustment)
static uint32_t AdjustTiming(uint32_t base_time) {
// 클럭 주파수(fCLK)에 따라 타이밍 조정 (Adjust timing based on fCLK)
return (uint32_t)(base_time * (2.0f / fCLK));
}
// 오류 처리 (Error handling)
void Error_Handler(void) {
// I²C 또는 기타 오류 시 무한 루프 (Infinite loop on I²C or other errors)
while (1) {
// LED 또는 UART로 오류 표시 (Indicate error via LED or UART)
}
}
// I2C 초기화 및 명령 함수 (I2C initialization and command functions)
void I2C1_Init(void) {
// I2C1 인터페이스 설정 (Configure I2C1 interface)
hi2c1.Instance = I2C1;
hi2c1.Init.Timing = 0x00702991; // 80MHz에서 400kHz (400kHz at 80MHz)
hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT; // 7비트 주소 모드 (7-bit addressing mode)
hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE; // 듀얼 주소 비활성 (Disable dual addressing)
hi2c1.Init.OwnAddress2 = 0; // 두 번째 주소 사용 안 함 (No second address)
hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE; // 일반 호출 비활성 (Disable general call)
hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE; // 클럭 스트레칭 활성 (Enable clock stretching)
if (HAL_I2C_Init(&hi2c1) != HAL_OK) {
Error_Handler(); // 초기화 실패 시 오류 처리 (Handle error on initialization failure)
}
}
void HAL_I2C_MspInit(I2C_HandleTypeDef* hi2c) {
// I2C1 핀 및 클럭 설정 (Configure I2C1 pins and clock)
GPIO_InitTypeDef GPIO_InitStruct = {0};
if (hi2c->Instance == I2C1) {
__HAL_RCC_GPIOB_CLK_ENABLE(); // GPIOB 클럭 활성화 (Enable GPIOB clock)
GPIO_InitStruct.Pin = GPIO_PIN_6 | GPIO_PIN_7; // PB6(SCL), PB7(SDA)
GPIO_InitStruct.Mode = GPIO_MODE_AF_OD; // 오픈 드레인 모드 (Open-drain mode)
GPIO_InitStruct.Pull = GPIO_PULLUP; // 풀업 저항 (Pull-up resistor)
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; // 고속 전송 (High-speed transmission)
GPIO_InitStruct.Alternate = GPIO_AF4_I2C1; // I2C1 대체 기능 (Alternate function for I2C1)
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); // GPIO 초기화 (Initialize GPIO)
__HAL_RCC_I2C1_CLK_ENABLE(); // I2C1 클럭 활성화 (Enable I2C1 clock)
}
}
HAL_StatusTypeDef ZSC31050_I2C_Transmit(uint8_t *data, uint16_t size) {
// I²C 전송 재시도 로직 (I²C transmission with retry logic)
uint8_t retries = 0;
HAL_StatusTypeDef status;
while (retries < MAX_I2C_RETRIES) {
status = HAL_I2C_Master_Transmit(&hi2c1, ZSC31050_ADDR, data, size, HAL_MAX_DELAY);
if (status == HAL_OK) return HAL_OK;
HAL_Delay(1); // 재시도 전 1ms 대기 (1ms wait before retry)
retries++;
}
return status;
}
HAL_StatusTypeDef ZSC31050_I2C_Receive(uint8_t *data, uint16_t size) {
// I²C 수신 재시도 로직 (I²C reception with retry logic)
uint8_t retries = 0;
HAL_StatusTypeDef status;
while (retries < MAX_I2C_RETRIES) {
status = HAL_I2C_Master_Receive(&hi2c1, ZSC31050_ADDR | 0x01, data, size, HAL_MAX_DELAY);
if (status == HAL_OK) return HAL_OK;
HAL_Delay(1); // 재시도 전 1ms 대기 (1ms wait before retry)
retries++;
}
return status;
}
HAL_StatusTypeDef ZSC31050_SetClockDynamic(void) {
// CFGAPP:OSCF에서 동적으로 클럭 설정 (Dynamically set clock from CFGAPP:OSCF)
uint16_t cfgapp;
HAL_StatusTypeDef status = ZSC31050_ReadEEPROM_Single(0x18, &cfgapp); // CFGAPP(0x98) 읽기 (Read CFGAPP at 0x98)
if (status != HAL_OK) return status;
uint8_t oscf = (cfgapp >> 5) & 0x03; // OSCF 비트 추출 (Extract OSCF bits)
switch (oscf) {
case 0: fCLK = FCLK_1MHZ; break;
case 1: fCLK = FCLK_2MHZ; break;
case 2: fCLK = FCLK_2MHZ; break;
case 3: fCLK = FCLK_4MHZ; break;
default: fCLK = FCLK_2MHZ; // 기본값 (Default)
}
printf("동적 클럭 설정: %d MHz (Dynamic clock set: %d MHz)\n", fCLK);
return HAL_OK;
}
HAL_StatusTypeDef ZSC31050_EnterCommandMode(void) {
// START_CM(0x72) 명령으로 Command Mode 진입 (Enter Command Mode with START_CM(0x72))
uint8_t cmd = CMD_START_CM;
HAL_StatusTypeDef status = ZSC31050_I2C_Transmit(&cmd, 1);
if (status == HAL_OK) {
HAL_Delay(AdjustTiming(BASE_READ_TIME) / 1000 + 1); // 읽기 시간 대기 (Wait for read time)
}
return status;
}
HAL_StatusTypeDef ZSC31050_ReadEEPROM_Single(uint8_t addr, uint16_t *data) {
// 단일 주소(0x00~0x1F)에서 EEPROM 데이터 읽기 (Read EEPROM data from single address 0x00~0x1F)
if (addr > 0x1F) return HAL_ERROR; // 주소 범위 확인 (Check address range)
uint8_t cmd = (addr < 0x10) ? (CMD_READ_EEP0 + addr) : (CMD_READ_EEP1 + (addr - 0x10)); // READ_EEP0/1 선택 (Select READ_EEP0/1)
HAL_StatusTypeDef status = ZSC31050_I2C_Transmit(&cmd, 1); // 명령 전송 (Send command)
if (status != HAL_OK) return status;
HAL_Delay(AdjustTiming(BASE_READ_TIME) / 1000 + 1); // 읽기 시간 대기 (Wait for read time)
uint8_t buffer[2];
status = ZSC31050_I2C_Receive(buffer, 2); // 데이터 수신 (Receive data)
if (status == HAL_OK) {
*data = (buffer[0] << 8) | buffer[1]; // 16비트 데이터로 변환 (Convert to 16-bit data)
}
return status;
}
HAL_StatusTypeDef ZSC31050_WriteEEPROM_Single(uint8_t addr, uint16_t data) {
// 단일 주소(0x00~0x1F)에 EEPROM 데이터 쓰기 (Write EEPROM data to single address 0x00~0x1F)
if (addr > 0x1F) return HAL_ERROR; // 주소 범위 확인 (Check address range)
uint8_t cmd = (addr < 0x10) ? (CMD_WRITE_EEP0 + addr) : (CMD_WRITE_EEP1 + (addr - 0x10)); // WRITE_EEP0/1 선택 (Select WRITE_EEP0/1)
uint8_t buffer[3] = {cmd, (data >> 8) & 0xFF, data & 0xFF}; // 명령과 데이터 준비 (Prepare command and data)
HAL_StatusTypeDef status = ZSC31050_I2C_Transmit(buffer, 3); // 데이터 전송 (Send data)
if (status == HAL_OK) {
HAL_Delay(AdjustTiming(BASE_WRITE_TIME) / 1000 + 1); // 쓰기 시간 대기 (Wait for write time)
}
return status;
}
HAL_StatusTypeDef ZSC31050_WriteEEPROM(uint8_t start_addr, uint16_t *data, uint8_t count) {
// 연속된 EEPROM 주소에 데이터 쓰기 (Write data to consecutive EEPROM addresses)
if (start_addr + count > 0x20) return HAL_ERROR; // 주소 범위 확인 (Check address range)
HAL_StatusTypeDef status = HAL_OK;
for (uint8_t i = 0; i < count; i++) {
status = ZSC31050_WriteEEPROM_Single(start_addr + i, data[i]); // 단일 주소 쓰기 호출 (Call single address write)
if (status != HAL_OK) break;
}
if (status == HAL_OK) {
uint16_t signature;
status = ZSC31050_GenerateAndVerifySignature(&signature); // 쓰기 후 서명 생성/확인 (Generate/verify signature after write)
}
return status;
}
HAL_StatusTypeDef ZSC31050_ConfigureEEPROM(void) {
// NOM을 위한 EEPROM 구성 워드 설정 (Configure EEPROM words for NOM)
uint16_t config_data[7] = {
0x0048, // CFGCYC(0x96): 측정 주기 설정
// 비트 15:10=000000 (사용 안 함, Not used)
// 비트 9:7=000 (npmc=2^0=1, 교량 측정 횟수, Number of bridge measurements per cycle)
// 비트 6:5=10 (ACOS2, IO1 출력=온도 1, Output Temperature 1 at IO1)
// 비트 4:3=01 (ACOS1, OUT 출력=측정값, Output Measurand at OUT)
// 비트 2=0 (CMVE, 공통 모드 전압 측정 비활성, Common-mode voltage measurement disabled)
// 비트 1=0 (T2E, 온도 2 측정 비활성, Temperature 2 measurement disabled)
// 비트 0=0 (ROMCHE, 스타트업 ROM 체크 비활성, Start-up ROM check disabled)
0x0034, // CFGSIF(0x97): 디지털 직렬 인터페이스 설정
// 비트 15:9=0000000 (SIFID2, 대체 I²C 슬레이브 주소=0x00, Alternative I²C slave address=0x00)
// 비트 8=0 (OWIE, 원와이어 통신 비활성, One-wire communication disabled)
// 비트 7=0 (OWIWIND, 원와이어 시작 창 활성, One-wire start window enabled)
// 비트 6=0 (SIFOUTT2, 온도 2 출력 비활성, Temperature 2 output disabled)
// 비트 5=1 (SIFOUTT1, 온도 1 출력 활성, Temperature 1 output enabled)
// 비트 4=1 (SIFOUTP, 측정값 출력 활성, Measurand output enabled)
// 비트 3=0 (SIFID2E, 대체 I²C 주소 비활성, Alternative I²C address disabled)
// 비트 2=1 (SPICKE, SPI 클럭 후행 엣지, SPI clock trailing edge)
// 비트 1=0 (SPICKP, SPI 클럭 저전위 유휴, SPI clock low idle)
// 비트 0=0 (SIFMD, I²C 통신 모드, I²C communication mode)
0x7625, // CFGAPP(0x98): 타겟 애플리케이션 설정
// 비트 15=0 (BSP, 브릿지 신호 극성=양, Bridge signal polarity=positive, VBR_DIFF=VBR_P-VBR_N)
// 비트 14=1 (사용 안 함, 항상 1, Not used, always 1)
// 비트 13:12=11 (ADRAIN3, ADC 입력 범위=-1/2 VADC_REF ~ +1/2 VADC_REF, CFGTMP:TAM2=11 필요, ADC input range, requires CFGTMP:TAM2=11)
// 비트 11:10=01 (IN3M, IN3 참조=VDDA/2, CFGTMP:TAM2=11 필요, IN3 reference=VDDA/2, requires CFGTMP:TAM2=11)
// 비트 9=1 (SCCD, 센서 연결 및 RAM 패리티 체크 비활성, Sensor connection and RAM parity check disabled)
// 비트 8=0 (CSBE, 센서 브릿지 여기=전압 공급, Sensor bridge excitation=voltage supplied)
// 비트 7=0 (XZCE, 확장 제로 보상 비활성, Extended zero compensation disabled)
// 비트 6:5=01 (OSCF, 오실레이터 주파수=2MHz, Oscillator frequency=2MHz)
// 비트 4=0 (ECLKE, 외부 클럭 비활성, External clock disabled)
// 비트 3=0 (ADREF, ADC 참조 전압=VBR, ADC reference voltage=VBR)
// 비트 2:1=10 (VDC, 아날로그 공급 전압=5.0V, Analog supply voltage=5.0V)
// 비트 0=1 (VDCE, 아날로그 공급 전압 제어 활성, Analog supply voltage control enabled)
0x9800, // CFGAFE(0x99): 아날로그 프론트엔드 설정, 13비트 해상도 (Analog front-end configuration, 13-bit resolution)
// 비트 15:13=100 (RADC, A/D 변환 해상도=13비트, A/D conversion resolution=13 bits)
// 비트 12=1 (OADC, A/D 변환 차수=2차, A/D conversion order=2nd order)
// 비트 11:10=10 (ADRAPR, 측정값 ADC 입력 범위=-1/4 VADC_REF ~ +3/4 VADC_REF, Measurand ADC input range=-1/4 VADC_REF to +3/4 VADC_REF)
// 비트 9=0 (XZC, 확장 제로 보상 부호=음수, Extended zero compensation sign=negative, CFGAPP:XZCE=1 필요, requires CFGAPP:XZCE=1)
// 비트 8:4=00000 (XZC, 확장 제로 보상 값=0, Extended zero compensation value=0, CFGAPP:XZCE=1 필요, requires CFGAPP:XZCE=1)
// 비트 3:0=0000 (aIN_p, 측정값 아날로그 프론트엔드 게인=420, Measurand analog front-end gain=420)
0x0124, // CFGTMP(0x9A): 온도 측정 설정
// 비트 15:14=00 (GAINT2, 온도 2 아날로그 프론트엔드 게인=GT4 ≈ 5.65, Temperature 2 analog front-end gain=GT4 ≈ 5.65)
// 비트 13:12=00 (GAINT1, 온도 1 아날로그 프론트엔드 게인=GT4 ≈ 5.65, Temperature 1 analog front-end gain=GT4 ≈ 5.65)
// 비트 11=0 (PETS2, 온도 2 외부 센서 극성=VSS, Temperature 2 external sensor polarity=VSS, CFGTMP:TAM2=01 or 10 필요, requires CFGTMP:TAM2=01 or 10)
// 비트 10=0 (PETS1, 온도 1 외부 센서 극성=VSS, Temperature 1 external sensor polarity=VSS)
// 비트 9:7=010 (ZCT2, 온도 2 제로 포인트 조정, Temperature 2 zero-point adjust)
// 비트 6:4=010 (ZCT1, 온도 1 제로 포인트 조정, Temperature 1 zero-point adjust)
// 비트 3:2=01 (TAM2, 온도 2 획득 모드=외부 다이오드, Temperature 2 acquisition mode=external diode)
// 비트 1:0=00 (TAM1, 온도 1 획득 모드=내부 다이오드, Temperature 1 acquisition mode=internal diode)
0x8060, // CFGOUT(0x9B): 신호 출력 설정
// 비트 15:14=10 (PWMRES, PWM 출력 해상도=11비트, PWM output resolution=11 bits, PMIO1=10 또는 COS1=10 필요, requires PMIO1=10 or COS1=10)
// 비트 13:12=00 (PTADWMD, PWM 출력 클럭 분주=fCLK/1, PWM output clock divider=fCLK/1)
// 비트 11:10=00 (PWMPO, PWM2/PWM1 출력 극성=하이 액티브, PWM2/PWM1 output polarity=high-active)
// 비트 9=0 (사용 안 함, No access)
// 비트 8=0 (VFCCLKD, A/D 변환기 클럭 분주=fCLK/1, A/D converter clock divider=fCLK/1)
// 비트 7=0 (AWME, 알람 윈도우 모드=비활성, Alarm window mode=disabled)
// 비트 6:5=11 (APO, 알람 2/알람 1 출력 극성=하이 액티브, Alarm 2/Alarm 1 output polarity=high-active)
// 비트 4=0 (PMIO2, IO2 출력 모드=비활성, IO2 output mode=disabled)
// 비트 3:2=00 (PMIO1, IO1 출력 모드=비활성, IO1 output mode=disabled)
// 비트 1:0=00 (COS1, OUT 포트 출력 모드=전압 출력, OUT port output mode=voltage output)
0x9248 // ADJREF(0x9C): 내부 참조 조정
// 비트 15:13=100 (CSB, 센서 브릿지 전류 조정=1배, Sensor bridge current adjustment=1x, CFGAPP:CSBE=1 필요, requires CFGAPP:CSBE=1)
// 비트 12:10=100 (VDCA, 아날로그 공급 전압 미세 조정=0%VDDA, Fine adjustment of analog supply voltage=0%VDDA, CFGAPP:VDCE 필요, requires CFGAPP:VDCE)
// 비트 9:7=100 (OSCA, 오실레이터 주파수 미세 조정=fCLK_NOM, Oscillator frequency fine adjustment=fCLK_NOM, CFGAPP:OSCF와 연계, linked with CFGAPP:OSCF)
// 비트 6:4=010 (BCUR, 바이어스 전류 조정=기본값, Bias current adjustment=default, 데이터 시트에서 xxx로 명시, assumed 010 for default)
// 비트 3:0=1000 (VREF, 내부 밴드갭 전압 온도 특성 조정, TC adjustment of internal bandgap voltage, CFGAPP:VDCE 및 VDC와 연계, linked with CFGAPP:VDCE and VDC)
};
HAL_StatusTypeDef status = ZSC31050_EnterCommandMode(); // Command Mode 진입 (Enter Command Mode)
if (status != HAL_OK) return status;
status = ZSC31050_WriteEEPROM(0x16, config_data, 7); // 주소 0x96~0x9C(명령 0xB6~0xBC) 쓰기 (Write to 0x96~0x9C using 0xB6~0xBC)
if (status == HAL_OK) {
uint16_t signature;
status = ZSC31050_GenerateAndVerifySignature(&signature); // 쓰기 후 서명 생성/확인 (Generate/verify signature after write)
}
return status;
}
HAL_StatusTypeDef ZSC31050_WriteCalibrationCoefficients(void) {
// 보정 계수 및 출력 제한 계수를 EEPROM 주소 0x80~0x95에 쓰기 (Write calibration and output limit coefficients to EEPROM 0x80~0x95)
uint16_t calib_data[22] = {
0x0800, // c0: Offset (Measurand)
0x2000, // c1: Gain
0x0000, // c2: Non-linearity 2nd order
0x0000, // c3: Non-linearity 3rd order
0x0000, // c4: Temp coefficient Bridge Offset 1st order
0x0000, // c5: Temp coefficient Bridge Offset 2nd order
0x0000, // c6: Temp coefficient Gain 1st order
0x0000, // c7: Temp coefficient Gain 2nd order
0x0000, // lmin: Lower Limit (Output)
0x07FF, // lmax: Upper Limit
0x1000, // t10: Offset Temperature 1
0x2000, // t11: Gain Temperature 1
0x0000, // t12: Non-linearity 2nd order Temperature 1
0x1000, // t20: Offset Temperature 2
0x2000, // t21: Gain Temperature 2
0x0000, // t22: Non-linearity 2nd order Temperature 2
0x0000, // Alarm 1: Threshold PWM1 (Lower Limit)
0x01FF, // Alarm 1: Hysteresis PWM1 (Upper Limit)
0x0000, // Alarm 1: On-/Off-delay
0x0000, // Alarm 2: Threshold Common-mode voltage (Lower Limit)
0xFFFF, // Alarm 2: Hysteresis Common-mode voltage (Upper Limit)
0x0000 // Alarm 2: On-/Off-delay
};
HAL_StatusTypeDef status = ZSC31050_EnterCommandMode(); // Command Mode 진입 (Enter Command Mode)
if (status != HAL_OK) return status;
return ZSC31050_WriteEEPROM(0x10, calib_data, 22); // 주소 0x80~0x95(명령 0xB0~0xC5) 쓰기 (Write to 0x80~0x95 using 0xB0~0xC5)
}
HAL_StatusTypeDef ZSC31050_ReadRawData(uint8_t cmd, uint16_t *data) {
// 원시 데이터(Z_ADC, Z_CORR) 읽기 (Read raw or corrected data)
HAL_StatusTypeDef status = ZSC31050_I2C_Transmit(&cmd, 1); // 명령 전송 (Send command)
if (status != HAL_OK) return status;
HAL_Delay(AdjustTiming(BASE_READ_TIME) / 1000 + 1); // 읽기 시간 대기 (Wait for read time)
uint8_t buffer[2];
status = ZSC31050_I2C_Receive(buffer, 2); // 데이터 수신 (Receive data)
if (status == HAL_OK) {
*data = (buffer[0] << 8) | buffer[1]; // 16비트 데이터로 변환 (Convert to 16-bit data)
if (*data == EEPROM_SIGN_ERROR || *data == RAM_PARITY_ERROR || *data == ADC_ERROR) {
return HAL_ERROR; // 오류 코드 확인 (Check error codes)
}
}
return status;
}
HAL_StatusTypeDef ZSC31050_GenerateAndVerifySignature(uint16_t *signature) {
// EEPROM 서명 생성 및 확인 (Generate and verify EEPROM signature)
uint8_t cmd = CMD_GEN_EEP_SIGN;
HAL_StatusTypeDef status = ZSC31050_I2C_Transmit(&cmd, 1); // 서명 생성 명령 전송 (Send signature generation command)
if (status != HAL_OK) return status;
HAL_Delay(AdjustTiming(BASE_SIGN_TIME) / 1000 + 1); // 서명 생성 시간 대기 (Wait for signature generation time)
cmd = CMD_GET_EEP_SIGN;
status = ZSC31050_I2C_Transmit(&cmd, 1); // 서명 읽기 명령 전송 (Send signature read command)
if (status != HAL_OK) return status;
HAL_Delay(AdjustTiming(BASE_READ_TIME) / 1000 + 1); // 읽기 시간 대기 (Wait for read time)
uint8_t buffer[2];
status = ZSC31050_I2C_Receive(buffer, 2); // 서명 데이터 수신 (Receive signature data)
if (status == HAL_OK) {
*signature = (buffer[0] << 8) | buffer[1]; // 16비트 서명으로 변환 (Convert to 16-bit signature)
if (*signature == EEPROM_SIGN_ERROR) return HAL_ERROR; // 서명 오류 확인 (Check for signature error)
}
return status;
}
HAL_StatusTypeDef ZSC31050_CopyEEPROMtoRAM(void) {
// EEPROM 데이터를 RAM으로 복사 (Copy EEPROM to RAM)
uint8_t cmd = CMD_COPY_EEP2RAM;
HAL_StatusTypeDef status = ZSC31050_I2C_Transmit(&cmd, 1);
if (status == HAL_OK) {
HAL_Delay(AdjustTiming(BASE_COPY_EEP2RAM) / 1000 + 1); // 130µs 대기 (Wait 130µs)
}
return status;
}
HAL_StatusTypeDef ZSC31050_CopyRAMtoEEPROM(void) {
// RAM 데이터를 EEPROM으로 복사 (Copy RAM to EEPROM)
uint8_t cmd = CMD_COPY_RAM2EEP;
HAL_StatusTypeDef status = ZSC31050_I2C_Transmit(&cmd, 1);
if (status == HAL_OK) {
HAL_Delay(AdjustTiming(BASE_COPY_RAM2EEP) / 1000 + 1); // 400ms 대기 (Wait 400ms)
uint16_t signature;
status = ZSC31050_GenerateAndVerifySignature(&signature); // 복사 후 서명 생성/확인 (Generate/verify signature after copy)
}
return status;
}
HAL_StatusTypeDef ZSC31050_StartNOM_RAM(void) {
// START_CYC_RAM(0x02) 명령으로 RAM 기반 NOM 시작 (Start NOM with RAM using START_CYC_RAM(0x02))
uint8_t cmd = CMD_START_CYC_RAM;
HAL_StatusTypeDef status = ZSC31050_I2C_Transmit(&cmd, 1);
if (status == HAL_OK) {
HAL_Delay(AdjustTiming(BASE_CYC_RAM_TIME) / 1000 + 1); // NOM 시작 시간 대기 (Wait for NOM start time)
printf("NOM이 RAM 기반으로 시작됨 (NOM Started with RAM)\n");
}
return status;
}
void ZSC31050_PeriodicMeasurement(void) {
// 주기적 측정 수행 (Perform periodic measurements)
uint16_t z_corr_p, z_corr_t1, z_corr_t2;
while (1) {
if (ZSC31050_ReadRawData(CMD_READ_ZCORR_P, &z_corr_p) != HAL_OK) Error_Handler();
if (ZSC31050_ReadRawData(CMD_READ_ZCORR_T1, &z_corr_t1) != HAL_OK) Error_Handler();
if (ZSC31050_ReadRawData(CMD_READ_ZCORR_T2, &z_corr_t2) != HAL_OK) Error_Handler();
printf("Z_CORR_P=0x%04X, Z_CORR_T1=0x%04X, Z_CORR_T2=0x%04X\n", z_corr_p, z_corr_t1, z_corr_t2);
HAL_Delay(100); // 100ms 주기 (100ms cycle)
}
}
int main(void) {
// 시스템 및 I2C 초기화 (Initialize system and I2C)
HAL_Init();
// 시스템 클럭 설정 (예: 80MHz, 실제 구현 필요) (System clock configuration, e.g., 80MHz, requires actual implementation)
I2C1_Init();
// 변수 선언 (Declare variables)
uint16_t z_adc_p, z_adc_t1, z_adc_t2, signature;
// 1. 동적 클럭 설정 및 EEPROM 구성 (Dynamic clock setting and EEPROM configuration)
printf("CFGAPP:OSCF에서 동적 클럭 설정 (Setting dynamic clock from CFGAPP:OSCF)\n");
if (ZSC31050_SetClockDynamic() != HAL_OK) Error_Handler();
printf("NOM을 위한 EEPROM 구성 설정 (Configuring EEPROM for NOM)\n");
if (ZSC31050_ConfigureEEPROM() != HAL_OK) Error_Handler();
// 2. Command Mode 진입 및 원시 데이터 읽기 (Enter Command Mode and read raw data)
printf("Command Mode 진입 (Entering Command Mode)\n");
if (ZSC31050_EnterCommandMode() != HAL_OK) Error_Handler();
printf("RAM 기반 NOM 시작 후 원시 데이터 읽기 (Reading raw data after starting RAM-based NOM)\n");
if (ZSC31050_StartNOM_RAM() != HAL_OK) Error_Handler();
if (ZSC31050_ReadRawData(CMD_READ_ZADC_P, &z_adc_p) != HAL_OK) Error_Handler();
if (ZSC31050_ReadRawData(CMD_READ_ZADC_T1, &z_adc_t1) != HAL_OK) Error_Handler();
if (ZSC31050_ReadRawData(CMD_READ_ZADC_T2, &z_adc_t2) != HAL_OK) Error_Handler();
printf("Z_ADC_P=0x%04X, Z_ADC_T1=0x%04X, Z_ADC_T2=0x%04X\n", z_adc_p, z_adc_t1, z_adc_t2);
// 3. 보정 계수 및 출력 제한 계수 EEPROM에 쓰기 (Write calibration and output limit coefficients to EEPROM)
printf("Command Mode 진입 후 보정 및 출력 제한 계수 쓰기 (Writing calibration and output limit coefficients after entering Command Mode)\n");
if (ZSC31050_WriteCalibrationCoefficients() != HAL_OK) Error_Handler();
// 4. EEPROM→RAM 복사 및 RAM→EEPROM 백업 (Copy EEPROM to RAM and backup RAM to EEPROM)
printf("EEPROM에서 RAM으로 복사 (Copying EEPROM to RAM)\n");
if (ZSC31050_CopyEEPROMtoRAM() != HAL_OK) Error_Handler();
printf("RAM에서 EEPROM으로 백업 (Backing up RAM to EEPROM)\n");
if (ZSC31050_CopyRAMtoEEPROM() != HAL_OK) Error_Handler();
// 5. RAM 기반 NOM 시작 및 주기적 측정 (Start RAM-based NOM and perform periodic measurements)
printf("RAM 기반 NOM 시작 (Starting NOM with RAM)\n");
if (ZSC31050_StartNOM_RAM() != HAL_OK) Error_Handler();
printf("주기적 측정 시작 (Starting periodic measurements)\n");
ZSC31050_PeriodicMeasurement();
while (1) {
// 메인 루프 (Main loop)
}
}
상세한 내용은 데이터시티와 메뉴얼을 참조하기 바랍니다.
'아날로그회로(Analog Circuit) > ADC관련' 카테고리의 다른 글
[ZSSC3230] 보정 절차 및 Calibration Math 분석 (0) | 2025.08.15 |
---|---|
[ZSSC3230] 센서 신호 컨디셔너(SSC) STM32을 사용한 I2C 코드 구현 (0) | 2025.08.15 |
[ZSSC3230] 원시 센서(Raw Sensor) 측정 설정 절차 (0) | 2025.08.15 |
[ZSSC3230] 전체 측정 전 NVM 설정 절차 (0) | 2025.08.15 |
[ZSSC3230]정전용량 센서 신호 컨디셔너 요약 (0) | 2025.08.14 |
[AD2S1210] Resolver-to-Digital Converter with STM32G474 SPI Driver (0) | 2025.08.14 |
[AD7747]정전용량-디지털 변환기 디바이스 드라이버 코드를 STM32용으로 구현 (Guide to implementing AD7747 Capacitance-to-Digital Converter driver for STM32 microcontroller) (0) | 2025.08.14 |
[ZSSC3123]Command List and Encodings 상세 분석 (0) | 2025.08.13 |