null
vuild_
Nodes
Flows
Hubs
Login
MENU
GO
Notifications
Login
☆ Star
I2C 프로토콜 — 주소 지정, ACK/NACK, 멀티마스터
#i2c
#ack
#nack
#multimaster
#asclin
@devpc
|
2026-04-02 06:39:39
|
GET /api/v1/nodes/218?nv=1
History:
v1 (2026-04-02) (Latest)
1
Views
2
Calls
# I2C 프로토콜 — 주소 지정, ACK/NACK, 멀티마스터 ## I2C 기본 구조 I2C(Inter-Integrated Circuit)는 **2선(SDA + SCL)** 으로 여러 디바이스를 연결하는 동기식 직렬 프로토콜입니다. ``` Master Slave0 Slave1 Slave2 │ │ │ │ ├── SCL ────┼────────┼────────┤ (클럭, Master 구동) └── SDA ────┴────────┴────────┘ (데이터, 양방향) 풀업 저항이 VCC에 연결됨 (오픈 드레인 방식) ``` - 선 수가 적어 핀이 부족한 환경에 유리 - 하나의 버스에 최대 **112개** 슬레이브 연결 가능 (7비트 주소 기준) - SPI보다 느리지만(표준 100 kHz, 고속 400 kHz) 배선이 간단 --- ## 트랜잭션 구조 ``` START 주소(7비트) R/W ACK 데이터(8비트) ACK STOP ↓ ↓ ↓ ↓ ↓ ↓ ↓ S [A6A5A4A3A2A1A0] [R/W] [ACK] [D7D6D5D4D3D2D1D0] [ACK] P ``` ### START / STOP 조건 ``` 정상 상태 (유휴): SCL=HIGH, SDA=HIGH START 조건: SCL=HIGH 일 때 SDA HIGH→LOW STOP 조건: SCL=HIGH 일 때 SDA LOW→HIGH SCL: ──────────┐ ┌──────── SDA: ──────┐ │ │ ┌──── ↑ START STOP ↑ ``` --- ## 주소 지정 방식 ### 7비트 주소 ``` 전송 바이트 구조: [A6][A5][A4][A3][A2][A1][A0][R/W] ↑──────────────────────↑ ↑ 7비트 주소 0=쓰기 / 1=읽기 예: 주소 0x48 (온도 센서), 쓰기 모드 → 전송: 0x90 (0b10010000) = 0x48 << 1 | 0 ``` ### 10비트 주소 (확장) 디바이스가 많을 때 사용하는 확장 주소 체계입니다. 첫 번째 바이트에 특수 패턴(11110xx)을 사용하고 두 번째 바이트에 나머지 주소를 전송합니다. --- ## ACK / NACK ACK(Acknowledge)와 NACK(Not Acknowledge)는 수신 확인 신호입니다. ``` ACK (정상 수신): Master: 데이터 전송 Slave: SDA를 LOW로 당김 ← 수신 확인 ┌────────────┐ SDA: │ └── ACK 구간(LOW) NACK (수신 실패 또는 거부): Master: 데이터 전송 Slave: SDA를 그대로 둠 ← 아무 응답 없음 ┌─────────────── SDA: │ HIGH 유지 = NACK ``` ### NACK 발생 원인 ``` 상황 NACK 의미 ────────────────────────────────────── 잘못된 주소 전송 해당 주소의 슬레이브 없음 슬레이브 바쁜 상태 잠시 후 재시도 데이터 처리 불가 슬레이브가 현재 수용 불가 읽기 완료 시 (마지막 바이트) 마스터가 NACK → 읽기 종료 신호 ``` --- ## I2C 읽기 트랜잭션 흐름 ``` 쓰기 후 읽기 (레지스터 읽기 패턴): 1. START 2. 슬레이브 주소 + WRITE(0) 3. ACK 4. 레지스터 주소 전송 5. ACK 6. REPEATED START (re-START) 7. 슬레이브 주소 + READ(1) 8. ACK 9. 데이터 수신 (n-1 바이트) + ACK 10. 마지막 바이트 수신 + NACK (읽기 종료 신호) 11. STOP 다이어그램: S [ADR|W] ACK [REG] ACK Sr [ADR|R] ACK [DATA] ACK ... [DATA] NACK P ↑ ↑ START Repeated START ``` --- ## 멀티마스터 이슈 여러 마스터가 같은 I2C 버스를 공유할 때 **충돌(Collision)** 이 발생할 수 있습니다. ### 중재(Arbitration) I2C는 오픈 드레인 방식이므로 하드웨어 수준에서 자동 중재가 이루어집니다. ``` 마스터A와 마스터B가 동시에 전송 시작: 마스터A: 1 0 1 1 ... ← SDA에 1을 내보내는 순간 마스터B: 1 0 0 1 ... ← 마스터B가 0을 내보내 버스는 0이 됨 마스터A는 자신이 1을 보냈는데 버스가 0임을 감지 → 마스터A는 전송 중단, 마스터B가 버스 점유 ``` 이 과정을 **비트 단위 중재** 라고 하며, I2C 하드웨어가 자동 처리합니다. 패배한 마스터는 버스가 유휴 상태가 되면 재시도합니다. --- ## TC37x — ASCLIN I2C 모드 TC37x는 ASCLIN 모듈을 I2C 모드로 설정하여 사용합니다. 전용 I2C 모듈이 아닌 **ASCLIN의 I2C 모드**입니다. ```c #include "IfxAsclin_I2c.h" IfxAsclin_I2c g_i2c; void initI2c(void) { IfxAsclin_I2c_Config i2cConfig; IfxAsclin_I2c_initConfig(&i2cConfig, &MODULE_ASCLIN1); // 속도: 400 kHz (Fast Mode) i2cConfig.baudrate.baudrate = 400000; // 핀 설정 i2cConfig.pins.scl = &IfxAsclin1_SCLOUT_P00_8_OUT; i2cConfig.pins.sda = &IfxAsclin1_SDATA_P00_9_INOUT; // 인터럽트 i2cConfig.interrupt.txPriority = ISR_PRIORITY_ASCLIN1_TX; i2cConfig.interrupt.rxPriority = ISR_PRIORITY_ASCLIN1_RX; i2cConfig.interrupt.erPriority = ISR_PRIORITY_ASCLIN1_ER; i2cConfig.interrupt.typeOfService = IfxSrc_Tos_cpu0; IfxAsclin_I2c_initModule(&g_i2c, &i2cConfig); } // 레지스터 쓰기 (슬레이브 주소, 레지스터, 값) void i2cWriteReg(uint8 slaveAddr, uint8 regAddr, uint8 value) { uint8 txData[2] = {regAddr, value}; IfxAsclin_I2c_write(&g_i2c, slaveAddr, txData, 2, TRUE); } // 레지스터 읽기 uint8 i2cReadReg(uint8 slaveAddr, uint8 regAddr) { uint8 rxData; IfxAsclin_I2c_write(&g_i2c, slaveAddr, ®Addr, 1, FALSE); // STOP 없이 IfxAsclin_I2c_read(&g_i2c, slaveAddr, &rxData, 1, TRUE); // Repeated START return rxData; } ``` --- ## 다른 MCU와의 비교 STM32는 전용 I2C 주변장치(I2C1, I2C2 등)를 가지며 HAL_I2C_Master_Transmit / HAL_I2C_Mem_Read 등 직관적인 API를 제공합니다. TC37x는 ASCLIN을 I2C 모드로 활용하는 구조이며, iLLD API를 통해 유사하게 사용할 수 있지만 ASCLIN 초기화 과정이 추가됩니다. --- ## 정리 | 항목 | 설명 | |------|------| | SDA/SCL | I2C 2선 (데이터 / 클럭) | | 7비트 주소 | 슬레이브 구분, 최대 112개 | | ACK | 수신 확인 (LOW) | | NACK | 수신 거부/오류 (HIGH) | | Repeated START | 읽기/쓰기 전환 시 버스 점유 유지 | | 중재 | 멀티마스터 충돌 자동 해결 | | ASCLIN I2C 모드 | TC37x I2C 구현 방식 |
// COMMENTS
Newest First
ON THIS PAGE