이문서는 Renesas의 ZSSC3241 센서 신호 컨디셔너 IC에 대해 깊이 파고들어 보겠습니다. 이 IC는 저항성 센서(브리지, 하프 브리지, Pt100, NTC/PTC 등)의 신호를 증폭, 디지털화, 보정하는 데 특화된 제품으로, 산업 자동화, 압력/유량 센싱, 의료 기기 등 다양한 응용 분야에서 활용됩니다. 최근에 ZSSC3241 데이터시트(REN_zssc3241-datasheet_DST_20240202.pdf)를 분석하며 STM32L432KC 마이크로컨트롤러와 I2C 인터페이스를 이용한 구현 코드입니다.
이 글은 데이터시트의 주요 기능을 바탕으로 한 분석과, 모든 기능을 포괄하는 I2C 코드 구현을 중심으로 구성했습니다. 데이터시트를 다시 확인하여 내용의 완전성을 보강하였으며, 코드에 상세한 주석을 추가했습니다. 초보자도 따라할 수 있도록 단계별로 설명하겠습니다. 코드 예시는 STM32 HAL 라이브러리를 사용하며, 실제 프로젝트에 적용할 수 있도록 세심하게 작성했습니다.
ZSSC3241 IC 개요와 데이터시트 분석
ZSSC3241은 센서 신호를 고정밀도로 처리하는 IC로, 주요 기능은 다음과 같습니다:
- 아날로그 프론트엔드 (AFE): 프로그래머블 게인 증폭기(PGA), ADC(12~24비트 해상도), 온도 센서(내부/외부)를 포함. 센서 공급 방식(비율 전압, 절대 전압, 전류 루프)을 선택할 수 있습니다. 데이터시트 섹션 6.2에서 상세히 설명되며, 센서 유형에 따라 설정이 필요합니다.
- 디지털 인터페이스: I2C, SPI, OWI 지원. I2C는 최대 3.4MHz 속도, 슬레이브 주소 기본값 0x00. 인터페이스 선택은 전원 인가 후 첫 번째 유효 신호로 결정됩니다(섹션 6.4).
- 작동 모드:
- 슬립 모드: 저전력 대기, 디지털 출력 전용.
- 명령 모드: 사용자가 명령으로 측정 실행, 테스트/캘리브레이션에 적합.
- 사이클릭 모드: 자동 주기적 측정, 연속 출력에 최적화.
- DAC 및 아날로그 출력: 13~16비트 DAC로 전압(0~1V, 0~5V, 비율) 또는 전류 루프(4~20mA) 출력. SSF2 레지스터에서 설정(섹션 6.5.3).
- 진단 기능: 센서 연결 체크, 메모리 무결성, 칩 크랙 검출 등. UPDATE_DIAG(0xB2)와 CHECK_DIAG(0xB0) 명령 사용(섹션 6.3).
- NVM (Non-Volatile Memory): 보정 계수와 설정 저장, 주소 0x00~0x35 (고객용). 잠금 기능(lock 비트) 지원(Table 35, 페이지 51).
- 기타 기능: 인터럽트(EOC 핀), 외부 LDO(5V~48V), 보정 계수 쓰기, 온칩 온도 센서, 외부 온도 센서 지원. 데이터시트 전체 기능은 섹션 6에서 상세히 설명됩니다.
이 IC는 센서 신호 보정(SSC) 수학 코어를 통해 센서 오프셋, 감도, 온도 드리프트, 비선형성을 보정합니다. 보정 계수는 다항식 형태로 NVM에 저장되며, 쓰기 전에 NVM 잠금 해제가 필수입니다.
STM32L432KC와 I2C를 이용한 구현
STM32L432KC는 저전력 MCU로, I2C1(PB6: SCL, PB7: SDA)을 사용하여 ZSSC3241과 통신할 수 있습니다. 아래 코드는 데이터시트의 모든 기능을 I2C로 구현한 것입니다.
주요 기능:
- 작동 모드 전환 (명령, 사이클릭, 슬립).
- NVM 읽기/쓰기, 잠금 해제 (RESO 핀 사용).
- 아날로그 프론트엔드 설정.
- 원시 데이터 및 SSC 보정 데이터 읽기.
- DAC 설정.
- 사이클릭 모드 스케줄 설정.
- 인터럽트 및 진단 기능.
- 외부 LDO 설정.
- 보정 계수 쓰기.
코드는 HAL 라이브러리를 사용하며, 오류 처리와 상태 확인을 포함했습니다. 실제 사용 시 STM32CubeIDE에서 프로젝트를 생성하고, 핀맵과 클럭 설정을 확인하세요
전체 코드
// ZSSC3241 데이터시트 기반 STM32L432KC I2C 구현 코드
// 모든 기능 커버: 모드 전환, NVM 읽기/쓰기, AFE 설정, 데이터 읽기, DAC, 진단, 인터럽트, 외부 LDO, 보정 계수
// 데이터시트 섹션 6 기반으로 작성, 전체 NVM 읽기, 진단 리셋 등
// 상세 주석 추가
#include "stm32l4xx_hal.h"
// ZSSC3241 기본 I2C 슬레이브 주소 (7비트) - 데이터시트 섹션 6.4.2
#define ZSSC3241_SLAVE_ADDR 0x00
// RESO 핀 설정 (예: PB8) - 데이터시트 핀 7, 리셋 및 NVM 잠금 해제 용
#define RESO_PIN GPIO_PIN_8
#define RESO_PORT GPIOB
// 데이터 유형 정의 - 센서/온도 구분
typedef enum { SENSOR, TEMPERATURE } DataType;
// 오류 처리 함수 - 실제 프로젝트에서 로그나 LED로 확장
void Error_Handler(void) {
while (1); // 무한 루프, 실제로는 디버깅 코드 추가
}
// 상태 바이트 읽기 (NOP 명령) - 데이터시트 Table 19, 섹션 6.4.1
// NOP (FxHEX)으로 상태 바이트(Busy, Mode, Memory Error 등) 확인
uint8_t get_status(I2C_HandleTypeDef *hi2c) {
uint8_t nop_cmd = 0xFF; // NOP 명령 코드
uint8_t status;
if (HAL_I2C_Master_Transmit(hi2c, ZSSC3241_SLAVE_ADDR << 1, &nop_cmd, 1, 100) != HAL_OK) {
Error_Handler();
}
if (HAL_I2C_Master_Receive(hi2c, (ZSSC3241_SLAVE_ADDR << 1) | 0x01, &status, 1, 100) != HAL_OK) {
Error_Handler();
}
return status;
}
// 장치가 바쁜지 확인 - 상태 바이트 비트 5 (Busy?) 확인
bool is_device_busy(I2C_HandleTypeDef *hi2c) {
return (get_status(hi2c) & 0x20) != 0; // Busy 비트(비트 5) 확인
}
// 명령 모드로 전환 - START_CM (0xA9) 명령, 데이터시트 섹션 6.6.1
HAL_StatusTypeDef enter_command_mode(I2C_HandleTypeDef *hi2c) {
uint8_t cmd = 0xA9; // START_CM 명령 코드
HAL_StatusTypeDef status = HAL_I2C_Master_Transmit(hi2c, ZSSC3241_SLAVE_ADDR << 1, &cmd, 1, 100);
if (status == HAL_OK) {
HAL_Delay(10); // 모드 전환 후 안정화 대기 시간 (데이터시트 권장)
}
return status;
}
// 사이클릭 모드로 전환 - START_CYC (0xAB) 명령, 데이터시트 섹션 6.6.1
HAL_StatusTypeDef enter_cyclic_mode(I2C_HandleTypeDef *hi2c) {
uint8_t cmd = 0xAB; // START_CYC 명령 코드
HAL_StatusTypeDef status = HAL_I2C_Master_Transmit(hi2c, ZSSC3241_SLAVE_ADDR << 1, &cmd, 1, 100);
if (status == HAL_OK) {
HAL_Delay(10); // 모드 전환 후 안정화 대기
}
return status;
}
// 슬립 모드로 전환 - START_SLEEP (0xA8) 명령, 데이터시트 섹션 6.6.1
HAL_StatusTypeDef enter_sleep_mode(I2C_HandleTypeDef *hi2c) {
uint8_t cmd = 0xA8; // START_SLEEP 명령 코드
HAL_StatusTypeDef status = HAL_I2C_Master_Transmit(hi2c, ZSSC3241_SLAVE_ADDR << 1, &cmd, 1, 100);
if (status == HAL_OK) {
HAL_Delay(10); // 모드 전환 후 안정화 대기
}
return status;
}
// NVM 잠금 상태 확인 - SSF1 (0x03) 레지스터 비트 14 (lock) 확인, 데이터시트 Table 35
bool is_nvm_locked(I2C_HandleTypeDef *hi2c) {
uint8_t ssf1[2];
HAL_StatusTypeDef status = HAL_I2C_Mem_Read(hi2c, ZSSC3241_SLAVE_ADDR, 0x03, I2C_MEMADD_SIZE_8BIT, ssf1, 2, 100);
if (status != HAL_OK) {
return true; // 읽기 실패 시 잠긴 것으로 가정
}
return (ssf1[0] & 0x40) != 0; // 비트 14 (lock) 확인
}
// RESO 핀으로 NVM 잠금 해제 및 리셋 - 데이터시트 핀 7 설명, 저전위로 리셋
void unlock_nvm(void) {
GPIO_InitTypeDef GPIO_InitStruct = {0};
__HAL_RCC_GPIOB_CLK_ENABLE(); // GPIO 클럭 활성화
GPIO_InitStruct.Pin = RESO_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(RESO_PORT, &GPIO_InitStruct);
// RESO 핀을 VSS(0V)로 설정하여 리셋 실행
HAL_GPIO_WritePin(RESO_PORT, RESO_PIN, GPIO_PIN_RESET);
HAL_Delay(10); // 리셋 유지 시간 (데이터시트 권장 최소 시간)
HAL_GPIO_WritePin(RESO_PORT, RESO_PIN, GPIO_PIN_SET); // 리셋 해제
HAL_Delay(10); // 안정화 대기 시간
}
// 체크섬 갱신 - Calculate NVM Checksum (0x90) 명령, 데이터시트 섹션 6.6.2
HAL_StatusTypeDef update_checksum(I2C_HandleTypeDef *hi2c) {
uint8_t cmd = 0x90; // 체크섬 갱신 명령
return HAL_I2C_Master_Transmit(hi2c, ZSSC3241_SLAVE_ADDR << 1, &cmd, 1, 100);
}
// NVM에 데이터 쓰기 (일반화된 함수) - Memory Write (0x40~0x75), 데이터시트 Table 34
HAL_StatusTypeDef write_nvm_data(I2C_HandleTypeDef *hi2c, uint8_t address, uint8_t *data, uint8_t size) {
if (is_nvm_locked(hi2c)) {
unlock_nvm(); // NVM 잠금 해제 시도
if (is_nvm_locked(hi2c)) {
return HAL_ERROR; // 여전히 잠겨 있으면 실패
}
}
enter_command_mode(hi2c); // 쓰기 전에 명령 모드로 전환
uint8_t write_addr = address + 0x40; // 쓰기 주소 = NVM 주소 + 0x40
HAL_StatusTypeDef status = HAL_I2C_Mem_Write(hi2c, ZSSC3241_SLAVE_ADDR, write_addr, I2C_MEMADD_SIZE_8BIT, data, size, 100);
if (status == HAL_OK) {
status = update_checksum(hi2c); // 쓰기 후 체크섬 갱신
}
return status;
}
// NVM 데이터 읽기 (일반화된 함수) - Memory Read (0x00~0x3F), 데이터시트 Table 34
HAL_StatusTypeDef read_nvm_data(I2C_HandleTypeDef *hi2c, uint8_t address, uint8_t *data, uint8_t size) {
enter_command_mode(hi2c); // 읽기 전에 명령 모드로 전환
return HAL_I2C_Mem_Read(hi2c, ZSSC3241_SLAVE_ADDR, address, I2C_MEMADD_SIZE_8BIT, data, size, 100);
}
// 전체 NVM 읽기 (0x00~0x35, 고객용) - 데이터시트 Table
HAL_StatusTypeDef read_all_nvm(I2C_HandleTypeDef *hi2c, uint8_t *data) {
enter_command_mode(hi2c);
for (uint8_t i = 0; i <= 0x35; i++) {
HAL_StatusTypeDef status = read_nvm_data(hi2c, i, &data[i * 2], 2);
if (status != HAL_OK) return status;
}
return HAL_OK;
}
// 전체 NVM 쓰기 (0x00~0x35)
HAL_StatusTypeDef write_all_nvm(I2C_HandleTypeDef *hi2c, uint8_t *data) {
if (is_nvm_locked(hi2c)) {
unlock_nvm();
if (is_nvm_locked(hi2c)) {
return HAL_ERROR;
}
}
enter_command_mode(hi2c);
for (uint8_t i = 0; i <= 0x35; i++) {
HAL_StatusTypeDef status = write_nvm_data(hi2c, i, &data[i * 2], 2);
if (status != HAL_OK) return status;
}
return HAL_OK;
}
// 아날로그 프론트엔드 설정 - 데이터시트 섹션 6.2, Table 5~13
HAL_StatusTypeDef configure_analog_frontend(I2C_HandleTypeDef *hi2c) {
// SSF1 설정: 센서 공급 방식(비율 전압), 온도 소스(내부), 기본 모드(명령 모드)
uint8_t ssf1[2] = {0x00, 0x00}; // sensor_sup = 00, temp_source = 000, default_mode = 00
HAL_StatusTypeDef status = write_nvm_data(hi2c, 0x03, ssf1, 2);
if (status != HAL_OK) return status;
// SM_config1 설정: Gain_stage1 = 40 V/V, ioffsc = 0, adc_bits = 16비트
uint8_t sm_config1[2] = {0x40, 0x70}; // adc_bits = 0100, ioffsc = 0000, Gain_stage1 = 0111
status = write_nvm_data(hi2c, 0x14, sm_config1, 2);
if (status != HAL_OK) return status;
// SM_config2 설정: Gain_stage2 = 1.2 V/V
uint8_t sm_config2[2] = {0x00, 0x01}; // Gain_stage2 = 001
status = write_nvm_data(hi2c, 0x15, sm_config2, 2);
if (status != HAL_OK) return status;
// extTemp_config1 설정: 외부 온도 센서 설정 (예시)
uint8_t ext_temp_config1[2] = {0x00, 0x00}; // 기본값
status = write_nvm_data(hi2c, 0x16, ext_temp_config1, 2);
if (status != HAL_OK) return status;
// extTemp_config2 설정: 외부 온도 센서 추가 설정 (예시)
uint8_t ext_temp_config2[2] = {0x00, 0x00}; // 기본값
status = write_nvm_data(hi2c, 0x17, ext_temp_config2, 2);
if (status != HAL_OK) return status;
return HAL_OK;
}
// 온칩 진단 수행 - UPDATE_DIAG (0xB2) 및 CHECK_DIAG (0xB0), 데이터시트 섹션 6.3
HAL_StatusTypeDef perform_diagnostics(I2C_HandleTypeDef *hi2c) {
uint8_t cmd = 0xB2; // UPDATE_DIAG 명령: 모든 진단 체크 수행
HAL_StatusTypeDef status = HAL_I2C_Master_Transmit(hi2c, ZSSC3241_SLAVE_ADDR << 1, &cmd, 1, 100);
if (status != HAL_OK) return status;
while (is_device_busy(hi2c)) {
HAL_Delay(10); // 진단 완료 대기
}
cmd = 0xB0; // CHECK_DIAG 명령: 진단 결과 읽기
if (HAL_I2C_Master_Transmit(hi2c, ZSSC3241_SLAVE_ADDR << 1, &cmd, 1, 100) != HAL_OK) {
return HAL_ERROR;
}
uint8_t diag_data[2];
if (HAL_I2C_Master_Receive(hi2c, (ZSSC3241_SLAVE_ADDR << 1) | 0x01, diag_data, 2, 100) != HAL_OK) {
return HAL_ERROR;
}
// diag_data 분석: 데이터시트 Table 18 참조 (예: 비트 15~0으로 오류 유형 확인)
return HAL_OK;
}
// 원시 데이터 읽기 - Raw Sensor (0xA2) / Temperature (0xA4), 데이터시트 섹션 6.5.1
int32_t read_raw_data(I2C_HandleTypeDef *hi2c, DataType type) {
enter_command_mode(hi2c); // 명령 모드 확인 및 전환
uint8_t cmd = (type == SENSOR) ? 0xA2 : 0xA4; // 명령 선택
if (HAL_I2C_Master_Transmit(hi2c, ZSSC3241_SLAVE_ADDR << 1, &cmd, 1, 100) != HAL_OK) {
Error_Handler();
}
while (is_device_busy(hi2c)) {
HAL_Delay(10); // 변환 완료 대기
}
uint8_t data[3];
if (HAL_I2C_Master_Receive(hi2c, (ZSSC3241_SLAVE_ADDR << 1) | 0x01, data, 3, 100) != HAL_OK) {
Error_Handler();
}
int32_t raw_value = (data[0] << 16) | (data[1] << 8) | data[2]; // 24비트 데이터 조합
if (raw_value & 0x800000) {
raw_value |= 0xFF000000; // 두 개의 보수 부호 확장
}
return raw_value;
}
// SSC 보정 데이터 읽기 - Measure (0xAA), 데이터시트 섹션 6.5.1
HAL_StatusTypeDef read_ssc_data(I2C_HandleTypeDef *hi2c, int32_t *sensor_data, int32_t *temp_data) {
uint8_t cmd = 0xAA; // SSC 보정 측정 명령
if (HAL_I2C_Master_Transmit(hi2c, ZSSC3241_SLAVE_ADDR << 1, &cmd, 1, 100) != HAL_OK) {
return HAL_ERROR;
}
while (is_device_busy(hi2c)) {
HAL_Delay(10); // 변환 완료 대기
}
uint8_t data[6];
if (HAL_I2C_Master_Receive(hi2c, (ZSSC3241_SLAVE_ADDR << 1) | 0x01, data, 6, 100) != HAL_OK) {
return HAL_ERROR;
}
*sensor_data = (data[0] << 16) | (data[1] << 8) | data[2]; // 센서 데이터
if (*sensor_data & 0x800000) *sensor_data |= 0xFF000000; // 부호 확장
*temp_data = (data[3] << 16) | (data[4] << 8) | data[5]; // 온도 데이터
if (*temp_data & 0x800000) *temp_data |= 0xFF000000; // 부호 확장
return HAL_OK;
}
// 사이클릭 모드에서 최신 데이터 읽기 - 데이터시트 섹션 6.5.2
HAL_StatusTypeDef read_latest_data_cyclic(I2C_HandleTypeDef *hi2c, int32_t *sensor_data, int32_t *temp_data) {
uint8_t data[6];
HAL_StatusTypeDef status = HAL_I2C_Master_Receive(hi2c, (ZSSC3241_SLAVE_ADDR << 1) | 0x01, data, 6, 100);
if (status != HAL_OK) return status;
*sensor_data = (data[0] << 16) | (data[1] << 8) | data[2]; // 센서 데이터
if (*sensor_data & 0x800000) *sensor_data |= 0xFF000000; // 부호 확장
*temp_data = (data[3] << 16) | (data[4] << 8) | data[5]; // 온도 데이터
if (*temp_data & 0x800000) *temp_data |= 0xFF000000; // 부호 확장
return HAL_OK;
}
// DAC 설정 (전압 출력 예: 0-5V) - 데이터시트 Table 29, 섹션 6.5.3
HAL_StatusTypeDef configure_dac(I2C_HandleTypeDef *hi2c) {
uint8_t ssf2[2] = {0x60, 0x00}; // Aout_setup = 011 (0~5V), dacouttype = 0 (센서 데이터)
return write_nvm_data(hi2c, 0x04, ssf2, 2);
}
// 사이클릭 모드 스케줄 설정 - 데이터시트 섹션 6.5.2, 레지스터 0x1E~0x20
HAL_StatusTypeDef configure_cyclic_scheduler(I2C_HandleTypeDef *hi2c) {
uint8_t scheduler0[2] = {0x00, 0x00}; // S (센서 측정), pause = 0
HAL_StatusTypeDef status = write_nvm_data(hi2c, 0x1E, scheduler0, 2);
if (status != HAL_OK) return status;
uint8_t scheduler1[2] = {0x00, 0x01}; // T (온도 측정), pause = 0
status = write_nvm_data(hi2c, 0x1F, scheduler1, 2);
if (status != HAL_OK) return status;
uint8_t scheduler2[2] = {0x00, 0xFF}; // 비활성화
status = write_nvm_data(hi2c, 0x20, scheduler2, 2);
if (status != HAL_OK) return status;
return HAL_OK;
}
// 인터럽트 설정 - 데이터시트 섹션 6.5.4, 레지스터 0x21
HAL_StatusTypeDef configure_interrupt(I2C_HandleTypeDef *hi2c) {
uint8_t int_data[2] = {0x00, 0x00}; // 예시: 임계값 및 히스테리시스 설정
return write_nvm_data(hi2c, 0x21, int_data, 2);
}
// 진단 리셋 - RESET_DIAG (0xB1), 데이터시트 섹션 6.3
HAL_StatusTypeDef reset_diagnostics(I2C_HandleTypeDef *hi2c) {
uint8_t cmd = 0xB1; // RESET_DIAG 명령
return HAL_I2C_Master_Transmit(hi2c, ZSSC3241_SLAVE_ADDR << 1, &cmd, 1, 100);
}
// 외부 LDO 설정 (5V~48V) - 데이터시트 섹션 6.7, 레지스터 0x22
HAL_StatusTypeDef configure_external_ldo(I2C_HandleTypeDef *hi2c) {
uint8_t ldo_data[2] = {0x00, 0x00}; // 예시: VDD_ldoctrl_target 설정
return write_nvm_data(hi2c, 0x22, ldo_data, 2);
}
// 모든 기능 통합 설정 - 데이터시트 전체 기능 커버
HAL_StatusTypeDef configure_all(I2C_HandleTypeDef *hi2c) {
HAL_StatusTypeDef status = configure_analog_frontend(hi2c);
if (status != HAL_OK) return status;
status = configure_calibration_coefficients(hi2c);
if (status != HAL_OK) return status;
status = configure_dac(hi2c);
if (status != HAL_OK) return status;
status = configure_cyclic_scheduler(hi2c);
if (status != HAL_OK) return status;
status = configure_interrupt(hi2c);
if (status != HAL_OK) return status;
status = configure_external_ldo(hi2c);
if (status != HAL_OK) return status;
return HAL_OK;
}
// 캘리브레이션 계수 쓰기 - 데이터시트 섹션 7, Table 36
HAL_StatusTypeDef write_calibration_coefficient(I2C_HandleTypeDef *hi2c, uint8_t address, uint16_t coefficient) {
uint8_t data[2] = {(coefficient >> 8) & 0xFF, coefficient & 0xFF};
return write_nvm_data(hi2c, address, data, 2);
}
// 보정 계수 설정 예시 - 센서/온도 계수 배열 쓰기
HAL_StatusTypeDef configure_calibration_coefficients(I2C_HandleTypeDef *hi2c) {
// 센서 보정 계수 (예시 값, 실제 캘리브레이션 데이터로 대체)
uint16_t sensor_coeffs[8] = {0x1000, 0x2000, 0x3000, 0x4000, 0x5000, 0x6000, 0x7000, 0x8000};
for (uint8_t i = 0; i < 8; i++) {
HAL_StatusTypeDef status = write_calibration_coefficient(hi2c, 0x06 + i, sensor_coeffs[i]);
if (status != HAL_OK) return status;
}
// 온도 보정 계수 (예시 값, 실제 캘리브레이션 데이터로 대체)
uint16_t temp_coeffs[6] = {0x9000, 0xA000, 0xB000, 0xC000, 0xD000, 0xE000};
for (uint8_t i = 0; i < 6; i++) {
HAL_StatusTypeDef status = write_calibration_coefficient(hi2c, 0x18 + i, temp_coeffs[i]);
if (status != HAL_OK) return status;
}
return update_checksum(hi2c);
}
// I2C 초기화 - 데이터시트 섹션 6.4.2, STM32 HAL 기반
void I2C1_Init(void) {
I2C_HandleTypeDef *hi2c = &hi2c1;
hi2c->Instance = I2C1;
hi2c->Init.Timing = 0x00702991; // 100kHz, 시스템 클럭에 따라 조정 (데이터시트 Table 22)
hi2c->Init.OwnAddress1 = 0;
hi2c->Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
hi2c->Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
hi2c->Init.OwnAddress2 = 0;
hi2c->Init.OwnAddress2Masks = I2C_OA2_NOMASK;
hi2c->Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
hi2c->Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
if (HAL_I2C_Init(hi2c) != HAL_OK) {
Error_Handler();
}
}
// GPIO 초기화 (I2C 및 RESO 핀 설정) - 데이터시트 핀 설명
void HAL_I2C_MspInit(I2C_HandleTypeDef *i2cHandle) {
GPIO_InitTypeDef GPIO_InitStruct = {0};
if (i2cHandle->Instance == I2C1) {
__HAL_RCC_GPIOB_CLK_ENABLE();
GPIO_InitStruct.Pin = GPIO_PIN_6 | GPIO_PIN_7; // PB6: SCL, PB7: SDA (데이터시트 핀 11, 9)
GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
GPIO_InitStruct.Pull = GPIO_PULLUP; // 풀업 저항 활성화
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF4_I2C1;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
__HAL_RCC_I2C1_CLK_ENABLE();
}
}
// 메인 함수 예시 - 모든 기능 테스트
int main(void) {
HAL_Init();
I2C1_Init();
// 모든 설정 실행
configure_all(&hi2c1);
// 진단 수행
perform_diagnostics(&hi2c1);
// 원시 데이터 읽기
int32_t sensor_data = read_raw_data(&hi2c1, SENSOR);
int32_t temp_data = read_raw_data(&hi2c1, TEMPERATURE);
// SSC 데이터 읽기
int32_t ssc_sensor, ssc_temp;
read_ssc_data(&hi2c1, &ssc_sensor, &ssc_temp);
// 사이클릭 모드 데이터 읽기
int32_t cyclic_sensor, cyclic_temp;
read_latest_data_cyclic(&hi2c1, &cyclic_sensor, &cyclic_temp);
// 진단 리셋
reset_diagnostics(&hi2c1);
// 슬립 모드 전환
enter_sleep_mode(&hi2c1);
while (1) {
// 메인 루프 - 실제 응용에서 데이터 처리 추가
}
}
코드 설명
위 코드에서 각 함수는 데이터시트의 특정 섹션과 연계됩니다:
함수 | 데이터시트 섹션 | 설명 |
---|---|---|
get_status | 6.4.1, Table 19 | NOP 명령으로 상태 바이트(Busy, Mode, Error) 확인 |
enter_command_mode | 6.6.1, Table 34 | START_CM (0xA9)으로 명령 모드 전환 |
enter_cyclic_mode | 6.6.1, Table 34 | START_CYC (0xAB)으로 사이클릭 모드 전환 |
enter_sleep_mode | 6.6.1, Table 34 | START_SLEEP (0xA8)으로 슬립 모드 전환 |
is_nvm_locked | Table 35, SSF1 | SSF1 비트 14 (lock) 확인 |
unlock_nvm | 핀 7 (RESO) | RESO 핀으로 리셋 및 잠금 해제 |
update_checksum | 6.6.2, Table 34 | Calculate NVM Checksum (0x90) |
write_nvm_data | Table 34 | Memory Write (0x40~0x75) |
read_nvm_data | Table 34 | Memory Read (0x00~0x3F) |
read_all_nvm | Table 35 | 전체 NVM (0x00~0x35) 읽기 보강 |
write_all_nvm | Table 35 | 전체 NVM (0x00~0x35) 쓰기 보강 |
configure_analog_frontend | 6.2, Table 5~13 | AFE 설정 (SSF1, SM_config1/2, extTemp_config) |
perform_diagnostics | 6.3, Table 17/18 | UPDATE_DIAG (0xB2) 및 CHECK_DIAG (0xB0) |
read_raw_data | 6.5.1, Table 34 | Raw Sensor/Temperature (0xA2/0xA4) |
read_ssc_data | 6.5.1, Table 34 | Measure (0xAA)으로 SSC 데이터 읽기 |
read_latest_data_cyclic | 6.5.2 | 사이클릭 모드 최신 데이터 읽기 |
configure_dac | 6.5.3, Table 29 | DAC 및 아날로그 출력 설정 (SSF2) |
configure_cyclic_scheduler | 6.5.2 | Measurement Scheduler (0x1E~0x20) |
configure_interrupt | 6.5.4 | 인터럽트 설정 (0x21) |
reset_diagnostics | 6.3 | RESET_DIAG (0xB1) |
configure_external_ldo | 6.7 | 외부 LDO 설정 (0x22) |
configure_all | 전체 | 모든 기능 통합 설정 |
write_calibration_coefficient | 7, Table 36 | 보정 계수 쓰기 |
configure_calibration_coefficients | 7 | 보정 계수 배열 설정 |
결론
이 가이드는 ZSSC3241의 데이터시트를 기반으로 모든 기능을 I2C 코드로 구현한 것입니다. 실제 프로젝트에서 센서 연결, 캘리브레이션 데이터 계산 등을 추가해 보세요.
참고: ZSSC3241 데이터시트 (Renesas), STM32L432KC 문서 (STMicroelectronics)