본 문서는 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. 원시 센서 데이터(Raw Data) 측정
원시 센서 데이터 측정은 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. Normal Operation 전 최종 설정
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. 주기적(Cyclic) 측정 수행
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 출력: 원시 및 보정 데이터 출력으로 디버깅 용이성 제공.
구현 코드
#ifndef ZSC31050_H
#define ZSC31050_H
#include "stm32l4xx_hal.h"
#include <stdio.h>
// 클럭 주파수 선택을 위한 열거형 정의 (Enumeration for selecting clock frequency)
typedef enum {
FCLK_1MHZ = 1, // 1MHz 클럭 주파수 (1MHz clock frequency)
FCLK_2MHZ = 2, // 2MHz 클럭 주파수 (2MHz clock frequency)
FCLK_4MHZ = 4 // 4MHz 클럭 주파수 (4MHz clock frequency)
} ZSC31050_Clock_t;
// I2C 핸들러 및 클럭 설정 변수 선언 (Declaration of I2C handler and clock configuration)
extern I2C_HandleTypeDef hi2c1; // I2C1 인터페이스 핸들러 (I2C1 interface handler)
extern ZSC31050_Clock_t fCLK; // ZSC31050의 동작 클럭 주파수 (Operational clock frequency for ZSC31050)
#define MAX_I2C_RETRIES 3 // I2C 통신 재시도 최대 횟수 (Maximum number of I2C retry attempts)
// ZSC31050 명령어 정의 (Command definitions for ZSC31050)
#define ZSC31050_ADDR 0x78 << 1 // 7비트 I2C 주소 0x78을 8비트로 변환 (7-bit I2C address 0x78 shifted to 8-bit)
#define CMD_START_CM 0x72 // Command Mode 진입 명령 (Command to enter Command Mode)
#define CMD_START_CYC_EEP 0x01 // EEPROM 기반 NOM(Normal Operation Mode) 시작 명령 (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 code)
#define RAM_PARITY_ERROR 0xCF0F // RAM 패리티 오류 코드 (RAM parity error code)
#define ADC_ERROR 0xCCCC // ADC 오류 코드 (ADC error code)
// 타이밍 상수 정의 (Timing constants)
#define BASE_READ_TIME 50 // 기본 읽기 시간 (µs, 2MHz 기준) (Base read time in µs at 2MHz)
#define BASE_WRITE_TIME 12500 // 기본 쓰기 시간 (µs) (Base write time in µs)
#define BASE_SIGN_TIME 150 // 서명 생성/확인 시간 (µs) (Signature generation/verification time)
#define BASE_CYC_EEP_TIME 350 // EEPROM 기반 NOM 시작 시간 (µs) (Time to start NOM with EEPROM)
#define BASE_CYC_RAM_TIME 220 // RAM 기반 NOM 시작 시간 (µs) (Time to start NOM with RAM)
#define BASE_COPY_EEP2RAM 130 // EEPROM→RAM 복사 시간 (µs) (EEPROM to RAM copy time)
#define BASE_COPY_RAM2EEP 400000 // RAM→EEPROM 복사 시간 (µs) (RAM to EEPROM copy time)
// 함수 프로토타입 선언 (Function prototypes)
void I2C1_Init(void); // I2C1 인터페이스 초기화 함수 (Initialize I2C1 interface)
void Error_Handler(void); // 오류 처리 함수 (Error handling function)
HAL_StatusTypeDef ZSC31050_I2C_Transmit(uint8_t *data, uint16_t size); // I2C 데이터 전송 함수 (I2C transmit function)
HAL_StatusTypeDef ZSC31050_I2C_Receive(uint8_t *data, uint16_t size); // I2C 데이터 수신 함수 (I2C receive function)
HAL_StatusTypeDef ZSC31050_SetClockDynamic(void); // 동적 클럭 설정 함수 (Dynamic clock setting function)
HAL_StatusTypeDef ZSC31050_EnterCommandMode(void); // Command Mode 진입 함수 (Enter Command Mode function)
HAL_StatusTypeDef ZSC31050_ReadEEPROM_Single(uint8_t addr, uint16_t *data); // 단일 EEPROM 주소 읽기 함수 (Read single EEPROM address)
HAL_StatusTypeDef ZSC31050_WriteEEPROM_Single(uint8_t addr, uint16_t data); // 단일 EEPROM 주소 쓰기 함수 (Write single EEPROM address)
HAL_StatusTypeDef ZSC31050_WriteEEPROM(uint8_t start_addr, uint16_t *data, uint8_t count); // 연속 EEPROM 주소 쓰기 함수 (Write multiple EEPROM addresses)
HAL_StatusTypeDef ZSC31050_ConfigureEEPROM(void); // EEPROM 구성 설정 함수 (Configure EEPROM for NOM)
HAL_StatusTypeDef ZSC31050_WriteCalibrationCoefficients(void); // 보정 계수 쓰기 함수 (Write calibration coefficients)
HAL_StatusTypeDef ZSC31050_ReadRawData(uint8_t cmd, uint16_t *data); // 원시 데이터 읽기 함수 (Read raw or corrected data)
HAL_StatusTypeDef ZSC31050_GenerateAndVerifySignature(uint16_t *signature); // EEPROM 서명 생성 및 검증 함수 (Generate and verify EEPROM signature)
HAL_StatusTypeDef ZSC31050_CopyEEPROMtoRAM(void); // EEPROM→RAM 복사 함수 (Copy EEPROM to RAM)
HAL_StatusTypeDef ZSC31050_CopyRAMtoEEPROM(void); // RAM→EEPROM 복사 함수 (Copy RAM to EEPROM)
HAL_StatusTypeDef ZSC31050_StartNOM_RAM(void); // RAM 기반 NOM 시작 함수 (Start NOM with RAM)
void ZSC31050_PeriodicMeasurement(void); // 주기적 측정 수행 함수 (Perform periodic measurements)
#endif // ZSC31050_H
#include "zsc31050.h"
// I2C 핸들러 및 클럭 설정 전역 변수 정의 (Global variables for I2C handler and clock configuration)
I2C_HandleTypeDef hi2c1; // I2C1 인터페이스 핸들러 (I2C1 interface handler)
ZSC31050_Clock_t fCLK = FCLK_2MHZ; // 기본 클럭 주파수: 2MHz (Default clock frequency: 2MHz)
// 타이밍 조정 함수 (Timing adjustment function)
// 클럭 주파수(fCLK)에 따라 기준 시간을 조정 (Adjusts base time based on fCLK)
static uint32_t AdjustTiming(uint32_t base_time) {
return (uint32_t)(base_time * (2.0f / fCLK)); // 2MHz 기준으로 시간 스케일링 (Scale time based on 2MHz)
}
// 오류 처리 함수 (Error handling function)
// I2C 또는 기타 오류 발생 시 무한 루프 실행 (Enters infinite loop on I2C or other errors)
void Error_Handler(void) {
while (1) {
// LED 또는 UART를 통해 오류 표시 가능 (Indicate error via LED or UART)
}
}
// I2C1 인터페이스 초기화 함수 (I2C1 interface initialization function)
// STM32의 I2C1 모듈을 설정 (Configures the I2C1 module of STM32)
void I2C1_Init(void) {
hi2c1.Instance = I2C1; // I2C1 모듈 선택 (Select I2C1 module)
hi2c1.Init.Timing = 0x00702991; // 80MHz에서 400kHz I2C 속도 설정 (400kHz I2C speed 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; // 두 번째 I2C 주소 사용 안 함 (No second I2C address)
hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE; // 일반 호출 모드 비활성화 (Disable general call mode)
hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE; // 클럭 스트레칭 활성화 (Enable clock stretching)
if (HAL_I2C_Init(&hi2c1) != HAL_OK) { // I2C 초기화 실행 (Perform I2C initialization)
Error_Handler(); // 초기화 실패 시 오류 처리 (Handle error on initialization failure)
}
}
// I2C MSP 초기화 함수 (I2C MSP initialization function)
// I2C1 핀(PB6: SCL, PB7: SDA) 및 클럭 설정 (Configures I2C1 pins and clock)
void HAL_I2C_MspInit(I2C_HandleTypeDef* hi2c) {
GPIO_InitTypeDef GPIO_InitStruct = {0}; // GPIO 설정 구조체 초기화 (Initialize GPIO configuration structure)
if (hi2c->Instance == I2C1) { // I2C1 모듈 확인 (Check for I2C1 module)
__HAL_RCC_GPIOB_CLK_ENABLE(); // GPIOB 클럭 활성화 (Enable GPIOB clock)
GPIO_InitStruct.Pin = GPIO_PIN_6 | GPIO_PIN_7; // PB6(SCL), PB7(SDA) 핀 선택 (Select PB6 for SCL, PB7 for SDA)
GPIO_InitStruct.Mode = GPIO_MODE_AF_OD; // 오픈 드레인 모드 설정 (Set open-drain mode)
GPIO_InitStruct.Pull = GPIO_PULLUP; // 풀업 저항 활성화 (Enable pull-up resistor)
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; // 고속 전송 설정 (Set high-speed transmission)
GPIO_InitStruct.Alternate = GPIO_AF4_I2C1; // I2C1 대체 기능 설정 (Set alternate function for I2C1)
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); // GPIO 초기화 실행 (Perform GPIO initialization)
__HAL_RCC_I2C1_CLK_ENABLE(); // I2C1 클럭 활성화 (Enable I2C1 clock)
}
}
// I2C 데이터 전송 함수 (I2C transmit function)
// ZSC31050에 데이터 전송, 최대 MAX_I2C_RETRIES번 재시도 (Transmits data to ZSC31050 with retry logic)
HAL_StatusTypeDef ZSC31050_I2C_Transmit(uint8_t *data, uint16_t size) {
uint8_t retries = 0; // 재시도 횟수 초기화 (Initialize retry counter)
HAL_StatusTypeDef status; // I2C 전송 상태 (I2C transmission status)
while (retries < MAX_I2C_RETRIES) { // 최대 재시도 횟수까지 반복 (Loop until max retries)
status = HAL_I2C_Master_Transmit(&hi2c1, ZSC31050_ADDR, data, size, HAL_MAX_DELAY); // 데이터 전송 시도 (Attempt data transmission)
if (status == HAL_OK) return HAL_OK; // 전송 성공 시 반환 (Return on successful transmission)
HAL_Delay(1); // 재시도 전 1ms 대기 (Wait 1ms before retry)
retries++; // 재시도 횟수 증가 (Increment retry counter)
}
return status; // 최종 상태 반환 (Return final status)
}
// I2C 데이터 수신 함수 (I2C receive function)
// ZSC31050으로부터 데이터 수신, 최대 MAX_I2C_RETRIES번 재시도 (Receives data from ZSC31050 with retry logic)
HAL_StatusTypeDef ZSC31050_I2C_Receive(uint8_t *data, uint16_t size) {
uint8_t retries = 0; // 재시도 횟수 초기화 (Initialize retry counter)
HAL_StatusTypeDef status; // I2C 수신 상태 (I2C reception status)
while (retries < MAX_I2C_RETRIES) { // 최대 재시도 횟수까지 반복 (Loop until max retries)
status = HAL_I2C_Master_Receive(&hi2c1, ZSC31050_ADDR | 0x01, data, size, HAL_MAX_DELAY); // 데이터 수신 시도 (Attempt data reception)
if (status == HAL_OK) return HAL_OK; // 수신 성공 시 반환 (Return on successful reception)
HAL_Delay(1); // 재시도 전 1ms 대기 (Wait 1ms before retry)
retries++; // 재시도 횟수 증가 (Increment retry counter)
}
return status; // 최종 상태 반환 (Return final status)
}
// 동적 클럭 설정 함수 (Dynamic clock setting function)
// CFGAPP:OSCF 레지스터에서 클럭 주파수 설정 (Sets clock frequency based on CFGAPP:OSCF register)
HAL_StatusTypeDef ZSC31050_SetClockDynamic(void) {
uint16_t cfgapp; // CFGAPP 레지스터 데이터 (CFGAPP register data)
HAL_StatusTypeDef status = ZSC31050_ReadEEPROM_Single(0x18, &cfgapp); // CFGAPP(0x98) 읽기 (Read CFGAPP at address 0x98)
if (status != HAL_OK) return status; // 읽기 실패 시 오류 반환 (Return error on read failure)
uint8_t oscf = (cfgapp >> 5) & 0x03; // OSCF 비트 추출 (Extract OSCF bits)
switch (oscf) { // OSCF 값에 따라 클럭 설정 (Set clock based on OSCF value)
case 0: fCLK = FCLK_1MHZ; break; // OSCF=0: 1MHz 설정 (Set 1MHz)
case 1: fCLK = FCLK_2MHZ; break; // OSCF=1: 2MHz 설정 (Set 2MHz)
case 2: fCLK = FCLK_2MHZ; break; // OSCF=2: 2MHz 설정 (Set 2MHz)
case 3: fCLK = FCLK_4MHZ; break; // OSCF=3: 4MHz 설정 (Set 4MHz)
default: fCLK = FCLK_2MHZ; // 기본값: 2MHz (Default: 2MHz)
}
printf("동적 클럭 설정: %d MHz\n", fCLK); // 설정된 클럭 출력 (Print configured clock)
return HAL_OK; // 성공 반환 (Return success)
}
// Command Mode 진입 함수 (Enter Command Mode function)
// CMD_START_CM(0x72) 명령으로 ZSC31050을 Command Mode로 전환 (Switches ZSC31050 to Command Mode using CMD_START_CM)
HAL_StatusTypeDef ZSC31050_EnterCommandMode(void) {
uint8_t cmd = CMD_START_CM; // Command Mode 진입 명령 (Command Mode entry command)
HAL_StatusTypeDef status = ZSC31050_I2C_Transmit(&cmd, 1); // 명령 전송 (Send command)
if (status == HAL_OK) { // 전송 성공 시 (On successful transmission)
HAL_Delay(AdjustTiming(BASE_READ_TIME) / 1000 + 1); // 읽기 시간 대기 (Wait for read time)
}
return status; // 상태 반환 (Return status)
}
// 단일 EEPROM 주소 읽기 함수 (Read single EEPROM address function)
// 지정된 EEPROM 주소(0x00~0x1F)에서 16비트 데이터 읽기 (Reads 16-bit data from specified EEPROM address)
HAL_StatusTypeDef ZSC31050_ReadEEPROM_Single(uint8_t addr, uint16_t *data) {
if (addr > 0x1F) return HAL_ERROR; // 주소 범위 확인 (Check address range)
uint8_t cmd = (addr < 0x10) ? (CMD_READ_EEP0 + addr) : (CMD_READ_EEP1 + (addr - 0x10)); // 적절한 읽기 명령 선택 (Select appropriate read command)
HAL_StatusTypeDef status = ZSC31050_I2C_Transmit(&cmd, 1); // 읽기 명령 전송 (Send read command)
if (status != HAL_OK) return status; // 전송 실패 시 오류 반환 (Return error on transmission failure)
HAL_Delay(AdjustTiming(BASE_READ_TIME) / 1000 + 1); // 읽기 시간 대기 (Wait for read time)
uint8_t buffer[2]; // 수신 데이터 버퍼 (Receive data buffer)
status = ZSC31050_I2C_Receive(buffer, 2); // 2바이트 데이터 수신 (Receive 2-byte data)
if (status == HAL_OK) { // 수신 성공 시 (On successful reception)
*data = (buffer[0] << 8) | buffer[1]; // 16비트 데이터로 변환 (Convert to 16-bit data)
}
return status; // 상태 반환 (Return status)
}
// 단일 EEPROM 주소 쓰기 함수 (Write single EEPROM address function)
// 지정된 EEPROM 주소(0x00~0x1F)에 16비트 데이터 쓰기 (Writes 16-bit data to specified EEPROM address)
HAL_StatusTypeDef ZSC31050_WriteEEPROM_Single(uint8_t addr, uint16_t data) {
if (addr > 0x1F) return HAL_ERROR; // 주소 범위 확인 (Check address range)
uint8_t cmd = (addr < 0x10) ? (CMD_WRITE_EEP0 + addr) : (CMD_WRITE_EEP1 + (addr - 0x10)); // 적절한 쓰기 명령 선택 (Select appropriate write command)
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) { // 전송 성공 시 (On successful transmission)
HAL_Delay(AdjustTiming(BASE_WRITE_TIME) / 1000 + 1); // 쓰기 시간 대기 (Wait for write time)
}
return status; // 상태 반환 (Return status)
}
// 연속 EEPROM 주소 쓰기 함수 (Write multiple EEPROM addresses function)
// 연속된 EEPROM 주소에 다수의 16비트 데이터 쓰기 (Writes multiple 16-bit data to consecutive EEPROM addresses)
HAL_StatusTypeDef ZSC31050_WriteEEPROM(uint8_t start_addr, uint16_t *data, uint8_t count) {
if (start_addr + count > 0x20) return HAL_ERROR; // 주소 범위 확인 (Check address range)
HAL_StatusTypeDef status = HAL_OK; // 상태 초기화 (Initialize status)
for (uint8_t i = 0; i < count; i++) { // 각 주소에 대해 반복 (Iterate over each address)
status = ZSC31050_WriteEEPROM_Single(start_addr + i, data[i]); // 단일 주소 쓰기 (Write single address)
if (status != HAL_OK) break; // 쓰기 실패 시 중단 (Break on write failure)
}
if (status == HAL_OK) { // 모든 쓰기 성공 시 (If all writes succeed)
uint16_t signature; // 서명 변수 (Signature variable)
status = ZSC31050_GenerateAndVerifySignature(&signature); // 서명 생성 및 검증 (Generate and verify signature)
}
return status; // 상태 반환 (Return status)
}
// EEPROM 구성 설정 함수 (Configure EEPROM for NOM function)
// NOM(Normal Operation Mode)을 위한 EEPROM 설정 워드 쓰기 (Writes EEPROM configuration words for NOM)
HAL_StatusTypeDef ZSC31050_ConfigureEEPROM(void) {
// NOM 설정을 위한 7개의 구성 워드 배열 (Array of 7 configuration words for NOM)
uint16_t config_data[7] = {
0x0048, // CFGCYC(0x96): 측정 주기 설정 (Measurement cycle configuration)
// 비트 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): 디지털 직렬 인터페이스 설정 (Digital serial interface configuration)
// 비트 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): 타겟 애플리케이션 설정 (Target application configuration)
// 비트 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, ADC input range)
// 비트 11:10=01 (IN3M, IN3 참조=VDDA/2, IN3 reference=VDDA/2)
// 비트 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)
// 비트 9=0 (XZC, 확장 제로 보상 부호=음수, Extended zero compensation sign=negative)
// 비트 8:4=00000 (XZC, 확장 제로 보상 값=0, Extended zero compensation value=0)
// 비트 3:0=0000 (aIN_p, 측정값 아날로그 프론트엔드 게인=420, Measurand analog front-end gain=420)
0x0124, // CFGTMP(0x9A): 온도 측정 설정 (Temperature measurement configuration)
// 비트 15:14=00 (GAINT2, 온도 2 아날로그 프론트엔드 게인=GT4 ≈ 5.65)
// 비트 13:12=00 (GAINT1, 온도 1 아날로그 프론트엔드 게인=GT4 ≈ 5.65)
// 비트 11=0 (PETS2, 온도 2 외부 센서 극성=VSS, Temperature 2 external sensor polarity=VSS)
// 비트 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): 신호 출력 설정 (Signal output configuration)
// 비트 15:14=10 (PWMRES, PWM 출력 해상도=11비트, PWM output resolution=11 bits)
// 비트 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): 내부 참조 조정 (Internal reference adjustment)
// 비트 15:13=100 (CSB, 센서 브릿지 전류 조정=1배, Sensor bridge current adjustment=1x)
// 비트 12:10=100 (VDCA, 아날로그 공급 전압 미세 조정=0%VDDA, Fine adjustment of analog supply voltage=0%VDDA)
// 비트 9:7=100 (OSCA, 오실레이터 주파수 미세 조정=fCLK_NOM, Oscillator frequency fine adjustment=fCLK_NOM)
// 비트 6:4=010 (BCUR, 바이어스 전류 조정=기본값, Bias current adjustment=default)
// 비트 3:0=1000 (VREF, 내부 밴드갭 전압 온도 특성 조정, TC adjustment of internal bandgap voltage)
};
HAL_StatusTypeDef status = ZSC31050_EnterCommandMode(); // Command Mode 진입 (Enter Command Mode)
if (status != HAL_OK) return status; // 실패 시 오류 반환 (Return error on failure)
status = ZSC31050_WriteEEPROM(0x16, config_data, 7); // 주소 0x96~0x9C에 구성 데이터 쓰기 (Write configuration data to 0x96~0x9C)
if (status == HAL_OK) { // 쓰기 성공 시 (On successful write)
uint16_t signature; // 서명 변수 (Signature variable)
status = ZSC31050_GenerateAndVerifySignature(&signature); // 서명 생성 및 검증 (Generate and verify signature)
}
return status; // 상태 반환 (Return status)
}
// 보정 계수 쓰기 함수 (Write calibration coefficients function)
// 보정 계수 및 출력 제한 계수를 EEPROM 주소 0x80~0x95에 쓰기 (Writes calibration and output limit coefficients to EEPROM 0x80~0x95)
HAL_StatusTypeDef ZSC31050_WriteCalibrationCoefficients(void) {
// 보정 계수 및 출력 제한 계수 배열 (Array of calibration and output limit coefficients)
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 error on failure)
return ZSC31050_WriteEEPROM(0x10, calib_data, 22); // 주소 0x80~0x95에 보정 데이터 쓰기 (Write calibration data to 0x80~0x95)
}
// 원시 데이터 읽기 함수 (Read raw or corrected data function)
// 지정된 명령으로 원시 또는 보정된 데이터(Z_ADC, Z_CORR) 읽기 (Reads raw or corrected data using specified command)
HAL_StatusTypeDef ZSC31050_ReadRawData(uint8_t cmd, uint16_t *data) {
HAL_StatusTypeDef status = ZSC31050_I2C_Transmit(&cmd, 1); // 명령 전송 (Send command)
if (status != HAL_OK) return status; // 전송 실패 시 오류 반환 (Return error on transmission failure)
HAL_Delay(AdjustTiming(BASE_READ_TIME) / 1000 + 1); // 읽기 시간 대기 (Wait for read time)
uint8_t buffer[2]; // 수신 데이터 버퍼 (Receive data buffer)
status = ZSC31050_I2C_Receive(buffer, 2); // 2바이트 데이터 수신 (Receive 2-byte data)
if (status == HAL_OK) { // 수신 성공 시 (On successful reception)
*data = (buffer[0] << 8) | buffer[1]; // 16비트 데이터로 변환 (Convert to 16-bit data)
if (*data == EEPROM_SIGN_ERROR || *data == RAM_PARITY_ERROR || *data == ADC_ERROR) { // 오류 코드 확인 (Check for error codes)
return HAL_ERROR; // 오류 발생 시 반환 (Return error)
}
}
return status; // 상태 반환 (Return status)
}
// EEPROM 서명 생성 및 검증 함수 (Generate and verify EEPROM signature function)
// EEPROM 데이터의 무결성을 확인하기 위해 서명 생성 및 검증 (Generates and verifies signature to ensure EEPROM data integrity)
HAL_StatusTypeDef ZSC31050_GenerateAndVerifySignature(uint16_t *signature) {
uint8_t cmd = CMD_GEN_EEP_SIGN; // 서명 생성 명령 (Signature generation command)
HAL_StatusTypeDef status = ZSC31050_I2C_Transmit(&cmd, 1); // 서명 생성 명령 전송 (Send signature generation command)
if (status != HAL_OK) return status; // 전송 실패 시 오류 반환 (Return error on transmission failure)
HAL_Delay(AdjustTiming(BASE_SIGN_TIME) / 1000 + 1); // 서명 생성 시간 대기 (Wait for signature generation time)
cmd = CMD_GET_EEP_SIGN; // 서명 읽기 명령 (Signature read command)
status = ZSC31050_I2C_Transmit(&cmd, 1); // 서명 읽기 명령 전송 (Send signature read command)
if (status != HAL_OK) return status; // 전송 실패 시 오류 반환 (Return error on transmission failure)
HAL_Delay(AdjustTiming(BASE_READ_TIME) / 1000 + 1); // 읽기 시간 대기 (Wait for read time)
uint8_t buffer[2]; // 수신 데이터 버퍼 (Receive data buffer)
status = ZSC31050_I2C_Receive(buffer, 2); // 서명 데이터 수신 (Receive signature data)
if (status == HAL_OK) { // 수신 성공 시 (On successful reception)
*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; // 상태 반환 (Return status)
}
// EEPROM→RAM 복사 함수 (Copy EEPROM to RAM function)
// EEPROM 데이터를 RAM으로 복사 (Copies EEPROM data to RAM)
HAL_StatusTypeDef ZSC31050_CopyEEPROMtoRAM(void) {
uint8_t cmd = CMD_COPY_EEP2RAM; // EEPROM→RAM 복사 명령 (EEPROM to RAM copy command)
HAL_StatusTypeDef status = ZSC31050_I2C_Transmit(&cmd, 1); // 명령 전송 (Send command)
if (status == HAL_OK) { // 전송 성공 시 (On successful transmission)
HAL_Delay(AdjustTiming(BASE_COPY_EEP2RAM) / 1000 + 1); // 복사 시간 대기 (Wait for copy time)
}
return status; // 상태 반환 (Return status)
}
// RAM→EEPROM 복사 함수 (Copy RAM to EEPROM function)
// RAM 데이터를 EEPROM으로 복사 및 서명 검증 (Copies RAM data to EEPROM and verifies signature)
HAL_StatusTypeDef ZSC31050_CopyRAMtoEEPROM(void) {
uint8_t cmd = CMD_COPY_RAM2EEP; // RAM→EEPROM 복사 명령 (RAM to EEPROM copy command)
HAL_StatusTypeDef status = ZSC31050_I2C_Transmit(&cmd, 1); // 명령 전송 (Send command)
if (status == HAL_OK) { // 전송 성공 시 (On successful transmission)
HAL_Delay(AdjustTiming(BASE_COPY_RAM2EEP) / 1000 + 1); // 복사 시간 대기 (Wait for copy time)
uint16_t signature; // 서명 변수 (Signature variable)
status = ZSC31050_GenerateAndVerifySignature(&signature); // 서명 생성 및 검증 (Generate and verify signature)
}
return status; // 상태 반환 (Return status)
}
// RAM 기반 NOM 시작 함수 (Start NOM with RAM function)
// CMD_START_CYC_RAM(0x02) 명령으로 RAM 기반 NOM 시작 (Starts NOM with RAM using CMD_START_CYC_RAM)
HAL_StatusTypeDef ZSC31050_StartNOM_RAM(void) {
uint8_t cmd = CMD_START_CYC_RAM; // RAM 기반 NOM 시작 명령 (RAM-based NOM start command)
HAL_StatusTypeDef status = ZSC31050_I2C_Transmit(&cmd, 1); // 명령 전송 (Send command)
if (status == HAL_OK) { // 전송 성공 시 (On successful transmission)
HAL_Delay(AdjustTiming(BASE_CYC_RAM_TIME) / 1000 + 1); // NOM 시작 시간 대기 (Wait for NOM start time)
printf("NOM이 RAM 기반으로 시작됨\n"); // NOM 시작 메시지 출력 (Print NOM start message)
}
return status; // 상태 반환 (Return status)
}
// 주기적 측정 수행 함수 (Perform periodic measurements function)
// 압력 및 온도 데이터를 주기적으로 읽고 출력 (Periodically reads and prints pressure and temperature data)
void ZSC31050_PeriodicMeasurement(void) {
uint16_t z_corr_p, z_corr_t1, z_corr_t2; // 보정된 데이터 변수 (Corrected data variables)
while (1) { // 무한 루프 (Infinite loop)
if (ZSC31050_ReadRawData(CMD_READ_ZCORR_P, &z_corr_p) != HAL_OK) Error_Handler(); // 보정된 압력 데이터 읽기 (Read corrected pressure data)
if (ZSC31050_ReadRawData(CMD_READ_ZCORR_T1, &z_corr_t1) != HAL_OK) Error_Handler(); // 보정된 온도1 데이터 읽기 (Read corrected temperature1 data)
if (ZSC31050_ReadRawData(CMD_READ_ZCORR_T2, &z_corr_t2) != HAL_OK) Error_Handler(); // 보정된 온도2 데이터 읽기 (Read corrected temperature2 data)
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); // 데이터 출력 (Print data)
HAL_Delay(100); // 100ms 주기로 측정 (Measure every 100ms)
}
}
#include "zsc31050.h"
// 메인 함수 (Main function)
// ZSC31050 센서를 초기화하고 주기적 측정을 수행
int main(void) {
// 시스템 및 HAL 초기화
HAL_Init(); // STM32 HAL 라이브러리 초기화
// 시스템 클럭 설정 (예: 80MHz, 실제 구현 필요)
I2C1_Init(); // I2C1 인터페이스 초기화
// 변수 선언
uint16_t z_adc_p, z_adc_t1, z_adc_t2; // 원시 데이터 변수
// 1. 동적 클럭 설정 및 EEPROM 구성
printf("CFGAPP:OSCF에서 동적 클럭 설정\n"); // 동적 클럭 설정 시작 메시지
if (ZSC31050_SetClockDynamic() != HAL_OK) Error_Handler(); // CFGAPP:OSCF에서 클럭 주파수 설정
printf("NOM을 위한 EEPROM 구성 설정\n"); // EEPROM 구성 시작 메시지
if (ZSC31050_ConfigureEEPROM() != HAL_OK) Error_Handler(); // NOM을 위한 EEPROM 설정
// 2. Command Mode 진입 및 원시 데이터 읽기
printf("Command Mode 진입\n"); // Command Mode 진입 메시지
if (ZSC31050_EnterCommandMode() != HAL_OK) Error_Handler(); // Command Mode로 전환
printf("RAM 기반 NOM 시작 후 원시 데이터 읽기\n"); // 원시 데이터 읽기 시작 메시지
if (ZSC31050_StartNOM_RAM() != HAL_OK) Error_Handler(); // RAM 기반 NOM 시작
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(); // 온도1 원시 데이터 읽기
if (ZSC31050_ReadRawData(CMD_READ_ZADC_T2, &z_adc_t2) != HAL_OK) Error_Handler(); // 온도2 원시 데이터 읽기
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에 쓰기
printf("Command Mode 진입 후 보정 및 출력 제한 계수 쓰기\n"); // 보정 계수 쓰기 시작 메시지
if (ZSC31050_WriteCalibrationCoefficients() != HAL_OK) Error_Handler(); // 보정 계수 쓰기
// 4. EEPROM→RAM 복사 및 RAM→EEPROM 백업
printf("EEPROM에서 RAM으로 복사\n"); // EEPROM→RAM 복사 시작 메시지
if (ZSC31050_CopyEEPROMtoRAM() != HAL_OK) Error_Handler(); // EEPROM 데이터를 RAM으로 복사
printf("RAM에서 EEPROM으로 백업\n"); // RAM→EEPROM 백업 시작 메시지
if (ZSC31050_CopyRAMtoEEPROM() != HAL_OK) Error_Handler(); // RAM 데이터를 EEPROM으로 백업
// 5. RAM 기반 NOM 시작 및 주기적 측정
printf("RAM 기반 NOM 시작\n"); // NOM 시작 메시지
if (ZSC31050_StartNOM_RAM() != HAL_OK) Error_Handler(); // RAM 기반 NOM 시작
printf("주기적 측정 시작\n"); // 주기적 측정 시작 메시지
ZSC31050_PeriodicMeasurement(); // 주기적 측정 수행
while (1) { // 메인 루프
// 추가 작업이 필요하면 여기에 구현
}
}
상세한 내용은 데이터시티와 메뉴얼을 참조하기 바랍니다.
'아날로그회로(Analog Circuit) > ADC관련' 카테고리의 다른 글
ZSC31015 Sensor Signal Conditioner IC 드라이버 구현: STM32를 활용한 Zacwire 인터페이싱 (4) | 2025.08.25 |
---|---|
ADS114S08 16비트 ADC STM32 HAL 기반 디바이스 드라이버 구현 (0) | 2025.08.24 |
PT100/PT1000 RTD 센서용 MAX31865 온도 변환 IC STM32 디바이스 드라이버 구현 (3) | 2025.08.24 |
PGA302 Sensor Signal Conditioner IC STM32용 I2C 드라이버 구현 (0) | 2025.08.20 |
ZSSC3230 Sensor Signal Conditioner IC 보정 절차 및 Calibration Math 분석 (1) | 2025.08.15 |
ZSSC3230 Sensor Signal Conditioner IC STM32을 사용한 I2C 코드 구현 (0) | 2025.08.15 |
ZSSC3230 Sensor Signal Conditioner IC 센서 Raw Data 측정 설정 절차 및 I2C 코드 (0) | 2025.08.15 |
ZSSC3230 Sensor Signal Conditioner IC 전체 측정(Measure) 절차 및 I2C 코드 (0) | 2025.08.15 |