아두이노/이론

I2C통신 아두이노와 오실로스코프로 확인해보기 3편

원원 2021. 10. 4. 11:03

안녕하세요. 오늘은 2편에 이어서 WRITE와 READ를 해보겠습니다.

I2C통신 아두이노와 오실로스코프로 확인해보기 1편
https://wowon.tistory.com/224?category=615512
I2C통신 아두이노와 오실로스코프로 확인해보기 2편
https://wowon.tistory.com/225?category=615512

1) WRITE하기

-Wire.write(value) : 슬레이브에게 보낼 데이터입니다. 데이터를 큐에 넣고, endTransmission() 함수를 호출하면 데이터를 전송합니다
value : 1바이트로 보내는 값

 

 

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
#include<Wire.h>
 
 
void setup() {
  Wire.begin();
  Serial.begin(9600);
}
 
void loop() {
  int i;
  uint16_t i2c_received = 0;
  Wire.beginTransmission(0x48);
 Wire.write(0x00);
  i = Wire.endTransmission();
 
  if(i ==0)
  {
    Serial.println("success");
 
  }
  else
  {
    Serial.print("Error : ");
    Serial.println(i);
  }
 
  delay(1000);
}
cs

13번줄에서 데이터 0x00을 write했습니다. 오실로스코프로 파형을 보겠습니다.

주황색: 마스터 흰색:슬레이브

 

데이터를 0x01과 0x02도 보내보겠습니다

 

-0x01

-0x02

 

2)READ하기

-Wire.requestFrom(address, quantity) : 마스터가 슬레이브로 바이트를 요청할때 사용합니다. 
Return값이 TRUE면 STOP메세지를 보내고 통신을 종료합니다
Return값이  FALSE면 요청 후 다시 메세지를 보냅니다. 다른 마스터 장치에서 메세지 보내는 것을 방지합니다

address : 슬레이브 주소
quantity : 요청 할 바이트 수

-Wire.readBytes(buffer, length) :데이터를 읽습니다
buffer : 저장할 장소
lenght : 읽을 바이트의 길이

 

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
31
32
33
34
35
36
37
#include<Wire.h>
 
 
void setup() {
  Wire.begin();
  Serial.begin(9600);
}
 
 
void loop() {
  int i;
  float result=0;
  uint16_t i2c_received = 0;
  Wire.beginTransmission(0x48);
  Wire.write(0);
  i = Wire.endTransmission();
 
  if(i ==0)
  {
    Serial.println("success");
    if (Wire.requestFrom(0x482)) {
    Wire.readBytes((uint8_t*)&i2c_received, 2);
    Serial.println(i2c_received);
    } 
    else
    {
      Serial.println("READ_ERR");
    }
  }
  else
  {
    Serial.print("Error : ");
    Serial.println(i);
  }
 
  delay(1000);
}
cs

일단 위의 코드는 온도값을 센서로부터 읽은 가공이 안된 상태입니다. 
22번 줄은 LM75A의 ADC 값이 2바이트를 읽으라고 되어있으므로 2바이트를 읽은 모습입니다
결과값이 24599이므로 2진수 0110 0000 0001 0111입니다. 실제 파형이 이렇게 찍혔나 보겠습니다

LM75A데이터시트에있는 2바이트 READ

앞부분은 WRITE이고 뒷부분은 READ입니다.  데이터값이 0001 0111가 읽히고 0110 0000 가 읽혔는데, readBytes를 사용하면 하위 1바이트를 먼저 저장하고 상위1바이트를 나중에 저장하는것 같습니다. 

그럼 이제 상위1비트와 하위1비트의 자리를 변경해주면 원래 값이 나옵니다. 그리고 이 데이터는 11개의 유효 비트만 사용하므로 LSB비트의 5개는 무시해야합니다. 쉬프트연산 해주면 됩니다. 그리고 *0.125해주면 섭씨가 나옵니다

 

 

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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
#include<Wire.h>
 
 
void setup() {
  Wire.begin();
  Serial.begin(9600);
}
 
 
void loop() {
  int i;
  float result=0;
  uint16_t i2c_received = 0;
   uint8_t i2c_received2 = 0;
   uint8_t i2c_received3 = 0;
  Wire.beginTransmission(0x48);
  Wire.write(0);
  i = Wire.endTransmission();
 
  if(i ==0)
  {
        if (Wire.requestFrom(0x482)) {
    Wire.readBytes((uint8_t*)&i2c_received, 2);
 
 
    int16_t refactored_value;
    uint8_t* ptr = (uint8_t*)&refactored_value;
 
    //swap
    *ptr = *((uint8_t*)&i2c_received + 1);
    *(ptr + 1= *(uint8_t*)&i2c_received;
 
    //shift
    refactored_value >>= 5;
 
    Serial.print("TEMP : ");
    Serial.print(refactored_value*0.125);
    Serial.println(" degree");
    
    } 
    else
    {
      Serial.println("READ_ERR");
    }
  }
  else
  {
    Serial.print("Error : ");
    Serial.println(i);
  }
 
  delay(1000);
}
cs