참고자료

아두이노, 오렌지보드 등의 오픈소스하드웨어를 사용하는데 필요한 것들을 알아봅니다.

통신 - I2C

2014-08-08 14:23:06

I2C 통신에 대하여

I2C 란

I2C(Inter-Intergrated Circuit)은 필립스에서 개발한 직렬 컴퓨터 버스이며.  마더보드, 임베디드 시스템, 휴대전화등에 저속의 주변기기를 연결하기 위해 사용된다.(출처 WiKi)

간단하게 통신을 하기위한 하나의 방법이라고 보면 된다.
아두이노에서는 기본으로 제공하는 Wire라이브러리를 사용하여 통신을 할 수 있으며 데이터라인(SDA)과 클럭라인(SCL) 2라인의 연결만 이루어 진다면 통신이 가능하다. 아두이노 UNO에서는 SDA와 SCL연결은 각각 아날로그 4번핀과 5번핀에 선을 꼽아 사용 할 수 있다.
I2C의 통신은 Master-Slave(주인-종)관계로 통신을 하게 되며 Master는 하나만 존재하며 Slave에게 데이터 요청을 할 수 있고, Slave는 각 기기마다 구별하기 위한 번호를 가지며 Master가 데이터를 요청하면 데이터를 전송할 수 있다.
I2C의 통신을 하기 위해서는 I2C통신을 가능하게 하는 Wire라이브러리에 대한 이해가 먼저 필요하다.

Wire라이브러리의 멤버함수

함수명 상세설명
begin()
begin(address)
Wire라이브러리를 초기화하고 I2C통신을 시작한다. 주소가 없을 경우 Master(데이터를 받는쪽)가 되고
주소를 매개변수로 입력할 경우에는 Slave(데이터를 전송하는쪽)가 된다.
requestFrom(address, quantity)
requestFrom(address, quantity,sendStop)
특정주소의 장치(address)에게 지정한 데이터의 양(quantity)만큼 데이터를 요청한다.
sendStop에는 요청완료후 정지메시지의 전송여부를 boolean값으로 나타낸다.
beginTransmission(address) 마스터장치가 특정주소(address)의 슬레이브 장치로 데이터 전송을 시작한다. 실제전송은 endTransmission()이 호출될때 일어난다.
endTransmission()
endTransmission(stop)
endTransmission이 호출될 때 실제 데이터 전송이 일어나고 beginTransmission()에 의해 시작된 데이터 전송을 끝낸다. 
stop값은 boolean값으로 true일 경우 stop메시지를 보내 연결을 해제하고 false일 경우 restart메시지를 계속보내서 연결을 유지한다.
write(value), write(string)
write(data, length)
beginTransmision()과 endTransmission()사이에서 마스터가 슬레이브에게 데이터를 전송하거나 슬레이브가 마스터에게 데이터를 전송할때 큐에 데이터를 입력하기 위해 사용한다. 
 available()  read()함수로 수신가능한 데이터의 바이트수를 반환한다. 이 함수는 마스터장치의 경우 requestFrom()을 호출한 후에 호출하고, 슬레이브의 경우에는 onReceive()함수 내부에서 호출해야한다.
 read() requestFrom()함수 호출에 의해 슬레이브가 마스터에게 전송한 데이터 한 바이트를 읽어서 반환한다.
마스터장치가 슬레이브에게 전송하는 데이터 1바이트를 읽을때도 사용가능하다. 
 onReceive() 마스터 장치가 보내는 데이터를 슬레이브가 수신했을때 호출되는 핸들러 함수를 호출한다. 쉽게말하면 데이터를 수신했을 때 특정 함수를 호출하게 하는 함수이다.
 onRequest() 마스터 장치가 슬레이브장치에게 데이터를 요청했을때 호출되는 함수를 등록한다. onReceive의 반대라고 생각하면 된다.

예제소스

예제소스를 사용하여 알아보자.

// Wire Master Reader
// by Nicholas Zambetti 

// Demonstrates use of the Wire library
// Reads data from an I2C/TWI slave device
// Refer to the "Wire Slave Sender" example for use with this

// Created 29 March 2006

// This example code is in the public domain.


#include 

void setup()
{
  Wire.begin();        // I2C통신을 시작한다
  Serial.begin(9600);  // 시리얼통신을 초기화 한다
}

void loop()
{
  Wire.requestFrom(2, 6);    // 2번 슬라이브기기에 6바이트의 데이터를 요구한다

  while(Wire.available())    // I2C통신을 통해 데이터가 전송되었는지 검사
  { 
    char c = Wire.read(); // 전송되었을 경우 데이터를 char형으로 읽는다
    Serial.print(c);         // 전송된 데이터를 출력한다
  }

  delay(500);
}

위 소스는 Wire예제소스를 master_reader라는 소스이다. 마스터에서 읽는 역할을 하는 소스로 생각하면 될 듯하다. 
소스를 보면 setup에서는 Wire.begin()과 Serial.begin(9600)을 사용하여 시리얼통신과 I2C통신을 초기화시켰다. 
loop()를 보면 requestFrom()함수를 통해 2번 주소를 가진 슬레이브에게서 6바이트의 데이터를 요청한다. 그 후 while문에서 available조건을 걸어줌으로 I2C통신으로 데이터가 전송되었을 경우 데이터를 읽어서 시리얼모니터에 출력한다. 

어려워 보이지만 시리얼통신과 별반 차이가 없다.

이번에는 마스터가 아닌 슬레이브 예제를 보자. Wire예제소스 중 slave_sender를 불러오자.

 

// Wire Slave Sender
// by Nicholas Zambetti 

// Demonstrates use of the Wire library
// Sends data as an I2C/TWI slave device
// Refer to the "Wire Master Reader" example for use with this

// Created 29 March 2006

// This example code is in the public domain.


#include 

void setup()
{
  Wire.begin(2);                // I2C통신을 시작하면서 2번의 태그를 가진다
  Wire.onRequest(requestEvent); // 데이터요청를 받으면 requestEvent함수를 실행한다
}

void loop()
{
  delay(100);
}

//마스터로부터 데이터전송 요청을 받으면requestEvent함수를 실행한다

void requestEvent()
{
  Wire.write("hello "); //6바이트크기의 "hello "를 전송한다
                       
}

setup에서는 begin(2)를 통해 주소를 2라고 명시해 줌으로써 자신이 슬레이브라는 것을 선언한다.(마스터일 경우 begin()에 매개변수를 적지 않는다) 그다음에 onRequest()함수를 통해 핸들러 함수를 지정해 주는데 여기서는 requestEvent라는 함수를 지정하였다. onRequest함수는 데이터 요청을 받았을 시에 핸들러함수를 호출하는 함수이므로 데이터 요청을 받았을 경우 이 슬레이브는 requestEvent()라는 함수를 호출하여 "hello"라는 문장을 전송하게 하였다. 

다음은 Master의 시리얼 모니터 창이다. 예제를 돌렸을 때 다음과 같이 hello 라는 문장을 Slave쪽에서 0.5초의 주기로(Master쪽에서 delay(500)으로 slave쪽으로 데이터 6바이트를 계속 요구한다) hello 라는 문장을 계속 송신한다.

kocoafabeditor

항상 진취적이고, 새로운 것을 추구하는 코코아팹 에디터입니다!

I2C통신, 중급, I2C, 통신