일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | |
7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 | 15 | 16 | 17 | 18 | 19 | 20 |
21 | 22 | 23 | 24 | 25 | 26 | 27 |
28 | 29 | 30 |
- raspberrypi
- AVR
- Debug
- QEMU
- GPIO
- Arduino
- Debugging
- 라즈베리파이
- Raspberry
- platformio
- BeagleBone
- USART
- 아두이노
- atmel
- Linux
- yocto
- 리눅스
- UART
- nucleo
- Visual Studio Code
- Visual Studio
- vscode
- esp32
- bare metal
- avr-gcc
- AArch64
- STM32
- 디버깅
- C++
- buildroot
- Today
- Total
임베디드를 좋아하는 조금 특이한 개발자?
[Arduino Uno] I2C통신 (Master 와 Slave간 송수신) 본문
- 개발 환경
개발 보드 :Arduino UNO R3
※ 주의
Arduino Uno R4 보드에서는 아래 실습코드가 동작하지 않습니다.!
해당 내용에 대해서는 따로 포스트 하도록 하겠습니다.
1. 서론
I2C 통신은 센서간 데이터 송수신에 많이 사용됩니다. 특히 2가지 큰 장점(2개의 배선으로 간단한 회로, 최대 127개의 디바이스 연결 가능)으로 인해 자주 사용합니다. 하지만, 다른 통신 보다 상대적으로 느린 속도를 가지고 있어 빠른 속도가 필요하다면 다른 통신을 고려해야합니다. 또한 통신의 주체가 마스터에게 있어 Slave 디바이스가 Master의 읽기 요청이 있기 전까지 데이터를 보낼 수 없습니다. 그리고 당연하게도 Slave 끼리의 데이터 통신도 불가능합니다.
- 장점
- SDA, SCL 2개의 배선으로 인해 매우 간단한 배선
- 최대 127개의 Slave 디바이스 연결 가능 (10bit 주소 크기 확장 가능)
- 단점
- 상대적으로 느린 통신 속도(클럭 속도를 높여 더 빠른 속도로 통신 가능)
2. 회로 배선
주의 할 점은 풀업 (Pull-up) 저항으로 4.7k옴을 사용하는 것과 두 아두이노 보드의 그라운드(GND)을 서로 연결해주어야 합니다. 두 보드가 Arduino Uno R3를 사용한다면 풀업 저항은 필수가 아닙니다. 하지만, Arduino Uno R4 를 사용한다면 반드시 풀업저항을 사용해야 합니다.
3. 실습 코드
3.1. Master -> Slave 데이터 송수신 코드 전송
- Master Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
#include <Wire.h>
void setup() {
Serial.begin(9600);
Wire.begin(); // 마스터로 설정
}
void loop() {
Wire.beginTransmission(0x10); // 0x10 Slave로 전송 시작
Wire.println("Hello world");
uint8_t err = Wire.endTransmission(); // 전송 마무리
if(err == 0){ // 성공적으로 전송
Serial.println("sent data successfully");
}
else{ // 전송 실패
Serial.println("Failed to send");
}
delay(1000);
}
|
cs |
5번째 줄에서 begin 함수에 매개변수을 전달하지 않으면 자동적으로 Master로 설정됩니다.
전송하고 싶은 데이터는 beginTransmisstion함수와 endTransmission함수로 감싸야 합니다.
endTransmission함수의 리턴값을 통해 전송 성공 유무를 알 수 있습니다.
- Slave Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
#include <Wire.h>
void setup() {
Serial.begin(9600);
Wire.begin(0x10); // 슬레이브 주소 0x10
Wire.onReceive(Wire_RecvISR);
}
void loop() {
}
void Wire_RecvISR(int size) {
while (Wire.available()) { // 수신 버퍼에 데이터가 남아 있다면
char c = Wire.read();
Serial.print(c);
}
}
|
cs |
5번째 줄에서 begin 함수에 설정하고자 하는 Slave 번호를 인자로 전달하여 Slave로 설정합니다.
6번째 줄에서 Master로 부터 데이터 전송 인터럽트 발생시 실행할 함수 포인터를 onReceive함수의 인수로 설정합니다.
3.2 Master <- Slave 데이터 송수신
- Master Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
#include <Wire.h>
void setup() {
Serial.begin(9600);
Wire.begin(); // 마스터로 설정
}
void loop() {
Wire.requestFrom(0x10, 12); // 0x10 Slave에게 12bytes 데이터 요청
while(Wire.available()){ // 수신 버퍼에 데이터있다면 반복
Serial.print((char)Wire.read());
}
delay(1000);
}
|
cs |
- Slave Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
#include <Wire.h>
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
Wire.begin(0x10);
Wire.onRequest(onRequestByWire);
}
void loop() {
}
void onRequestByWire(){
Wire.write("Hello world\n");
}
|
cs |
'Embedded > Arduino' 카테고리의 다른 글
[Arduino Uno R4 WIFI] Arduino IDE에서 디버깅 (0) | 2025.04.03 |
---|---|
[PlatformIO] Visual studio code에서 arduino 개발 (0) | 2025.03.25 |