nowornever

I2C 가 뭐죠? 본문

Study

I2C 가 뭐죠?

JohnnyKoo 2014. 5. 27. 17:21

SI 회사에 처음 들어갔을 때에, 한 차장님께서 내게 물으셨다. 


"I2C 에 대해서 말해보세요." 

꿀먹은 벙어리.....로 3초간 있었지만 그래도 나름 전자 HW 업체에서 3년이나 일했는데 사람들 입에 그렇게 많이 오르락 내리락 하는 I2C 도 모르다니..... 너무 챙피했다. 그렇다면 이제 I2C 가 뭔지 제대로 좀 알고 가자. 


I2C 버스

자, I2C 버스란, 간단하게 두개의 선을 말한다. 그게 다임? 아니 좀 기다려 봐.. 인내심 부족하기는.. 이제부터 복잡해질테니! 근데 그 두개의 선 이름이 SCL 이랑 SDA 라고 해. 이 두개의 선이 I2C 버스위에 있는 모든 디바이스에 연결이 되거든. (아래 그림 참조) 근데 3번째 선이 필요한데, 이건 GND 혹은 그냥 0 V 이면 돼. 혹은 5V 의 추가적인 전원 선이 있을 수도 있는데 이건 디바이스들에 연결이 되겠지. SCL , SDA 선 두개 모두 "open drain" 드라이버 라고 부르는데 이게 무슨말이냐 하면, LOW 출력을 낼 수 있는 chip 이라는 이야기 이다. 그런데 HIGH 출력은 낼 수가 없다. HIGH 출력을 내기 위해서는 5V 공급선에 풀업 저항을 반드시 달아야 한다. SCL 선에서 5V 라인으로 저항이 있어야 하고, 또한 SDA 에서 5V 라인에도 저항이 필요하다. 전체의 I2C 버스를 위해서는 오직 한 세트의 풀업 저항들만 있으면 된다. 아래 그림을 참조. 



저항의 값은 그리 중요하지 않다. 1k8 ~ 47k 사이 값이면 괜찮다. 10k 가 가장 무난하고 추천 값은 1k8 정도.  만약 풀업 저항이 없다면, SCL, SDA 라인들은 모두 언제나 LOW 로 있을 것이다. 당연한 이야기지만 말이지. 그리고 I2C 버스는 동작이 되지 않겠지. 


마스터, 그리고 슬레이브

I2C 버스에 연결된 디바이스들은 마스터(주인) 이거나 슬레이브(노예) 가 된다. 마스터는 언제나 SCL 클록 라인을 drive (동작?) 시키는 디바이스이며 오직 마스터만이 할 수 있는 기능이다. 그리고 보통 한 개이상의 여러 슬레이브 디바이스들이 I2C 버스에 달리게 된다. 그러나 아까도 말했듯이 보통 하나의 마스터 디바이스만 존재하게 된다. 뭐, 여러개의 마스터가 불가능한 것은 아니지만, 드문 경우이고 여기서는 언급하지  않는다. 로봇의 경우, 마스터는 당신의 컨트롤러가 되겠고 슬레이브들은 우리의 모듈들, 즉 SRF08 (ultrasonic range finder, 초음파 센서 모듈로 추정) 혹은 CMP03 (solar charge controller)이 될 것이다. 당연히 슬레이브는 절대로 transfer 를 initiate 할 수 없다. 마스터와 슬레이브는 서로 I2C 버스라인을 통해 데이터를 주고 받을 수 있는데 언급하였듯이 통신은 언제나 마스터에 의해 제어된다.  

physical protocol

만약 마스터가 슬레이브와 통신을 하고 싶은 소망이 있다면, I2C 버스의 start sequence 를 이슈함으로 시작이 된다. 이 스타트 시퀀스와 stop sequence 는 I2C 에서 여러 다른 시퀀스들중 특별히 정의된 두 개의 시퀀스 들이다. 아래 그림 참조하면 바로 이해가 될 듯 하다. 


데이터는 8비트의 시퀀스로 transfer 가 되게 되는데 이것은 SDA 라인의 MSB (Most Significant Bit) 를 시작으로 비트들이 놓이게 된다. 그러면 SCL 라인이 HIGH 로 그리고 LOW 로 펄스가 된다. 기억해야할 점은, 이 칩은 사실 라인자체를 HIGH 로 drive 할 수 없고 다만, let go ("let it go" 가 최근에 유행하지 않았나. let go 는 그냥 수동적으로 그렇게 하게 냅둔다...내버려 두다..라고 이해하면 좋을것 같다). 총 8비트의 데이타가 전송되면, 디바이스는 데이터를 받았다는 LOW의  ack 비트를 보내게 된다. 그러면, 이제 데이터 다 받았으니깐 또 다른 패킷 보내! I'm ready! 라는 말이다.  만약 HIGH 의 ack bit를 보내게 된다면, 추가적인 데이터를 받을 수 없다는 뜻이므로 마스터는 stop 시퀀스를 보냄으로서 전송을 중단(terminate) 해야한다. 



How fast? 빠르기 ? 

기본적인 클록 (SCL)의 I2C 스피드는 100KHz 이다. fast mode, 400KHz, High Speed mode, 3.4MHz 까지 있다고 한다. 

I2C Device Addressing

모든 I2C 주소들은 7bit 혹은 10bit 로 이루어진다. 10bit 주소는 좀 드문 케이스이고 여기서는 7bit 주소를 다루어 보자. 그렇게 되면 우리는 I2C 에서 최대 128개의 디바이스를 연결할 수 있게 된다. (7bit 은 0~127 까지 표현이 가능함, 그리고 7비트씩 데이터를 보내게 되며 우리는 항상 8비트를 보내게 된다. 나머지 1비트는 마스터가 슬레이브에게 내가 지금 보내는 7비트 데이터가 너한테 쓰는것인지 (write) 혹은 읽으려는 요청인지 (read) 식별해주는 비트이다) 

e.g.) 만약 마스터가 특정 슬레이브의 주소 값을 읽고 싶다면, 상위 7비트는 읽으려는 슬레이브 디바이스의 주소값, 그리고 나머지 LSB 1비트는 읽겠다는 표현을 하게 된다. 

조금 헷갈릴 수 있지만 주소번지 21에 쓰기를 하고 싶다면 실제로 보내야 하는 값은42이다. (42는 21에서 1비트씩 움직인 값이다) 그냥 8비트를 보낸다고 생각하면 덜 헷갈릴 것으로 보인다. 이렇게 되면 같은주소값을 쓰거나 읽는것은 똑같은 주소값에서 짝수/홀수로 변할 뿐이다. CMP30 을 예로 들면, 0xC0 을 보내면 쓰는 데이터이고 0xC1 이면 읽는 요청 값이다. 


The I2C Software Protocol
The first thing that will happen is that the master will send out a start sequence. This will alert all the slave devices on the bus that a transaction is starting and they should listen in case it is for them. Next the master will send out the device address. The slave that matches this address will continue with the transaction, any others will ignore the rest of this transaction and wait for the next. Having addressed the slave device the master must now send out the internal location or register number inside the slave that it wishes to write to or read from. This number is obviously dependant on what the slave actually is and how many internal registers it has. Some very simple devices do not have any, but most do, including all of our modules. Our CMPS03 has 16 locations numbered 0-15. The SRF08 has 36. Having sent the I2C address and the internal register address  the master can now send the data byte (or bytes, it doesn't have to be just one). The master can continue to send data bytes to the slave and these will normally be placed in the following registers because the slave will automatically increment the internal register address after each byte. When the master has finished writing all data to the slave, it sends a stop sequence which completes the transaction. So to write to a slave device: 
1. Send a start sequence
2. Send the I2C address of the slave with the R/W bit low (even address)
3. Send the internal register number you want to write to
4. Send the data byte
5. [Optionally, send any further data bytes]
6. Send the stop sequence.

As an example, you have an SRF08 at the factory default address of 0xE0. To start the SRF08 ranging you would write 0x51 to the command register at 0x00 like this:
1. Send a start sequence
2. Send 0xE0 ( I2C address of the SRF08 with the R/W bit low (even address)
3. Send 0x00 (Internal address of the command register)
4. Send 0x51 (The command to start the SRF08 ranging)
5. Send the stop sequence.

Reading from the Slave
This is a little more complicated - but not too much more. Before reading data from the slave device, you must tell it which of its internal addresses you want to read. So a read of the slave actually starts off by writing to it. This is the same as when you want to write to it: You send the start sequence, the I2C address of the slave with the R/W bit low (even address) and the internal register number you want to write to. Now you send another start sequence (sometimes called a restart) and the I2C address again - this time with the read bit set. You then read as many data bytes as you wish and terminate the transaction with a stop sequence. So to read the compass bearing as a byte from the CMPS03 module:
1. Send a start sequence
2. Send 0xC0 ( I2C address of the CMPS03 with the R/W bit low (even address)
3. Send 0x01 (Internal address of the bearing register)
4. Send a start sequence again (repeated start)
5. Send 0xC1 ( I2C address of the CMPS03 with the R/W bit high (odd address)
6. Read data byte from CMPS03
7. Send the stop sequence.

The bit sequence will look like this:

Wait a moment
That's almost it for simple I2C communications, but there is one more complication. When the master is reading from the slave, its the slave that places the data on the SDA line, but its the master that controls the clock. What if the slave is not ready to send the data! With devices such as EEPROMs this is not a problem, but when the slave device is actually a microprocessor with other things to do, it can be a problem. The microprocessor on the slave device will need to go to an interrupt routine, save its working registers, find out what address the master wants to read from, get the data and place it in its transmission register. This can take many uS to happen, meanwhile the master is blissfully sending out clock pulses on the SCL line that the slave cannot respond to. The I2C protocol provides a solution to this: the slave is allowed to hold the SCL line low! This is called clock stretching. When the slave gets the read command from the master it holds the clock line low. The microprocessor then gets the requested data, places it in the transmission register and releases the clock line allowing the pull-up resistor to finally pull it high. From the masters point of view, it will issue the first clock pulse of the read by making SCL high and then check to see if it really has gone high. If its still low then its the slave that holding it low and the master should wait until it goes high before continuing. Luckily the hardware I2C ports on most microprocessors will handle this automatically.

Sometimes however, the master I2C is just a collection of subroutines and there are a few implementations out there that completely ignore clock stretching. They work with things like EEPROM's but not with microprocessor slaves that use clock stretching. The result is that erroneous data is read from the slave. Beware!

Example Master Code
This example shows how to implement a software I2C master, including clock stretching. It is written in C for the PIC processor, but should be applicable to most processors with minor changes to the I/O pin definitions. It is suitable for controlling all of our I2C based robot modules. Since the SCL and SDA lines are open drain type, we use the tristate control register to control the output, keeping the output register low. The port pins still need to be read though, so they're defined as SCL_IN and SDA_IN. This definition and the initialization is probably all you'll need to change for a different processor.

#define SCL     TRISB4 // I2C bus
#define SDA     TRISB1 //
#define SCL_IN  RB4    //
#define SDA_IN  RB1    //

To initialize the ports set the output resisters to 0 and the tristate registers to 1 which disables the outputs and allows them to be pulled high by the resistors.
SDA = SCL = 1;
SCL_IN = SDA_IN = 0;

We use a small delay routine between SDA and SCL changes to give a clear sequence on the I2C bus. This is nothing more than a subroutine call and return.
void i2c_dly(void)
{
}

The following 4 functions provide the primitive start, stop, read and write sequences. All I2C transactions can be built up from these.
void i2c_start(void)
{
  SDA = 1;             // i2c start bit sequence
  i2c_dly();
  SCL = 1;
  i2c_dly();
  SDA = 0;
  i2c_dly();
  SCL = 0;
  i2c_dly();
}

void i2c_stop(void)
{
  SDA = 0;             // i2c stop bit sequence
  i2c_dly();
  SCL = 1;
  i2c_dly();
  SDA = 1;
  i2c_dly();
}

unsigned char i2c_rx(char ack)
{
char x, d=0;
  SDA = 1; 
  for(x=0; x<8; x++) {
    d <<= 1;
    do {
      SCL = 1;
    }
    while(SCL_IN==0);    // wait for any SCL clock stretching
    i2c_dly();
    if(SDA_IN) d |= 1;
    SCL = 0;
  } 
  if(ack) SDA = 0;
  else SDA = 1;
  SCL = 1;
  i2c_dly();             // send (N)ACK bit
  SCL = 0;
  SDA = 1;
  return d;
}

bit i2c_tx(unsigned char d)
{
char x;
static bit b;
  for(x=8; x; x--) {
    if(d&0x80) SDA = 1;
    else SDA = 0;
    SCL = 1;
    d <<= 1;
    SCL = 0;
  }
  SDA = 1;
  SCL = 1;
  i2c_dly();
  b = SDA_IN;          // possible ACK bit
  SCL = 0;
  return b;
}

The 4 primitive functions above can easily be put together to form complete I2C transactions. Here's and example to start an SRF08 ranging in cm:

i2c_start();              // send start sequence
i2c_tx(0xE0);             // SRF08 I2C address with R/W bit clear

i2c_tx(0x00);             // SRF08 command register address
i2c_tx(0x51);             // command to start ranging in cm
i2c_stop();               // send stop sequence

Now after waiting 65mS for the ranging to complete (I've left that to you) the following example shows how to read the light sensor value from register 1 and the range result from registers 2 & 3.

i2c_start();              // send start sequence
i2c_tx(0xE0);             // SRF08 I2C address with R/W bit clear

i2c_tx(0x01);             // SRF08 light sensor register address
i2c_start();              // send a restart sequence
i2c_tx(0xE1);             // SRF08 I2C address with R/W bit set

lightsensor = i2c_rx(1);  // get light sensor and send acknowledge. Internal register address will increment automatically.
rangehigh = i2c_rx(1);    // get the high byte of the range and send acknowledge.
rangelow = i2c_rx(0);     // get low byte of the range - note we don't acknowledge the last byte.
i2c_stop();               // send stop sequence

Easy isn't it?

The definitive specs on the I2C bus can be found on the Philips website. It currently here but if its moved you'll find it easily be googleing on "i2c bus specification".


모든 그림과 내용은 다음 추처에서 거의 번역, 내지는 재해석한 내용입니다. 

출처: http://www.robot-electronics.co.uk/acatalog/I2C_Tutorial.html


'Study' 카테고리의 다른 글

추락해버리다.....ㅜㅜ  (0) 2013.05.15
Firefox 주소검색창 검색엔진 변경  (0) 2013.05.14
Excel 에서 문자 카운트 ! (콤마로 구분 되어있을 경우)  (0) 2013.05.11
LED Shift ~  (0) 2013.05.08
2013 Quadcopter project  (0) 2013.05.08