본문 바로가기

# Embedded

[Arduino] I2C와 Wire.h

728x90
반응형

Wire.h

I2C 통신을 쉽게 하기 위해 만든 객체

I2C 통신을 위해 SDA(A4), SCL(A5)핀을 제공한다.

SDA는 데이터를 주고 받기 위한 선, SCL은 타이밍 동기화를 위한 클럭 선이다.

하나의 마스터와 하나 이상의 slave로 이루어지고 최대 127개까지 연결 가능하다.

데이터 송수신은 master에서 주도하며 전송과 읽어오기 전 slave의 주소를 명시해야하므로 짧은 데이터 통신에 주로 사용된다.

시리얼(UART) 통신과 비교했을 때 장접은 동기화 통신이다. 통신 속도가 따로 정해지지 않아도 된다는 점이다.

시작신호, 데이터 신호, 정지 신호로 이루어진다.

image
image

공식 API : https://www.arduino.cc/reference/en/language/functions/communication/wire/

#include <Wire.h>

함수


1) Wire.begin( )

Wire.begin(address)     
I2C통신을 초기화 하고, 활성화 하는 함수

Slave모드인 경우 자신의 주소 값을 지정한다.

지정하지 않을 경우 자동으로 Master 모드로 설정된다.

통신 시작 전 한번만 호출하면 된다.

2) Wire.beginTransmission(address)

Master에서 전송을 시작하기 위해 Slave에서 주소 값을 지정한다.

Slave의 주소 값이 데이터 버퍼에 저장되어 전송될 준비를 한다.

해당 함수가 호출될 때 전송되는 것이 아닌 Wire.endTransmission( ) 함수가 호출될 때 한번에 전송된다.

address : 데이터를 전송할 슬레이브의 주소 값. 7bit data이므로 127을 넘을 수 없다.

3) Wire.wirte(value)

Wire.write(String)

Wire.write(dataArray, length)
Master는 Wire.beginTransmission( ) 함수가 호출 된 후 데이터 버퍼에 실제로 전송될 데이터를 저장하는 함수이다. 

Wire.write( ) 함수로 버퍼에 저장된 데이터는 Wire.endTransmission( ) 함수가 호출될 때 한꺼번에 전송된다.

Slave는 Master로부터 데이터 요청이 있을 때 요청에 대한 데이터를 전송하기 위해 사용된다. 이 때는 마스터에서 생성되는 클럭 신호에 맞춰 자동으로 전송 된다.

value : 전송할 데이터. 기본으로 byte형 데이터, int long 타입도 가능하지만 byte로 변환되어 손실될 수 있음

String : String 데이터를 전송한다. 길이만큼 버퍼에 저장된다.

dataArray : byte형 배열, length만큼 버퍼에 저장된다.

4) Wire.endTransmission( )
Wire.endTransmission(stop)

데이터 버퍼에 저장된 데이터를 전송한다. 

Master만 사용한다.

함수를 호출했을 때, 시작 신호부터 slave주소, 데이터가 전송되며, 정지신호의 생성 여부를 지정할 수 있다. 

전송이 완료된 후 전송 성공 여부를 byte형의 값으로 반환한다.

stop : 정지 신호를 생성할지 말지를 boolean값으로 지정한다. 지정하지 않은 경우 자동으로 TRUE로 설정되어 정지신호를 생성하며 FALSE인 경우 정지 신호를 생성하지 않고 연속하여 데이터를 전송한다.

<b>반환 값</b>

0 : 성공

1 : 데이터 버퍼의 길이가 허용 범위를 초과한 경우

2 : 주소 전송 단계에서 NACK 응답이 발생한 경우, 즉 해당 주소 값을 가진 slave가 없는 경우

3 : 데이터 전송 단계에서 NACK응답이 발생한 경우. 데이터 전송이 실패한 경우

4 : 그 외의 오류

5) byte Wire.requestFrom(address, quantity)

byte Wire.requestFrom(address, quantity, stop)
master에서 slave로 데이터를 요청한다. 요청할 슬레이브 기기의 주소 값을 지정하고, 수신할 데이터의 길이(byte 개수)를 설정한다.

boolean 형의 stop값으로 데이터 요청 후 정지 신호를 생성할지 말지를 지정할 수 있다. 

요청 후 수신된 데이터의 길이가 반환된다.

address : slave기기의 주소 값

quantity : 요청할 데이터의 바이트 수

stop : 정지신호 생성 여부

정지 신호는 둘 이상의 마스터가 존재하는 경우 사용된다. I2C통신에서 데이터 통신 라인(SDA)이 하나밖에 없기 때문에 한 번에 하나의 마스터만 전송할 수 있다. 이를 방지하기 위해 정지신호를 만든다.

6) int Wire.available( )

수신된 데이터 바이트 수를 반환한다.

master는 Wire.requestFrom( ) 함수 이후에 사용될 수 있고, Slave는 Wire.onReceive( ) 함수에 지정한 수신 이벤트 처리 함수 내에서 사용될 수 있다.

7) byte Wire.read( )

수신된 데이터를 읽어온다.

Wire.available( )로 수신 여부가 확인된 후 사용 된다.

<b>

8) Wire.onReceive(handler)

slave에서 사용되며, master로부터 데이터가 수신되었을 때 호출될 이벤트 처리 함수를 등록한다. 

이때 등록되는 이벤트 처리 함수는 반드시 정의되어 있는 함수여야 하고, 이벤트 ㅓ리 함수에는 다른 이벤트 처리 함수들과 달리 int형의 매개 변수가 사용되어야 한다.

handler : int형의 매개변수를 가지는 이벤트 처리 함수
#include <Wire.h>

byte address = 100;
byte recvDataBuf[128];

void setup(){
    Wire.begin(address);
    Wire.onReceive(receiveHandler);
}
void loop(){}

void receiveHandler(){
    for(int i = 0;i < nByteNum;i++){
        recvDataBuf[i] = Wire.read();
    }
}

9) Wire.onRequest(handler)

slave에서 사용되며 master로부터 데이터를 요청 받았을 때 호출될 이벤트 처리 함수를 등록한다.
#include <Wire.h>

byte address = 100;

void setup(){
    Wire.begin(address);
    Wire.onRequest(receiveHandler);
}

void loop(){}

void requestHandler(){
    byte data = 10;
    Wire.write(data);
}
728x90
반응형