본문 바로가기
개발/Embedded

[I2C] 라즈베리파이와 EEPROM의 I2C 통신 (i2cget)

by jungcow 2024. 2. 6.

오늘은 간단하게 Linux의 i2c-tools 패키지 중 i2cget 사용을 알아볼 것이다.

이렇게 따로 기록하려는 이유는, EEPROM이 16-bit addressing을 사용하여 다른 인터넷에서 볼 수 있었던 예시와는 다르게 값을 넣어야 했기 때문이다.

 

이것이 어떤 말인지를 먼저 알아보고, EEPROM에 잘 작동이 되는 예시 명령어들을 살펴보려 한다.

환경

i2cget의 메뉴얼

i2cget과 address counter

일반적인 i2cget 사용은 아래와 같다.

i2cget -y <bus라인> <장치주소>

장치 주소만을 명시하는 방식이다.

 

address counter가 내부적으로 저장되는 EEPROM과 같은 장치에선, 마지막 작업이 있었던 주소에 1 byte 크기의 데이터를 읽어 반환하는 동작을 보여준다.

 

따라서 아래의 예시에선 1byte씩 5개의 데이터를 순차적으로 읽는 동작을 수행하게 된다.

i2cget -y 0 0x50 # 0x0000 주소의 데이터 반환
i2cget -y 0 0x50 # 0x0001 주소의 데이터 반환
i2cget -y 0 0x50 # 0x0002 주소의 데이터 반환
i2cget -y 0 0x50 # 0x0003 주소의 데이터 반환
i2cget -y 0 0x50 # 0x0004 주소의 데이터 반환

위 주석은 현재 address counter가 0x0000 주소를 가질 때의 동작을 보여준다.

 

이러한 동작은 하드웨어에서 아래의 "current address read" 와 같은 기능을 지원해주는 경우에만 가능하다. 

24fc512-i/ot 의 datasheet 중 Current Address Read

 

그럼 address counter가 가리키는 "현재 주소"는 어떻게 설정이 가능할까? 아래에서 계속 살펴보자.

i2cget과 i2cset

i2cset 명령어를 통해 현재 작업 위치를 설정해 줄 수 있다.

i2cset -y 0 0x50 0x00 0x00 i

[이전 포스팅] 에서 봤듯이, 지금 쓰고 있는 EEPROM의 경우 16-bit addressing을 사용하고 있으므로, i 라는 block mode를 통해 0x00 0x00 데이터를 두번 써줄 수 있게 했다.

 

위 명령어를 통해 address counter를 0x0000 위치로 설정해줄 수 있다. 이와 같이 동작하는 이유는, 현재 EEPROM의 메모리 주소까지만 write를 수행해주고 있고, 이는 아래의 그림에서 Data를 제외한 채 I2C write 통신을 수행하고 있는 건데,

24fc512-i/ot의 datasheet 중 일부

이 작업을 통해 수행되고 있는 것은 오로지 address counter를 내부적으로 설정하여 "작업"을 준비하는 과정밖에 없기 때문이다.

 

따라서 내부적으로 관리되는 address counter는 0x0000으로 설정되고, 다음 명령어가 위 "Current Address Read"와 같이 메모리 주소를 보내지 않는 I2C 통신일 경우 바로 현재 설정된 address counter 주소에 데이터를 가져오는 작업을 수행하게 된다.

 

지금까지의 도달한 과정을 정리하자면, 

특정 address counter를 설정할 수 있고, 이 설정된 주소에 데이터를 순차적으로 1byte씩 읽어올 수 있다

i2cset -y 0 0x50 0x00 0x00 i
i2cget -y 0 0x50 # 0x0000 주소의 데이터 반환
i2cget -y 0 0x50 # 0x0001 주소의 데이터 반환
i2cget -y 0 0x50 # 0x0002 주소의 데이터 반환
i2cget -y 0 0x50 # 0x0003 주소의 데이터 반환
i2cget -y 0 0x50 # 0x0004 주소의 데이터 반환

 

그럼 임의의 주소에서 read는 어떻게 할까? 아래에서 예시와 함께 살펴보자.

i2cget 임의의 주소에서 read

우리가 주소를 지정하기 위해선 i2cget -y 0 0x50 다음에 값을 하나더 추가해주면 된다. 아래 예시를 보면,

i2cget -y 0 0x50 0x00
  • 0x50: eeprom이 연결되어 있는 주소
  • 0x00: 읽으려는 데이터의 high-order 주소

우린 16-bit addressing 을 사용하고 있는 EEPROM의 임의의 주소에서 데이터를 읽어오고 싶다. 하지만 위 0x00이라는 데이터만 추가했고, 이는 high-order 주소를 의미한다고 언급했다. 

 

그럼 low-order 주소는 추가할 수 없는가?

 

위 사진을 보면 0x00 뒤에 0x02를 추가하여 0x0002 주소에서 데이터를 읽어오려 했다. 하지만 위와 같은 오류가 발생한다. 

 

보통의 장치들은 8-bit addressing 으로 내부 메모리 또는 레지스터에 접근하는 것 같다. 따라서 대부분의 장치에선 문제가 없겠지만, 이렇게 내가 사용하고 있는 EEPROM의 경우 2 바이트 주소를 지정하지 못하기 때문에, 바이트 단위의  "Random"한 주소로는 값을 읽어오지 못한다.

 

따라서 현재까지 판단하기엔 다음 두가지 방식으로만 수행할 수 있을 것 같다.

  1. high-order 주소만 지정해준 다음, lower-order주소 전반에 걸쳐 "Current Address Read"를 수행해주어야 할 것이다.
  2. i2cget을 수행하기 전, 항상 i2cset을 통해 address counter를 임의의 값으로 맞춘다.

결론

이와 같이 i2cget 명령어를 통한 여러 동작 방식을 살펴봤는데, 사실 여러 우여곡절이 있었다.

address counter가 내부에 관리되고 있다는 것을 알지 못했다면 동작 방식을 이해할 수 없었을 것이고, i2cset으로 이를 설정할 수 있다는 것도 몰랐다면 정말 i2cget 명령어를 사용할 수 없었을 것이다.

 

아래는 내가 사용하는 EEPROM의 datasheet의 일부이다. 

이렇게 datasheet을 꼼꼼히 읽고, 어떤 동작이 가능한지를 먼저 알아야 하는 것이 중요한 것 같다.

 

 

Appendix - i2cget과 word read

아래의 그림처럼 i2cget을 통해 2-byte read를 수행할 수도 있다.

 

'개발 > Embedded' 카테고리의 다른 글

[I2C] 라즈베리파이와 EEPROM의 I2C 통신 (i2cset)  (1) 2024.01.29