I2C : Inter IC Bus
I2C Bus
Inter-IC Bus (= TWI: Two-wire Serial Interface)
Philips¿¡¼ Á¦¾ÈÇÑ IC°£ Åë½Å ¹æ½ÄÀ¸·Î Ŭ·°(SCL)°ú µ¥ÀÌÅÍ(SDA)ÀÇ
2¶óÀÎÀ» »ç¿ëÇÏ´Â µ¿±â ¾ç¹æÇâ 2¼±½Ä BusÀÌ´Ù. ¹ö½º¿¡ ¿¬°áµÈ °¢ µð¹ÙÀ̽º´Â °íÀ¯ÀÇ
¾îµå·¹½º¸¦ °®À¸¸ç Çʿ信 µû¶ó receiver¿Í transmitter·Î µ¿ÀÛÇÑ´Ù. Àü¼Û¼Óµµ´Â
standard mode¿¡¼ 100kbps±îÁö À̰í fast mode¿¡¼´Â 400kbps±îÁö °¡´ÉÇÏ´Ù.
transmitter: ¹ö½º¿¡ µ¥ÀÌŸ¸¦ º¸³»´Â ÀåÄ¡
receiver: ¹ö½º·ÎºÎÅÍ µ¥ÀÌŸ¸¦ ¹Þ´Â ÀåÄ¡
master: Àü¼ÛÀ» °³½ÃÇÏ´Â ÀåÄ¡·Î Ŭ·° ÆÞ½º¸¦ ¸¸µé°í, Àü¼ÛÀ» Á¾·áÇÏ´Â ÀÏÀ» ÇÑ´Ù.
slave: master°¡ ¾îµå·¹½ÌÇÑ ÀåÄ¡
master°¡ start conditionÀ» ¸¸µé¸é ¹ö½º¿¡ ¿¬°áµÈ ½½·¹À̺ê ÀåÄ¡µéÀÌ
ÀÌÈÄÀÇ µ¥ÀÌÅ͸¦ ±â´Ù¸°´Ù. master°¡ slave ¾îµå·¹½º¸¦ º¸³»¸é °¢ ĨÀº ÀÚ½ÅÀÇ °íÀ¯
¾îµå·¹½º¿Í ºñ±³¸¦ ÇÑ´Ù. ¾îµå·¹½º°¡ ÀÏÄ¡Çϴ ĨÀº À̾îÁö´Â acknowledge ½ÅÈ£ ±¸°£¿¡¼
µ¥ÀÌÅ͸¦ low·Î À¯ÁöÇØ ÀÀ´äÀ» º¸³½´Ù. ±×·¯¸é master´Â µ¥ÀÌÅ͸¦ Àаųª ¾²±â¸¦
ÇÒ ¼ö ÀÖ´Ù. ¸ðµç ÀÛ¾÷ÀÌ ³¡³ª¸é master´Â stop conditionÀ» ¹ß»ýÇÏ°í ¹ö½º¸¦ releaseÇÑ´Ù.
SDA H -\ /---\ /---\
/---\ /---\
/--- L \----/ \---/
\--------/ \-------/
\----/ SCL H ----\ /-\
/-\ /-\ /-\ /-\
/-\ /------ L
\---/ \-----/ \---/ \--/ \--/
\--/ \--/ | START |
1 | 1 | 0
| 1 | 0 | 1 | STOP
* start condition Ŭ·°°ú µ¥ÀÌÅͰ¡ ¸ðµÎ highÀÎ ÀÏ¹Ý »óÅ¿¡¼ µ¥ÀÌŸ ¶óÀÎÀÌ low·Î
¶³¾îÁö´Â »óÅÂ.
SDA H ------\ L
\------- SCL H ---------\ L
\----
* stop condition
Ŭ·°ÀÌ highÀÎ µ¿¾È¿¡ µ¥ÀÌŸ ¶óÀÎÀÌ low¿¡¼ high·Î ¹Ù²î´Â »óÅÂ.
SDA H
/---- L ---------/ SCL H
/------- L ------/
* ÀÏ¹Ý µ¥ÀÌÅÍ Àü¼Û¿¡¼´Â Ŭ·°ÀÌ lowÀÏ ¶§¸¸ µ¥ÀÌŸÀÇ »óŸ¦
¹Ù²Ü ¼ö ÀÖ´Ù. µû¶ó¼ Ŭ·°ÀÌ highÀÎ ±¸°£¿¡¸¸ À¯È¿ÇÑ µ¥ÀÌŸÀÌ´Ù. master´Â ¸ÕÀú
µ¥ÀÌŸ ¶óÀÎÀ» Àû´çÇÑ µ¥ÀÌŸ·Î ¹Ù²Ù°í Ŭ·° ¶óÀÎÀ» ÀÏÁ¤½Ã°£ high·Î ÇÏ°í ´ÙÀ½ SDA
¶óÀÎÀÇ »óŸ¦ ¹Ù²Ù±â Àü¿¡ Ŭ·°À» low·Î ¸¸µç´Ù. µ¥ÀÌŸ´Â 8bitÀ̰í MSB°¡ ¸ÕÀú
Àü¼ÛµÈ´Ù. start ¿Í stop condition »çÀÌ¿¡ Àü¼ÛµÇ´Â µ¥ÀÌŸÀÇ ¼ö´Â Á¦ÇÑÀÌ ¾ø´Ù.
SDA H /----------\
L -----/\----------/\------- SCL H
/----\ L --------/ \----------
* acknowledge Á¶°Ç masterµç slaveµç transmitter´Â 8 bit Àü¼ÛÀ» ¸¶Ä¡°í ¹ö½º¼±À» high·Î
ÇÑ´Ù. 9¹øÂ° »çÀÌŬ µ¿¾È receiver´Â µ¥ÀÌŸ ¼±À» low·Î À¯ÁöÇÏ¿© acknowledge ¸¦
Ç¥½ÃÇÑ´Ù.
Çɸ¦ open drainÀ¸·Î ÇÏ°í ¿ÜºÎ¿¡ Ç®¾÷ ÀúÇ×À» ´Þ±â ¶§¹®¿¡ ±âº» °ªÀº high »óÅÂÀÌ´Ù. ÀÎ½Ä ½ÅÈ£ÀÎ ACK ´Â low ·Î Á¤ÇØ¾ß ÇÑ´Ù.
¾Æ¹« º¯È°¡ ¾ø´Â high »óŰ¡ NACK °¡ µÈ´Ù.
* slave ÀåÄ¡°¡ ¹Ù»Û °æ¿ì´Â ACK ·Î ÀÀ´äÇÏÁö ¾ÊÀ» ¼ö ÀÖ´Ù. ±× ¶§´Â STOP conditionÀ» ÁÖ°í ÀÌÈÄ¿¡ Àç½Ãµµ ÇÑ´Ù.
write½Ã
ÇÑ byte write½Ã
S |
slave address |
A |
data write |
A |
P |
¿©·¯ byte write½Ã
S |
slave address |
A |
data write |
A |
data write |
A |
... |
data write |
A |
P |
Note : S = start condition
A = Wait for Acknowledge (master <-- slave)
P = stop condition
read½Ã
slave address¸¦ º¸³½ÈÄ SDA¸¦ ³õ¾ÆÁÖ¸é slave°¡ 8bit µ¥ÀÌÅ͸¦
º¸³»°í master´Â ack½ÅÈ£¸¦ slave¿¡°Ô º¸³»ÁØ´Ù.
ÇÑ byte reading
S |
slave address |
WA |
read byte |
GNA |
P |
¿©·¯ byte reading
S |
slave address |
WA |
read byte |
GA |
... |
read byte |
GNA |
P |
Note: WA = Wait for Acknowledge (master <-- slave)
GA = Give Acknowledge (master --> slave)
GNA = Give Acknowledge with NACK (master --> slave) : end of reading
master ¿Í slave °£ handshake
slave ÀåÄ¡´Â address ¸ÅÄ¡ ¹× µ¥ÀÌÅÍ ¹ÙÀÌÆ® ¼ö½Å½Ã ACK ½ÅÈ£¸¦ º¸³»ÁØ ÀÌÈÄ¿¡ ³»ºÎ ó¸® ½Ã°£ÀÌ ÇÊ¿äÇÑ °æ¿ì´Â clock ¶óÀÎÀ» low ·Î À¯ÁöÇÏ¿© master ÀåÄ¡°¡ ´ÙÀ½ ¹ÙÀÌÆ®¸¦ ¼Û½ÅÇÏÁö ¾Ê°í ´ë±âÇϵµ·Ï ÇÒ ¼ö ÀÖ´Ù. (Clock stretching)
I2C bus reset (I2C bus recovery)
I2C´Â state machineÀ¸·Î µ¿ÀÛÇÏ´Â ±¸Á¶¶ó¼ ³ëÀÌÁî µîÀ¸·Î master¿Í slave ÀÇ state°¡ ¼·Î ¾î±ß³¯ °æ¿ì ´õÀÌ»ó µ¿ÀÛÇÏÁö ¾Ê°Ô µÈ´Ù. º¸Åë ÀÌ·±°æ¿ì slave°¡ SDA ¶óÀÎÀ» °è¼ÓÇØ¼ 0À¸·Î ºÙÀâ°í ÀÖ°Ô µÈ´Ù. ÀÌ·± °æ¿ì´Â I2C¹ö½º¸¦ ¸®¼Â½ÃÄÑ ÁØ´Ù. ÃÖ´ë 9ºñÆ®ÀÇ µ¥ÀÌÅ͸¦ ¸¸µé¾î ÁÖ°í ¸¶Áö¸·¿¡ STOP conditionÀ» Á༠°á±¹ slaveÀÇ state machineÀ» ÃʱâÈ ½ÃÄÑÁÖ°Ô µÈ´Ù.
from Analog Device¡¯s Application note AN-686 ¡°Implementing an I2C Reset¡±
1) Master tries to assert a Logic 1 on the SDA line
2) Master still sees a Logic 0 and then generates a clock pulse on SCL (1-0-1 transition)
3) Master examines SDA. If SDA = 0, go to Step 2; if SDA = 1, go to Step 4
4) Generate a STOP condition
°£´ÜÇÏ°Ô GPIO ¸ðµå·Î Ŭ·°À» 11 ¸¸µé¾î ÁÖ°í ¸¶Áö¸·¿¡ STOP condition À» º¸³»¼ i2c ¹ö½º¸¦ ÃʱâÈ ÇÑ´Ù.
I2C software driver pseudo code
#define SDA_HIGH() { ... your code here ... } // SDA pin high
#define SDA_LOW() { ... your code here ... } // SDA pin low
#define SCL_HIGH() { ... your code here ... } // SCL pin high
#define SCL_LOW() { ... your code here ... } // SCL pin low
#define SDA_OUTPUT() { ... your code here ... } // SDA pin output mode
#define SDA_INPUT() { ... your code here ... } // SDA pin input mode
#define SDA_READ() { ... your code here ... } // SDA pin read
#define i2c_delay() delay_us(5) // delay time for 100khz clock
void i2c_start(void)
{
SDA_HIGH(); SCL_HIGH(); i2c_delay();
SDA_LOW(); i2c_delay();
SCL_LOW(); i2c_delay();
}
void i2c_stop(void)
{
SDA_LOW();
SCL_HIGH(); i2c_delay();
SDA_HIGH(); i2c_delay();
}
unsigned char i2c_write(unsigned char data)
{
unsigned char i, ack;
for(i=0; i<8; i++)
{
if(data & 0x80) SDA_HIGH(); // MSB first
else SDA_LOW();
i2c_delay();
SCL_HIGH(); i2c_delay();
SCL_LOW(); i2c_delay();
data = data << 1;
}
// read ACK
SDA_HIGH(); // leave SDA HI
SDA_INPUT(); // change direction to input on SDA line
SCL_HIGH(); // clock back up
i2c_delay();
ack = SDA_READ(); // get the ACK bit
SCL_LOW();
SDA_OUTPUT(); // change direction back to output
SCL_LOW();
i2c_delay();
return ack;
}
unsigned char i2c_read(void)
{
unsigned char i, data;
SDA_HIGH(); // leave SDA HI
SDA_INPUT(); // change direction to input on SDA line
data = 0;
for(i=0; i<8; i++)
{
data = data << 1; // MSB first
SCL_HIGH(); // clock HI
i2c_delay();
if(SDA_READ()) // get the Data bit
data |= 1;
SCL_LOW(); // clock LO
i2c_delay();
}
SDA_OUTPUT(); // change direction back to output
// send ACK
SDA_LOW(); i2c_delay();
SCL_HIGH(); i2c_delay();
SCL_LOW(); i2c_delay();
SDA_HIGH();
return data;
}
unsigned char i2c_read_nack(void)
{
unsigned char i, data;
SDA_HIGH(); // leave SDA HI
SDA_INPUT(); // change direction to input on SDA line
data = 0;
for(i=0; i<8; i++)
{
data = data << 1; // MSB first
SCL_HIGH(); // clock HI
i2c_delay();
if(SDA_READ()) // get the Data bit
data |= 1;
SCL_LOW(); // clock LO
i2c_delay();
}
SDA_OUTPUT(); // change direction back to output
// send NACK
SDA_HIGH(); i2c_delay();
SCL_HIGH(); i2c_delay();
SCL_LOW(); i2c_delay();
SDA_HIGH();
return data;
}
EEPROM read/write sample (AT24C32)
#define EEP_SLAVE_ADR 0xA0
#define TWI_WRITE 0x00
#define TWI_READ 0x01
#define TWI_ACK 0
#define TWI_NACK 1
#define TWI_ERROR TWI_NACK
void eep_write(unsigned short addr, unsigned char data)
{
i2c_start();
i2c_write(EEP_SLAVE_ADR|TWI_WRITE); // slave address
i2c_write(addr>>8); // word address high
i2c_write(addr & 0xFF); // word address low
i2c_write(data);
i2c_stop();
delay_ms(6); // 5ms EEPROM write cycle time
}
unsigned char eep_read(unsigned short addr)
{
unsigned char data;
i2c_start();
i2c_write(EEP_SLAVE_ADR|TWI_WRITE); // slave address
i2c_write(addr>>8); // word address high
i2c_write(addr & 0xFF); // word address low
i2c_start();
i2c_write(EEP_SLAVE_ADR|TWI_READ); // slave address with READ
data = i2c_read_nack();
i2c_stop();
return data;
}
2004-06-14 [Á¶È¸: 32767]
|