1. 개요
라즈베리파이와 EEPROM간의 I2C 통신 방법을 간략히 살펴보고 문제 해결에 초점을 맞추어 글을 이어나가려 한다.
환경
- raspberry pi 4
- ubuntu 20.04
- eeprom
2. I2C 통신 활성화
sudo raspi-config
위 명령어를 통해 라즈베리파이의 설정 화면으로 들어간다. 이후 아래의 글을 따라서 i2c 설정 및 연결 확인 작업을 수행한다.
https://m.blog.naver.com/chgy2131/221922893758
만약 위 블로그에서와 같이 i2cdetect 명령어로 주소 번호가 뜨지 않는다거나 하는 오류가 발생하면 다음을 확인해보면 좋다.
- eeprom이 정상적으로 납땜이 되었는가.
- eeprom과 라즈베리파이간의 와이어 연결이 정상적으로 되었는가.
나의 경우, eeprom이 납땜이 정상적으로 되어 있지 않아 i2cdetect 가 정상적으로 수행되지 않았던 적이 있다. 또한 sda 라인과 scl 라인을 엇갈리게 연결했을 때도 이런 문제가 발생했었다. 이런 확인하기 어려운 것들은 여러개의 eeprom을 가지고 비교 검증을 수행해보면 좋을 것 같다.
설정이 완료된 후 아래의 명령어를 쳐보자.
ls /dev/i2c*
위 명령어로 i2c-0이나 i2c-1 이라는 결과가 나왔다면, 뒤에 있는 숫자가 아래의 명령어와 -y 뒤에 붙을 숫자가 된다. 이 숫자는 bus를 의미한다고 나와 있다. 위 블로그에서는 1이 나와서 명령어와 -y 옵션 이후 1을 붙여주고 있다.
3. 16-bit addressing 의 문제
내가 사용하고 있는 EEPROM은 2바이트 어드레싱을 사용하고 있다. 즉 메모리의 주소가 2바이트로 표현되어 총 2^16의 바이트를 저장할 수 있는 구조이다.
이것이 왜 문제가 되냐... 바로 i2cset과 i2cget의 설명을 보면 1byte 주소체계를 사용하고 있는 장치에 맞게 명령어가 구성되어 있다는 것이다.
i2cset의 파라미터 구조는 다음과 같다.
i2cset -y <bus> <device address> <register address> <value>
# ex) i2cset -y 0 0x50 0x00 0x00
- bus: 0
- device address: 0x50
- register address: 0x00
- value: 0x00
이와 같이 볼 수 있다.
하지만 내가 원하는 것은 register address가 2 bytes, 즉 16-bit addressing을 함과 동시에 데이터를 쓰고 싶은 것이다. 따라서 아래와 같이 코드를 적어보면,
i2cset -y 0 0x50 0x00 0x00 0x78
위와 같은 오류가 발생한다. <value>뒤에 하나의 인자를 더 넣어 오류가 발생한 건데, 이를 해결하여 16-bit addressing을 i2cset 명령어에 어떻게 적용시키는지 살펴보도록 하자.
4. 해결 과정
i2c 통신에서의 데이터 값
먼저 위에서 봤던 예시를 다시 가져와보자.
i2cset -y <bus> <device address> <register address> <value>
# ex) i2cset -y 0 0x50 0x00 0x00
위와 같이 device address 이후에 오는 값에 대해 register address와 value라는 의미를 넣긴 했지만, 사실 register address와 value 모두 I2C 통신 입장에선 하나의 Data이다.
즉 데이터를 여러개 보낸다면, 이 장치는 첫번째 데이터는 register address로 해석하고, 두번째 값부터는 value로 해석한다는 뜻이다.
여기서 나의 16-bit addressing을 수행하는 EEPROM의 경우엔 어떻게 해석할까?
첫번째 값은 high-order address로, 두번째 값은 low-order address로 해석하고, 세번째 값부터는 이 두 바이트로 이루어진 주소에 쓰려는 값으로 해석하게 된다.
따라서 8bit addressing을 하던지 16-bit addressing 을 하던지간에 각각에 맞는 데이터 개수를 인자로 넣으면 된다는 것이다.
위 오류의 해결과정
그럼 위 실행에선 필요한 바이트 수만큼 넣어줬는데 왜 오류가 발생했는가? i2cset에선 `i` 라는 모드를 이용해서 여러개의 데이터들을 한번에 보낼 수 있다. 따라서 다음과 같이 고칠 수 있다.
i2cset -y 0 0x50 0x00 0x00 0x78 i
- 0: bus
- 0x50: eeprom이 연결되어 있는 주소
- 0x00: high-order address
- 0x00: low-order address
- 0x78: 0x0000에 write하려는 데이터 값
- i: block data 전송 모드.
5. 결론
사실 위에서는 i2cset 명령어가 1byte addressing에 더 적합하게 파라미터가 구성되어 있다고 언급했었는데, 그건 사용자 입장에서고 실제 i2c 통신 입장에선 장치 주소 이후에 오는 값들은 모두 데이터라고 인식할 뿐이다.
따라서 i2cset에 16-bit addressing을 사용하기 위해선 단순히 여러개의 값을 추가로 더 보내기만 하면 되는 문제였다. 값을 여러개 보내야 할 필요성을 느꼈다면, i2cset의 모드 중 여러 바이트열을 보낼 수 있는 모드가 있는지를 살펴봤으면 바로 문제 해결이 됐을 것이다.
i2cset 뿐만 아니라 i2cget에서도 16-bit addressing에서 오는 문제가 있었는데, 이는 EEPROM에 실질적으로 수행한 내용과 이것의 결과, 그리고 오류들을 적어놓을 때 같이 기록하려 한다.
'개발 > Embedded' 카테고리의 다른 글
[I2C] 라즈베리파이와 EEPROM의 I2C 통신 (i2cget) (0) | 2024.02.06 |
---|