본문 바로가기
Embedded System/소프트웨어 (C,C++)

[Arduino] Wire 라이브러리

by MachineJW 2023. 4. 19.

1.  I2C 통신 구현 라이브러리

아두이노에서는 I2C 통신을 쉽게 할 수 있도록 Wire 라는 객체를 제공한다.

I2C 통신을 모른다면.... 아래 게시물 참조

https://machinejw.tistory.com/44

 

I2C 통신

I2C 통신은 I Two C 또는 I Square C 라고 하며, Inter IC Bus의 약자이다. 이전에 공부했듯이 시리얼 통신 중에서도 동기식(데이터를 언제 주고받을지 규약됨) 통신 이며, I2C 통신의 경우 SCL(Serial Clock Line)

machinejw.tistory.com

2.  Wire 객체 함수 사용법

#include<Wire.h> 
// Wire 객체는 Wire.h 파일에 선언되어 있다.

Wire 는 아두이노 기본 제공 라이브러리이다.

(1) begin

Wire.begin();
Wire.begin(uint8_t address);

- 매개변수 : 7 비트 형식의 I2C 주소

- 반환 값 : 없음

 

begin()함수는 Wire 라이브러리를 초기화하고 I2C 버스를 참여한다.

매개변수로 7비트 형식의 I2C 주소를 지정하면 슬레이브로 I2C 버스로 참여한다.

주소를 지정하지 않으면 마스터로 참여한다.

마스터가 시작신호(START)와 7비트의 주소를 보내고 Write 값을 보냈다면 지정한 주소를 갖는 슬레이브는 마스터가 1바이트의 데이터를 보낼 것임을 인식하고 데이터가 수신되기를 기다린다. 

R/W가 HIGH 인 경우 마스터는 지정한 슬레이브로부터 전송되는 데이터를 SDA 라인에서 읽어 들일 것임을 나타낸다. R/W가 LOW인 경우 마스터는 지정한 슬레이브로 SDA 라인을 통해 데이터를 전송할 것 임을 나타낸다.

(2) beginTransmission

Wire.beginTransmission(uint8_t address);

- 매개변수 : 슬레이브 주소 (7 비트 형식의 I2C 주소)

- 반환 값 : 없음

 

지정한 주소의 슬레이브 장치로 데이터 전송을 시작한다. 실제 데이터 전송은 wirte 함수로 버퍼에 데이터를 기록한 후 endTransmission 함수가 호출 될 때 일어난다.

(3) endTransmission

Wire.endTransmission();
Wire.endTransmission(uint8_t sendStop);

- 매개변수 : 요청 완료 후 정지 메세지 전송 여부 (boolean)

- 반환값 : 전송 상태 스테이터스

반환값 의미
0 전송 성공
1 전송 데이터가 버퍼용량을 초과
2 주소 전송 후 NACK 수신
3 데이터 전송 후 NACK 수신
4 기타 TWI 오류

sendStop 매개변수가 false 이면 전송이 완료된 후에도 연결을 유지하여 다른 마스터 장치가 데이터를 전송할 수 없게 된다. defalut 값은 true 이다.

데이터를 수신한 장치는 데이터를 정상적으로 수신했음을 ACK 비트로 알려준다.

바이트 단위로 데이터를 전송한 뒤 수신 장치는 정상적인 수신을 알리기 위해 9번째 비트를 송신 장치로 전송한다. LOW 값은 ACK 비트로 수신 장치가 송신 장치로 정상적으로 데이터를 수신했음을 알려주기 위해 사용되며, HIGH 값은 NACK 비트로 정상적인 데이터 수신 이외의 상황이 발생 했음을 알려주기 위해 사용된다.

마지막 n 번째 바이트가 수신된 이후 마스터는 NACK를 슬레이브로 전송하여 수신이 완료 되었음을 알려준다. 데이터 전송이 끝나면 종료비트(P)를 전송함으로써 통신을 끝낸다.

(4) write

Wire.write(uint8_t data);
Wire.write(const uint8_t *data, size_t quantity);

- 매개변수 : data -> 전송할 단일 바이트 또는 바이트 배열에 대한 포인터

                    quantity -> 전송할 바이트 수

- 반환값 : 전송된 바이트 수

 

마스터 장치의 요청에 따라 슬레이브 장치가 데이터를 전송하거나, 마스터 장치에서 슬레이브 장치로 전송할 데이터를 큐에 기록하기 위해 사용한다.  마스터 장치에서 슬레이브 장치로 데이터를 전송하는 경우 write 함수는 반드시 beginTransmission함수와 endTransmission함수 사이에 있어야 한다.

슬레이브 장치에서 마스터 장치로 데이터를 전송하는 경우 write 함수는 onRequest 함수로 등록한 송신 요청 핸들러 함수 내에 있어야 한다.

(5) requestFrom

Wire.requestFrom(uint8_t address, uint8_t quantity);
Wire.requestFrom(uint8_t address, uint8_t quantity, uint8_t sendStop);

- 매개변수 : address -> 슬레이브 주소

                    quantity -> 요청하는 바이트 수

                    sendStop -> 요청 완료 후 정지 메세지 전송 여부

- 반환값 : 슬레이브 장치로부터 전송된 바이트 수

 

마스터 장치가 특정 주소의 슬레이브 장치에 지정한 양의 데이터를 요청한다. sendStop은 요청이 완료된 후 정지 메세지 전송 여부로, false를 지정하면 요청이 완료된 후에도 연결을 유지하여 다른 장치가 데이터를 요구할 수 없게 된다. 디폴트 값은 true이다.

(6) available

Wire.available();

- 매개변수 : 없음

- 반환값 : 유효바이트 수

 

데이터 수신 버퍼에서 read 함수로 읽을 수 있는 데이터의 바이트 수를 반환한다.

(7) read

Wire.read();

- 매개변수 : 없음

- 반환값 : 수신 버퍼의 한 바이트를 읽어서 반환

 

마스터 장치의 requestFrom 함수 호출에 따라 슬레이브 장치가 마스터 장치로 전송한 데이터 한 바이트를 수신 버퍼에서 읽어온다.

마스터 장치가 전송한 데이터를 슬레이브 장치에서 읽기 위해 슬레이브 장치에서 onReceive 함수로 등록한 수신 핸들러 함수에서도 read 함수를 사용할 수 있다.

(8) onReceive

Wire.onRequest( void (*function) (int) );

- 매개변수 : 데이터를 수신 했을 때 호출되는 핸들러 함수 포인터

- 반환값: 없음

 

슬레이브 장치가 마스터 장치로부터 데이터를 수신했을 때 호출되는 핸들러 함수를 등록한다.

핸들러 함수는 반환값이 없고 , 수신한 데이터의 바이트 수를 나타내는 int 타입의 매개변수를 갖는다.

(9) onRequest

Wire.onRequest(void (*function)(void));

- 매개변수 : 데이터 요청이 있을 때 호출되는 핸들러 함수 포인터

- 반환값 : 없음

 

슬레이브 장치가 마스터 장치로 부터 데이터 요청을 받았을 때 호출되는 핸들러 함수를 등록한다.

(10) setClock

Wire.setClock(uint32_t clock);

- 매개변수 : 동작 클럭

- 반환 값 : 없음

 

클럭 주파수 defalut 값은 100kHz 이다.

3.  실제 적용법

아두이노 프레임워크는 대부분 I2C 통신을 하는 해당 센서에 대해 라이브러리를 제공한다.

그러나 I2C 통신을 사용하는 어떤 센서가 있는데, 아두이노 라이브러리로 구현이 안되있을 경우도 있다.

이럴 경우 Slave(센서)측의 데이터시트를 확인하여 I2C 통신 부분을 보면서

직접 Wire 통신 라이브러리를 사용하여 구현하여야 한다. 

 

해당 데이터 시트는 SGP30, SGP40 센서 데이터 시트이다.

I2C 주소 값 부터 커맨드가 자세히 나와있다.
데이터시트의 커맨드(요청데이터)를 사용하여 원하는 값을 읽어올 수있다.