[마이크로 프로세서] I2C 통신

이현준·2020년 11월 25일
0

I2C 통신 설명

I2C(Inter-Integrated Circuit)는 “아이-투-씨”라고 쉽게 읽기도 하지만, 정식 발음은 “아이-스퀘어-씨(I²C)”이다. 아두이노의 칩 제조사인 ‘Atmel’에서는 TWI(The Two-Wire Serial Interface)라고도 한다.
I2C 통신은 데이터를 주고 받기 위한 선(SDA) 하나와 송수신 타이밍 동기화를 위한 클럭 선(SCL) 하나로 이루어진다. 하나의 마스터(Master)와 하나 이상의 슬레이브(Slave)로 이루어지며, 슬레이브는 최대 127개까지 연결할 수 있다. 
데이터 송수신은 마스터에서 주도하며, 데이터를 전송하거나 읽어오기 전 반드시 슬레이브의 주소를 명시해준 후 통신을 시작해야 하기 때문에 긴 데이터 통신보다는 짧은 데이터 통신에 주로 사용된다.
I2C 통신의 장점은 동기화 통신 방식이라는 점이다. 
동기화 통신 방식이란 클럭(Clock) 신호를 이용해서 데이터의 전송 타이밍을 맞추는 방식인데, 때문에 시리얼 통신처럼 통신 속도가 따로 정해지지 않아도 된다는 장점이 있다.

master - receiver

Master 아두이노(좌)

#include <Wire.h>

void setup() {
  Wire.begin();        
  Serial.begin(9600);  
}

void loop() {
  // 8주소로부터 6바이트 받기(만약 2바이트면 hello에서 he만 온다)
  //이때 wire를 통해 요청을 하는 것임
  Wire.requestFrom(8, 6);    
  while (Wire.available()) {  
    char c = Wire.read(); 
    Serial.println(c);         
  }

  delay(500);
}

Slave 아두이노(우)

#include <Wire.h>

void setup() {
  Wire.begin(8);       
  //Master에서 requestFrom으로 요청했을 때
  //작동시킬 메소드 설정 
  //=>요청받으면 requestEvent을 실행한다.
  Wire.onRequest(requestEvent);
}

void loop() {
  delay(100);
}

//Master 아두이노에게 wire를 통해 hello를 전송한다.
void requestEvent() {
  Wire.write("hello"); 
}

master - writer

Master 아두이노(좌)

#include <Wire.h>

void setup()
{
  Wire.begin();
}

byte x = 0;

void loop()
{
  //4번 주소로 전송
  Wire.beginTransmission(4); 
  Wire.write("x is ");        
  Wire.write(x); 
  //전송마침 - 이래야지 slave쪽에서 끝난지 알 수 있음..?
  Wire.endTransmission();    

  x++;
  delay(500);
}

Slave 아두이노(우)

#include <Wire.h>

void setup()
{
  Wire.begin(4);                
  Wire.onReceive(receiveEvent); 
  Serial.begin(9600);           
}

void loop()
{
  delay(100);
}

void receiveEvent(int howMany)
{
  //Wire.available()은 현재 받은 바이트 수
  //howMany는 Wire.available()와 똑같은 값을 가진다
  Serial.println(Wire.available());
  while(1 < Wire.available()) 
  {
    char c = Wire.read(); 
    Serial.print(c);         
  }
  int x = Wire.read();    
  Serial.println(x);         
}

결과

slave 아두이노 측에서 이렇게 출력됨

마스터 쪽에서 "x is " 하고 숫자 x 를 보냈기 때문에 6바이트가 전송됨 그래서 Serial.println(Wire.available());의 결과가 6이 나오고
while(1 < Wire.available())을 통해 한 자리 남을때까지 읽어서 출력함으로 "x is "가 출력되고 한자리일때는 이것이 숫자로 보낸 x만 남아있으므로 숫자로 읽어서 출력해준다.

1:n 통신

master 아두이노 (좌)

#include <Wire.h>
void setup() 
{
  Wire.begin();        // join i2c bus (address optional for master)
  Serial.begin(9600);  // start serial for output
}
void loop() 
{
  	Wire.requestFrom(8, 6);    // request 6 bytes from slave device #8
	Serial.print("Received Name of address 8 : ");
  	while (Wire.available()) 
    { // slave may send less than requested
    char c = Wire.read(); // receive a byte as character
    Serial.print(c);         // print the character
  	}
	Serial.println("\n");
    delay(500);
	Wire.requestFrom(9, 6);    // request 6 bytes from slave device #8
	Serial.print("Received Name of address 9 : ");
  	while (Wire.available()) { // slave may send less than requested
    char c = Wire.read(); // receive a byte as character
    Serial.print(c);         // print the character
    }
    Serial.println("\n");
    delay(500);

}

slave 아두이노 (가운데)

#include <Wire.h>

void setup() {
  Wire.begin(8);                // join i2c bus with address #8
  Wire.onRequest(requestEvent); // register event
}

void loop() {
  delay(100);
}

// function that executes whenever data is requested by master
// this function is registered as an event, see setup()
void requestEvent() {
  Wire.write("Slave1"); // respond with message of 6 bytes
  //Wire.write(123);
  // as expected by master
}

slave 아두이노 (우)

#include <Wire.h>

void setup() {
  Wire.begin(9);                // join i2c bus with address #8
  Wire.onRequest(requestEvent); // register event
}

void loop() {
  delay(100);
}

// function that executes whenever data is requested by master
// this function is registered as an event, see setup()
void requestEvent() {
  Wire.write("Slave2"); // respond with message of 6 bytes
  // as expected by master
}

0개의 댓글