{"id":2583,"date":"2011-05-09T18:47:31","date_gmt":"2011-05-09T22:47:31","guid":{"rendered":"http:\/\/embedded-lab.com\/blog\/?p=2583"},"modified":"2012-07-30T09:29:19","modified_gmt":"2012-07-30T13:29:19","slug":"lab-14-inter-integrated-circuit-i2c-communication","status":"publish","type":"post","link":"https:\/\/embedded-lab.com\/blog\/lab-14-inter-integrated-circuit-i2c-communication\/","title":{"rendered":"Lab 14: Inter-Integrated Circuit (I2C) communication"},"content":{"rendered":"<p>I2C (Inter-Integrated Circuit) is a short distance serial interface that requires only 2 bus lines for data transfer. It was invented by Philips in 1980&#8217;s, originally to provide easy on-board communications between a CPU and various peripheral chips in a TV set. Today, it is widely used in varieties of embedded systems to connect low speed peripherals (external EEPROMs, digital sensors, LCD drivers, etc) to the main controller. In this experiment, we will cover an overview of I2C protocol, its implementation in PIC microcontrollers, and the method of connecting single and multiple devices on a common I2C bus. We will demonstrate the technique by connecting two I2C EEPROM chips (24LC512) and an I2C compatible temperature sensor (DS1631) with PIC18F2550 microcontroller.<\/p>\n<div id=\"attachment_2607\" style=\"width: 570px\" class=\"wp-caption aligncenter\"><a href=\"http:\/\/embedded-lab.com\/blog\/wp-content\/uploads\/2011\/05\/I2C_Title.jpg\"><img loading=\"lazy\" decoding=\"async\" aria-describedby=\"caption-attachment-2607\" class=\"size-full wp-image-2607\" title=\"I2C_Title\" src=\"http:\/\/embedded-lab.com\/blog\/wp-content\/uploads\/2011\/05\/I2C_Title.jpg\" alt=\"\" width=\"560\" height=\"257\" srcset=\"https:\/\/embedded-lab.com\/blog\/wp-content\/uploads\/2011\/05\/I2C_Title.jpg 560w, https:\/\/embedded-lab.com\/blog\/wp-content\/uploads\/2011\/05\/I2C_Title-550x252.jpg 550w\" sizes=\"auto, (max-width: 560px) 100vw, 560px\" \/><\/a><p id=\"caption-attachment-2607\" class=\"wp-caption-text\">I2C devices with PICMicro<\/p><\/div>\n<p><!--more--><\/p>\n<p><strong>Theory<\/strong><\/p>\n<p>I2C bus has two lines: a <strong>serial data<\/strong> line (SDA) and a <strong>serial clock <\/strong>line (SCL). Any data sent from one device to another goes through the SDA line, whereas the SCL line provides the necessary synchronization clock for the data transfer. The devices on an I2C bus are either <strong>Masters<\/strong> or <strong>Slaves<\/strong>. Only a Master can initiate a data transfer and Slaves respond to the Master. It is possible to have multiple Masters on a common bus, but only one could be active at a time. The SCL clock line is always driven by the master.\u00a0In this tutorial, we will discuss a single master case, and our master is the PIC18F2550 microcontroller. The figure below shows a I2C bus with a single master and three slaves. Slaves can never initiate a data transfer but they can transfer data over the I2C bus, and that is always controlled by the Master.<\/p>\n<p><a href=\"http:\/\/embedded-lab.com\/blog\/wp-content\/uploads\/2011\/05\/MutipleI2C_Devices.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-medium wp-image-2584\" title=\"MutipleI2C_Devices\" src=\"http:\/\/embedded-lab.com\/blog\/wp-content\/uploads\/2011\/05\/MutipleI2C_Devices-550x347.png\" alt=\"\" width=\"550\" height=\"347\" srcset=\"https:\/\/embedded-lab.com\/blog\/wp-content\/uploads\/2011\/05\/MutipleI2C_Devices-550x347.png 550w, https:\/\/embedded-lab.com\/blog\/wp-content\/uploads\/2011\/05\/MutipleI2C_Devices.png 620w\" sizes=\"auto, (max-width: 550px) 100vw, 550px\" \/><\/a><\/p>\n<p>Both SCL and SDA lines are open drain drivers, and are therefore, connected to a positive supply voltage through pull-up resistors. This means the <em>I2C devices can only pull the line low, but they cannot drive it high<\/em>. When no device is pulling on the line, it will float high through the pull-up resistor. This is why pull-up resistors are important in I2C. The open-drain outputs of I2C devices helps to perform the wired-AND function on the bus. Data on the I2C bus can be transferred at a rate up to 100 Kbps (in standard mode), 400 Kbps (in fast mode), or up to 3.4 Mbps (in high-speed mode).<\/p>\n<p><em><strong>Start and Stop conditions<\/strong><\/em><\/p>\n<p>Prior to any transaction on the bus, a Start condition is issued by the Master device to inform all the slave devices that something is about to be transmitted on the bus. As a result, all connected slave devices will listen to the serial data line for instructions. The Start condition is issued by pulling the SDA line low followed by the SCL line. Once the data transfer is finished, the bus Master sends a Stop condition to inform other devices that it would like to release the bus. The signaling used for a Stop condition is a release of the SCL line followed by a release of the SDA line. Remember that when the lines are released, they float high because of the pull-up resistors. Thus, the Start and Stop sequences mark the beginning and end of a transaction with the slave device.<\/p>\n<div id=\"attachment_2593\" style=\"width: 493px\" class=\"wp-caption aligncenter\"><a href=\"http:\/\/embedded-lab.com\/blog\/wp-content\/uploads\/2011\/05\/I2C_StartStop.png\"><img loading=\"lazy\" decoding=\"async\" aria-describedby=\"caption-attachment-2593\" class=\"size-full wp-image-2593\" title=\"I2C_StartStop\" src=\"http:\/\/embedded-lab.com\/blog\/wp-content\/uploads\/2011\/05\/I2C_StartStop.png\" alt=\"\" width=\"483\" height=\"186\" \/><\/a><p id=\"caption-attachment-2593\" class=\"wp-caption-text\">Signaling for Start and Stop conditions<\/p><\/div>\n<div><strong><em>I2C device addressing<\/em><\/strong><\/div>\n<div><strong><em><br \/>\n<\/em><\/strong><\/div>\n<div>\n<div>Each device \u00a0connected to the bus is software\u00a0addressable by a unique 7-bit or 10-bit address. The use of 10-bit address is not very common and therefore, is not discussed here. The first byte sent after the Start condition is known as <strong>Control byte<\/strong>. The first seven bits of the control byte make up the slave address, whereas the\u00a0eighth bit (LSB) is a\u00a0data direction bit (R\/W): a \u2018zero\u2019 in the LSB of the first byte indicates that the Master will write information to a selected slave. A \u2018one\u2019 in this position indicates that the Master will read data from the slave.\u00a0For 7-bit devices, typically the first four bits are fixed,\u00a0the next three bits are set by hardware address pins (A0,\u00a0A1, and A2) that allow the user to modify the \u00a0I2C\u00a0address allowing \u00a0up to eight of the same devices to\u00a0operate on the I2C bus. These pins are held high to VCC or held low to GND. We will discuss more in the circuit section on how to setup the device address on the bus.<\/div>\n<div>\n<div id=\"attachment_2596\" style=\"width: 448px\" class=\"wp-caption aligncenter\"><a href=\"http:\/\/embedded-lab.com\/blog\/wp-content\/uploads\/2011\/05\/I2C_Address.png\"><img loading=\"lazy\" decoding=\"async\" aria-describedby=\"caption-attachment-2596\" class=\"size-full wp-image-2596\" title=\"I2C_Address\" src=\"http:\/\/embedded-lab.com\/blog\/wp-content\/uploads\/2011\/05\/I2C_Address.png\" alt=\"\" width=\"438\" height=\"216\" \/><\/a><p id=\"caption-attachment-2596\" class=\"wp-caption-text\">The control byte (first byte after the Start condition) holds the slave address<\/p><\/div>\n<\/div>\n<\/div>\n<div>\n<div>When a control byte is sent, each device in the system\u00a0compares the first seven receiving bits with its address. If they match, the device considers itself\u00a0addressed by the master as a slave-receiver or slave-transmitter, depending upon the value of the data direction bit (8th bit).<\/div>\n<\/div>\n<p><strong>Data transfer<\/strong><\/p>\n<p>Every byte put on the SDA line must be 8-bits long. The data is sent on the SDA line starting with the most significant bit (MSB) first and the SCL line produces a synchronization clock. The data on the SDA line is considered valid when SCL is high, and therefore the data must be stable during the HIGH period of the clock. The HIGH or LOW state of the data line can only change when the clock signal on the SCL line is LOW. This is how the timing of each bit works.<\/p>\n<div id=\"attachment_2594\" style=\"width: 520px\" class=\"wp-caption aligncenter\"><a href=\"http:\/\/embedded-lab.com\/blog\/wp-content\/uploads\/2011\/05\/I2C_DataValid.png\"><img loading=\"lazy\" decoding=\"async\" aria-describedby=\"caption-attachment-2594\" class=\"size-full wp-image-2594\" title=\"I2C_DataValid\" src=\"http:\/\/embedded-lab.com\/blog\/wp-content\/uploads\/2011\/05\/I2C_DataValid.png\" alt=\"\" width=\"510\" height=\"203\" \/><\/a><p id=\"caption-attachment-2594\" class=\"wp-caption-text\">Data is valid only during the High condition of SCL<\/p><\/div>\n<p>If a slave is not in a position to receive or transmit another complete byte of data until it has performed some other function, for example servicing an internal interrupt, it can hold the SCL line low to force the master into a wait state. Data transfer continues when the slave is ready for another byte of data and releases the clock line.<\/p>\n<p>A\u00a0data transfer is always terminated by a Stop condition generated by the master. However, if a master still wishes\u00a0to communicate on the bus, it can generate a <em>repeated-Start condition<\/em> and address another slave without\u00a0first generating a Stop condition.<\/p>\n<p><strong><em>Acknowledgment<\/em><\/strong><\/p>\n<p>Usually, a receiver which has been addressed is obliged to generate an acknowledge (ACK) after each byte has been received.\u00a0The acknowledge takes place after the 8th\u00a0data bit has\u00a0been transferred in any transaction. During this state\u00a0the transmitter should release the SDA bus to allow\u00a0the receiver to drive it. The receiver drives the SDA\u00a0signal low to acknowledge receipt of the byte. If the\u00a0receiver does not drive SDA low, the condition is a\u00a0no-acknowledge (NACK) and the operation is aborted. If the byte sent is the control byte (slave address + R\/W bit), then only that slave which has the matching address will respond with an acknowledge.<\/p>\n<p>Now lets discuss how these various sequences of operation takes place while the PIC18F2550 microcontroller communicates with 24LC512 EEPROM and DS1631 temperature sensor over an I2C bus. The MSSP (Master Synchronous Serial Port) module in PIC18F2550 allows I2C communication through two of its I\/O pins: RB0\/SDA (21) and RB1\/SCL (22). The functioning details of this module is not discussed here because of the use of mikroC compiler that provides library routines for I2C communication.<\/p>\n<p><strong><em>Serial EEPROM (24LC512)<\/em><\/strong><\/p>\n<p>24LC512 is an I2C compatible serial EEPROM from Microchip Technology with a capacity of 64K x 8 (512 Kbits). The pin diagram of this IC chip is shown in the circuit section. The first four bits of the 7-bit address for this device is set as &#8216;1010&#8217;. The next three bits are, however, configurable through its A0, A1, and A2 pins. For example, a 24LC512 device with A0 at logic high and A1-A2 pins grounded will have its 7-bit address as &#8216;1010001&#8217; . This scheme allows a maximum of 8 similar devices addressable on the same I2C bus.<\/p>\n<p><em>Byte Write operation<\/em><\/p>\n<p>For byte write operation, two bytes of addresses are required to select one out of 65536 locations in the EEPROM. Master provides these two address bytes after the control byte has been sent. 24LC512 responds with an acknowledge pulse after receiving each address byte. Master then sends a byte of data to be written in to the memory. Upon receipt of this data, 24LC512 sends an acknowledge pulse. \u00a0The Master then terminates the data transfer by issuing a Stop condition.<\/p>\n<div id=\"attachment_2620\" style=\"width: 570px\" class=\"wp-caption aligncenter\"><a href=\"http:\/\/embedded-lab.com\/blog\/wp-content\/uploads\/2011\/05\/WriteByte.png\"><img loading=\"lazy\" decoding=\"async\" aria-describedby=\"caption-attachment-2620\" class=\"size-full wp-image-2620\" title=\"WriteByte\" src=\"http:\/\/embedded-lab.com\/blog\/wp-content\/uploads\/2011\/05\/WriteByte.png\" alt=\"\" width=\"560\" height=\"146\" srcset=\"https:\/\/embedded-lab.com\/blog\/wp-content\/uploads\/2011\/05\/WriteByte.png 560w, https:\/\/embedded-lab.com\/blog\/wp-content\/uploads\/2011\/05\/WriteByte-550x143.png 550w\" sizes=\"auto, (max-width: 560px) 100vw, 560px\" \/><\/a><p id=\"caption-attachment-2620\" class=\"wp-caption-text\">Byte write operation<\/p><\/div>\n<p><em>Page Write operation<\/em><\/p>\n<p>To minimize write cycle time, 24LC512 offers Page write feature, which allows simultaneous writing of up to 128 contiguous bytes. A page write is initiated in the same way as a byte write, but instead of generating a Stop\u00a0condition, the master transmits up to 127 additional\u00a0bytes, which are temporarily stored in the on-chip page\u00a0buffer and will be written into memory after the master\u00a0has transmitted a Stop condition. Please read the datasheet of 24LC512 to learn more about the Page write operation.<\/p>\n<div id=\"attachment_2621\" style=\"width: 570px\" class=\"wp-caption aligncenter\"><a href=\"http:\/\/embedded-lab.com\/blog\/wp-content\/uploads\/2011\/05\/WritePage.png\"><img loading=\"lazy\" decoding=\"async\" aria-describedby=\"caption-attachment-2621\" class=\"size-full wp-image-2621\" title=\"WritePage\" src=\"http:\/\/embedded-lab.com\/blog\/wp-content\/uploads\/2011\/05\/WritePage.png\" alt=\"\" width=\"560\" height=\"119\" srcset=\"https:\/\/embedded-lab.com\/blog\/wp-content\/uploads\/2011\/05\/WritePage.png 560w, https:\/\/embedded-lab.com\/blog\/wp-content\/uploads\/2011\/05\/WritePage-550x116.png 550w\" sizes=\"auto, (max-width: 560px) 100vw, 560px\" \/><\/a><p id=\"caption-attachment-2621\" class=\"wp-caption-text\">Page write operation<\/p><\/div>\n<p><em>Read operation<\/em><\/p>\n<p>Read operations are initiated in the same way as write\u00a0operations with the exception that the R\/W bit of the\u00a0control byte is set to \u20181\u2019. 24LC512 allows\u00a0three basic types of\u00a0read operations: <em>current address<\/em> read, <em>random<\/em> read\u00a0and <em>sequential<\/em> read.<\/p>\n<p>Internally, the EEPROM contains an address counter that maintains the address of the last word accessed, incremented by \u20181\u2019. Therefore, if the previous read\u00a0access was to address \u2018n\u2019, the\u00a0next current address read operation would access data\u00a0from address n + 1.\u00a0Upon receipt of the control byte with R\/W bit set to \u20181\u2019,\u00a0the EEPROM issues an acknowledge and transmits the current address data byte.\u00a0The master will not acknowledge the\u00a0transfer but does generate a following Stop condition and the\u00a0EEPROM discontinues transmission.<\/p>\n<div id=\"attachment_2622\" style=\"width: 422px\" class=\"wp-caption aligncenter\"><a href=\"http:\/\/embedded-lab.com\/blog\/wp-content\/uploads\/2011\/05\/CurrentRead.png\"><img loading=\"lazy\" decoding=\"async\" aria-describedby=\"caption-attachment-2622\" class=\"size-full wp-image-2622\" title=\"CurrentRead\" src=\"http:\/\/embedded-lab.com\/blog\/wp-content\/uploads\/2011\/05\/CurrentRead.png\" alt=\"\" width=\"412\" height=\"193\" \/><\/a><p id=\"caption-attachment-2622\" class=\"wp-caption-text\">Current address read signal<\/p><\/div>\n<p>Random read operations allow the master to access\u00a0any memory location in a random manner. To perform\u00a0this type of read operation, first the word address must\u00a0be set. This is done by sending the word address to 24LC512 as part of a write operation (R\/W bit set to\u00a0\u20180\u2019). After the word address is sent, the master\u00a0generates a repeated-Start condition following the acknowledge.\u00a0This terminates the write operation. Then, the master issues\u00a0the control byte again but with the R\/W bit set to a one.\u00a0The EEPROM will then issue an acknowledge and\u00a0transmit the 8-bit data word. The master will not\u00a0acknowledge the transfer but does generate a Stop\u00a0condition which causes the EEPROM to discontinue\u00a0transmission.<\/p>\n<div id=\"attachment_2624\" style=\"width: 570px\" class=\"wp-caption aligncenter\"><a href=\"http:\/\/embedded-lab.com\/blog\/wp-content\/uploads\/2011\/05\/RandomRead.png\"><img loading=\"lazy\" decoding=\"async\" aria-describedby=\"caption-attachment-2624\" class=\"size-full wp-image-2624\" title=\"RandomRead\" src=\"http:\/\/embedded-lab.com\/blog\/wp-content\/uploads\/2011\/05\/RandomRead.png\" alt=\"\" width=\"560\" height=\"167\" srcset=\"https:\/\/embedded-lab.com\/blog\/wp-content\/uploads\/2011\/05\/RandomRead.png 560w, https:\/\/embedded-lab.com\/blog\/wp-content\/uploads\/2011\/05\/RandomRead-550x164.png 550w\" sizes=\"auto, (max-width: 560px) 100vw, 560px\" \/><\/a><p id=\"caption-attachment-2624\" class=\"wp-caption-text\">Random read operation<\/p><\/div>\n<p>Sequential reads are initiated by either a current address read or a random address read. After receiving the first byte from 24LC512,\u00a0the master issues an acknowledge instead of\u00a0the Stop condition used in a current address or random\u00a0read. This acknowledge directs 24LC512 to\u00a0transmit the next sequentially addressed 8-bit word. Following the final byte transmitted to the\u00a0master, the master will NOT generate an acknowledge,\u00a0but will generate a Stop condition.<\/p>\n<div id=\"attachment_2623\" style=\"width: 570px\" class=\"wp-caption aligncenter\"><a href=\"http:\/\/embedded-lab.com\/blog\/wp-content\/uploads\/2011\/05\/SequentialRead.png\"><img loading=\"lazy\" decoding=\"async\" aria-describedby=\"caption-attachment-2623\" class=\"size-full wp-image-2623\" title=\"SequentialRead\" src=\"http:\/\/embedded-lab.com\/blog\/wp-content\/uploads\/2011\/05\/SequentialRead.png\" alt=\"\" width=\"560\" height=\"141\" srcset=\"https:\/\/embedded-lab.com\/blog\/wp-content\/uploads\/2011\/05\/SequentialRead.png 560w, https:\/\/embedded-lab.com\/blog\/wp-content\/uploads\/2011\/05\/SequentialRead-550x138.png 550w\" sizes=\"auto, (max-width: 560px) 100vw, 560px\" \/><\/a><p id=\"caption-attachment-2623\" class=\"wp-caption-text\">Sequential read operation<\/p><\/div>\n<p><em>Write Protect (WP)<\/em><\/p>\n<p>Pin number 7 of 24LC512 is a hardware Write Protect input. If this pin is tied to Vcc, write operations are inhibited but read operations are not affected. In our experiment, we will ground this pin.<\/p>\n<p><strong><em>I2C temperature sensor (DS1631) <\/em><\/strong><\/p>\n<p>DS1631 is a digital thermometer manufactured by Dallas Semiconductor (now MAXIM) that provides 9, 10, 11, or 12-bit (user selectable) temperature measurements over a -55 \u00b0C\u00a0to 125 \u00b0C. The default resolution at power-up is 12-bit, corresponding to the temperature increment of 0.0625\u00a0\u00a0\u00b0C.\u00a0The communication with DS1631 is achieved through I2C interface and three address pins (A0, A1, and A2) allow up to 8 devices to be multi-dropped on the same 2-wire bus (see the pin diagram in the circuit section). The 7-bit address of each slave is 1 0 0 1 A2 A1 A0, where A0, A1, and A2 are user selectable through the corresponding input pins.<\/p>\n<p><em>Temperature measurement<\/em><\/p>\n<p>I recommend to read the datasheet of DS1631 for details on its architecture and temperature conversion process. Here, I am describing only the one-shot mode of temperature conversion. Suppose, the device is just powered up, and the resolution of conversion is set to 12-bit. In one-shot mode, the DS1631 sensor starts converting temperature into 12-bit digital word after receiving a command byte, 51h, from the Master. This is known as the Start Convert T command. After the conversion, the digital temperature is stored as a 16-bit two&#8217;s complement number in to its two-byte temperature register: TH and TL (see below). The Sign bit (S) indicates whether the temperature is positive (S=0) or negative (S=1).<\/p>\n<div id=\"attachment_2625\" style=\"width: 570px\" class=\"wp-caption aligncenter\"><a href=\"http:\/\/embedded-lab.com\/blog\/wp-content\/uploads\/2011\/05\/TempRegister.png\"><img loading=\"lazy\" decoding=\"async\" aria-describedby=\"caption-attachment-2625\" class=\"size-full wp-image-2625\" title=\"TempRegister\" src=\"http:\/\/embedded-lab.com\/blog\/wp-content\/uploads\/2011\/05\/TempRegister.png\" alt=\"\" width=\"560\" height=\"113\" srcset=\"https:\/\/embedded-lab.com\/blog\/wp-content\/uploads\/2011\/05\/TempRegister.png 560w, https:\/\/embedded-lab.com\/blog\/wp-content\/uploads\/2011\/05\/TempRegister-550x110.png 550w\" sizes=\"auto, (max-width: 560px) 100vw, 560px\" \/><\/a><p id=\"caption-attachment-2625\" class=\"wp-caption-text\">Temperature register inside DS1631<\/p><\/div>\n<div id=\"attachment_2626\" style=\"width: 570px\" class=\"wp-caption aligncenter\"><a href=\"http:\/\/embedded-lab.com\/blog\/wp-content\/uploads\/2011\/05\/StartConvertT.png\"><img loading=\"lazy\" decoding=\"async\" aria-describedby=\"caption-attachment-2626\" class=\"size-full wp-image-2626\" title=\"StartConvertT\" src=\"http:\/\/embedded-lab.com\/blog\/wp-content\/uploads\/2011\/05\/StartConvertT.png\" alt=\"\" width=\"560\" height=\"162\" srcset=\"https:\/\/embedded-lab.com\/blog\/wp-content\/uploads\/2011\/05\/StartConvertT.png 560w, https:\/\/embedded-lab.com\/blog\/wp-content\/uploads\/2011\/05\/StartConvertT-550x159.png 550w\" sizes=\"auto, (max-width: 560px) 100vw, 560px\" \/><\/a><p id=\"caption-attachment-2626\" class=\"wp-caption-text\">Issuing a Start Convert T command<\/p><\/div>\n<p>The master can read the temperature data from DS1631 by sending a Read Temperature (AAh) command.\u00a0After\u00a0receiving an ACK in response to the command, the master must generate a repeated Start followed by\u00a0a control byte with the same slave address as the first control byte. However, this time the R\/W bit must\u00a0be a 1, which tells DS1631 that a \u201cread\u201d is being performed.\u00a0DS1631 sends an ACK in response to this control byte, and it begins transmitting the\u00a0requested data on the next clock cycle.\u00a0For two byte reads (TH and TL registers), the master must respond to the first data byte\u00a0with an ACK and to the second byte with a NACK followed by a STOP. If only the most significant byte\u00a0of data is needed, the master can issue a NACK followed by a STOP after reading the first data byte.<\/p>\n<div id=\"attachment_2628\" style=\"width: 560px\" class=\"wp-caption aligncenter\"><a href=\"http:\/\/embedded-lab.com\/blog\/wp-content\/uploads\/2011\/05\/ReadTHTL.png\"><img loading=\"lazy\" decoding=\"async\" aria-describedby=\"caption-attachment-2628\" class=\"size-medium wp-image-2628\" title=\"ReadTHTL\" src=\"http:\/\/embedded-lab.com\/blog\/wp-content\/uploads\/2011\/05\/ReadTHTL-550x201.png\" alt=\"\" width=\"550\" height=\"201\" srcset=\"https:\/\/embedded-lab.com\/blog\/wp-content\/uploads\/2011\/05\/ReadTHTL-550x201.png 550w, https:\/\/embedded-lab.com\/blog\/wp-content\/uploads\/2011\/05\/ReadTHTL.png 735w\" sizes=\"auto, (max-width: 550px) 100vw, 550px\" \/><\/a><p id=\"caption-attachment-2628\" class=\"wp-caption-text\">Reading 16-bit temperature data from DS1631<\/p><\/div>\n<p><strong>Circuit setup<\/strong><\/p>\n<p>The circuit diagram for I2C experiment is shown below. Two serial EEPROMs (24LC512) and a DS1631 temperature sensor are connected on a common I2C bus. The address conflict between the two EEPROMs is avoided by connecting one&#8217;s A0 pin to Gnd and others to Vcc. The 7-bit addresses of all three I2C devices are shown in the diagram. The two 10 K resistors are the pull-up resistors for the I2C bus lines. The SDA and SCL lines go to RB0 and RB1 pins of PIC18F2550, respectively. I am using the <strong><a href=\"http:\/\/embedded-lab.com\/blog\/?p=2321\" target=\"_blank\">StartUSB for PIC<\/a><\/strong> board again for PIC18F2550.<\/p>\n<div id=\"attachment_2600\" style=\"width: 560px\" class=\"wp-caption aligncenter\"><a href=\"http:\/\/embedded-lab.com\/blog\/wp-content\/uploads\/2011\/05\/Ckt_I2C.png\"><img loading=\"lazy\" decoding=\"async\" aria-describedby=\"caption-attachment-2600\" class=\"size-medium wp-image-2600\" title=\"Ckt_I2C\" src=\"http:\/\/embedded-lab.com\/blog\/wp-content\/uploads\/2011\/05\/Ckt_I2C-550x420.png\" alt=\"\" width=\"550\" height=\"420\" srcset=\"https:\/\/embedded-lab.com\/blog\/wp-content\/uploads\/2011\/05\/Ckt_I2C-550x420.png 550w, https:\/\/embedded-lab.com\/blog\/wp-content\/uploads\/2011\/05\/Ckt_I2C.png 733w\" sizes=\"auto, (max-width: 550px) 100vw, 550px\" \/><\/a><p id=\"caption-attachment-2600\" class=\"wp-caption-text\">Circuit diagram for connecting EEPROMs and Temp. sensor<\/p><\/div>\n<p>A standard 16&#215;2 character LCD is also used in the circuit to display the I2C Read\/Write operations. The microcontroller pins used to drive the LCD are shown below.<\/p>\n<div id=\"attachment_2774\" style=\"width: 560px\" class=\"wp-caption aligncenter\"><a href=\"http:\/\/embedded-lab.com\/blog\/wp-content\/uploads\/2011\/05\/I2C_CktNew.jpg\"><img loading=\"lazy\" decoding=\"async\" aria-describedby=\"caption-attachment-2774\" class=\"size-medium wp-image-2774\" title=\"I2C_CktNew\" src=\"http:\/\/embedded-lab.com\/blog\/wp-content\/uploads\/2011\/05\/I2C_CktNew-550x475.jpg\" alt=\"\" width=\"550\" height=\"475\" srcset=\"https:\/\/embedded-lab.com\/blog\/wp-content\/uploads\/2011\/05\/I2C_CktNew-550x475.jpg 550w, https:\/\/embedded-lab.com\/blog\/wp-content\/uploads\/2011\/05\/I2C_CktNew.jpg 668w\" sizes=\"auto, (max-width: 550px) 100vw, 550px\" \/><\/a><p id=\"caption-attachment-2774\" class=\"wp-caption-text\">I2C bus and LCD connections to PIC18F2550<\/p><\/div>\n<div id=\"attachment_2606\" style=\"width: 570px\" class=\"wp-caption aligncenter\"><a href=\"http:\/\/embedded-lab.com\/blog\/wp-content\/uploads\/2011\/05\/I2C_Setup.jpg\"><img loading=\"lazy\" decoding=\"async\" aria-describedby=\"caption-attachment-2606\" class=\"size-full wp-image-2606\" title=\"I2C_Setup\" src=\"http:\/\/embedded-lab.com\/blog\/wp-content\/uploads\/2011\/05\/I2C_Setup.jpg\" alt=\"\" width=\"560\" height=\"252\" srcset=\"https:\/\/embedded-lab.com\/blog\/wp-content\/uploads\/2011\/05\/I2C_Setup.jpg 560w, https:\/\/embedded-lab.com\/blog\/wp-content\/uploads\/2011\/05\/I2C_Setup-550x247.jpg 550w\" sizes=\"auto, (max-width: 560px) 100vw, 560px\" \/><\/a><p id=\"caption-attachment-2606\" class=\"wp-caption-text\">Circuit setup on breadboard<\/p><\/div>\n<p><strong>Software<\/strong><\/p>\n<p>We will be writing an application software for testing the I2C communication between the PIC18F2550 microcontroller and the three devices that are multi-dropped on a common I2C bus. The program will first check the presence of all three devices on the bus, and then sends a temperature conversion command to DS1631. The two-byte temperature will be then read and stored in to the two EEPROMs (higher byte in one EEPROM and lower byte in the other, starting at location 0). After five temperature samples are recorded, they will be read sequentially from EEPROM locations, converted in to actual temperature units (\u00b0C) and displayed on LCD screen.<\/p>\n<p>The mikroC Pro for PIC compiler offers the library routines for handling I2C communication, which are briefly described here.<\/p>\n<p><strong>void<\/strong> I2C1_Init(<strong>const<\/strong> <strong>unsigned long<\/strong> clock) :- The first thing we need to do is the initialization of the MSSP module for I2C communication. This can be done with <em>I2C1_Init<\/em> function. e.g. <em>I2C_Init(100000)<\/em> will configure the MSSP module for I2C communication at 100 KHz.<\/p>\n<p><strong>unsigned short<\/strong> I2C1_Start(<strong>void<\/strong>) :- Determines if <acronym title=\"Inter-Integrated Circuit\">I\u00b2C<\/acronym> bus is free and issues Start signal. It returns zero if there is no error.<\/p>\n<p><strong>void<\/strong> I2C1_Repeated_Start(<strong>void<\/strong>) :- Issues a repeated-start condotion.<\/p>\n<p><strong>unsigned short<\/strong> I2C1_Is_Idle(<strong>void<\/strong>) :- Checks if I2C bus is free. If it is free, it returns 1, otherwise 0.<\/p>\n<p><strong>unsigned short<\/strong> I2C1_Rd(<strong>unsigned short<\/strong> ack) :- Reads one byte from the slave, and sends <em>NACK<\/em> signal if parameter ack is 0, otherwise it sends <em>acknowledge<\/em>. For example, if the microcontroller needs to read two-byte temperature readings from DS1631, it should use I2C1_Rd(1) to read the first byte and I2C1_Rd(0) for the second byte.<\/p>\n<p><strong>unsigned short<\/strong> I2C1_Wr(<strong>unsigned short<\/strong> data) :- Sends data byte via I2C bus. It returns zero if there is no error.<\/p>\n<p><strong>void<\/strong> I2C1_Stop(<strong>void<\/strong>) :- Issues a Stop condition.<\/p>\n<p>In our test program, PIC18F2550 will first check the availability of the three devices on the bus. It is done by sending a device address for each and if it is acknowledged, that means the device is present. A mikroC routine to check the presence of a device on the I2C bus is given below.<\/p>\n<pre>void check_device(unsigned short dev_address){\r\n I2C1_Start();\r\n if (I2C1_Wr(dev_address)){\r\n  Lcd_Out(2,1,\"Device not found\");\r\n }\r\n else Lcd_Out(2,1,\"Device is OK\");\r\n I2C1_Stop();\r\n}<\/pre>\n<p>The following program allows PIC18F2550 to send a Start Convert T command to DS1631, then wait for 750 ms until the 12-bit temperature conversion is done, and finally receive the two-byte temperature reading.<\/p>\n<pre>\/\/ Read temperature\r\n I2C1_Start();\r\n I2C1_Wr(DS1631);\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \/\/ Send device address\r\n I2C1_Wr(0x51);\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \/\/ Start Convert Temp command\r\n I2C1_Stop();\r\n Delay_ms(750);\r\n I2C1_Start();\r\n I2C1_Wr(DS1631);\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \/\/ DS1631 Address again\r\n I2C1_Wr(0xAA);\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \/\/ Read Temperature command\r\n I2C1_Repeated_Start();\r\n I2C1_Wr(DS1631+1);\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \/\/ Address with Read\r\n MS_Byte = I2C1_Rd(1);\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \/\/ Read MSB and send ACK\r\n LS_Byte = I2C1_Rd(0);\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \/\/ Read LSB and send NAK\r\n I2C1_Stop();<\/pre>\n<p>You can see while reading the last byte, PIC18F2550 does not need to send an acknowledge pulse.<\/p>\n<p>The following two routines will perform byte read and write operations with the two EEPROMs.<\/p>\n<pre>\/\/--------------- Reads data from 24LC512 EEPROM - single location\r\nunsigned short EEPROM_ReadByte(unsigned short EEPROM_Select, unsigned short rAddress) {\r\n unsigned short rAddrH, rAddrL, result;\r\n rAddrH = 0;\r\n rAddrL = rAddress;\r\n I2C1_Start();\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \/\/ issue I2C1 start signal\r\n I2C1_Wr(EEPROM_Select);\u00a0\u00a0\u00a0 \/\/ send byte via I2C1\u00a0 (device address + W)\r\n I2C1_Wr(rAddrH);\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \/\/ send Higher address byte\r\n I2C1_Wr(rAddrL);\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \/\/ send Lower address byte\r\n I2C1_Repeated_Start();\u00a0\u00a0\u00a0 \/\/ issue I2C1 signal repeated start\r\n I2C1_Wr(EEPROM_Select+1);\u00a0\u00a0\u00a0\/\/ send byte (device address + R)\r\n result = I2C1_Rd(0u);\u00a0\u00a0\u00a0\u00a0 \/\/ Read the data (NO acknowledge)\r\n while (!I2C1_Is_Idle())\r\n asm nop;\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \/\/ Wait for the read cycle to finish\r\n I2C1_Stop();\r\n return result;\r\n}<\/pre>\n<pre>\/\/--------------- Writes data to 24LC512 EEPROM - single location\r\nvoid EEPROM_WriteByte(unsigned DeviceSelect, unsigned short wAddress, unsigned short wData) {\r\n unsigned short wAddrH, wAddrL;\r\n wAddrH = 0;\r\n wAddrL = wAddress;\r\n I2C1_Start();\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \/\/ issue I2C1 start signal\r\n I2C1_Wr(DeviceSelect);\u00a0\u00a0 \/\/ send control byte\r\n I2C1_Wr(wAddrH);\u00a0\u00a0\u00a0\u00a0 \/\/ send higher address byte\r\n I2C1_Wr(wAddrL);\u00a0\u00a0\u00a0\u00a0 \/\/ send lower address byte\r\n I2C1_Wr(wData);\u00a0\u00a0\u00a0\u00a0\u00a0 \/\/ send data to be written\r\n I2C1_Stop();\r\n}<\/pre>\n<p><a href=\"http:\/\/embedded-lab.com\/uploads\/HexFiles\/PIC18F2550\/I2C.zip\">Download mikroC source and hex files<\/a><\/p>\n<p><strong>Output<\/strong><\/p>\n<p>The following pictures show the sequence of operations performed while executing the I2C test software.<\/p>\n<div id=\"attachment_2608\" style=\"width: 570px\" class=\"wp-caption aligncenter\"><a href=\"http:\/\/embedded-lab.com\/blog\/wp-content\/uploads\/2011\/05\/I2CDevices.jpg\"><img loading=\"lazy\" decoding=\"async\" aria-describedby=\"caption-attachment-2608\" class=\"size-full wp-image-2608\" title=\"I2CDevices\" src=\"http:\/\/embedded-lab.com\/blog\/wp-content\/uploads\/2011\/05\/I2CDevices.jpg\" alt=\"\" width=\"560\" height=\"247\" srcset=\"https:\/\/embedded-lab.com\/blog\/wp-content\/uploads\/2011\/05\/I2CDevices.jpg 560w, https:\/\/embedded-lab.com\/blog\/wp-content\/uploads\/2011\/05\/I2CDevices-550x242.jpg 550w\" sizes=\"auto, (max-width: 560px) 100vw, 560px\" \/><\/a><p id=\"caption-attachment-2608\" class=\"wp-caption-text\">Start up message<\/p><\/div>\n<div id=\"attachment_2604\" style=\"width: 570px\" class=\"wp-caption aligncenter\"><a href=\"http:\/\/embedded-lab.com\/blog\/wp-content\/uploads\/2011\/05\/EEPROM1OK.jpg\"><img loading=\"lazy\" decoding=\"async\" aria-describedby=\"caption-attachment-2604\" class=\"size-full wp-image-2604\" title=\"EEPROM1OK\" src=\"http:\/\/embedded-lab.com\/blog\/wp-content\/uploads\/2011\/05\/EEPROM1OK.jpg\" alt=\"\" width=\"560\" height=\"288\" srcset=\"https:\/\/embedded-lab.com\/blog\/wp-content\/uploads\/2011\/05\/EEPROM1OK.jpg 560w, https:\/\/embedded-lab.com\/blog\/wp-content\/uploads\/2011\/05\/EEPROM1OK-550x282.jpg 550w\" sizes=\"auto, (max-width: 560px) 100vw, 560px\" \/><\/a><p id=\"caption-attachment-2604\" class=\"wp-caption-text\">Testing EEPROM1<\/p><\/div>\n<div id=\"attachment_2605\" style=\"width: 570px\" class=\"wp-caption aligncenter\"><a href=\"http:\/\/embedded-lab.com\/blog\/wp-content\/uploads\/2011\/05\/EEPROM2OK.jpg\"><img loading=\"lazy\" decoding=\"async\" aria-describedby=\"caption-attachment-2605\" class=\"size-full wp-image-2605\" title=\"EEPROM2OK\" src=\"http:\/\/embedded-lab.com\/blog\/wp-content\/uploads\/2011\/05\/EEPROM2OK.jpg\" alt=\"\" width=\"560\" height=\"229\" srcset=\"https:\/\/embedded-lab.com\/blog\/wp-content\/uploads\/2011\/05\/EEPROM2OK.jpg 560w, https:\/\/embedded-lab.com\/blog\/wp-content\/uploads\/2011\/05\/EEPROM2OK-550x224.jpg 550w\" sizes=\"auto, (max-width: 560px) 100vw, 560px\" \/><\/a><p id=\"caption-attachment-2605\" class=\"wp-caption-text\">Testing EEPROM2<\/p><\/div>\n<div id=\"attachment_2603\" style=\"width: 570px\" class=\"wp-caption aligncenter\"><a href=\"http:\/\/embedded-lab.com\/blog\/wp-content\/uploads\/2011\/05\/DS1631OK.jpg\"><img loading=\"lazy\" decoding=\"async\" aria-describedby=\"caption-attachment-2603\" class=\"size-full wp-image-2603\" title=\"DS1631OK\" src=\"http:\/\/embedded-lab.com\/blog\/wp-content\/uploads\/2011\/05\/DS1631OK.jpg\" alt=\"\" width=\"560\" height=\"220\" srcset=\"https:\/\/embedded-lab.com\/blog\/wp-content\/uploads\/2011\/05\/DS1631OK.jpg 560w, https:\/\/embedded-lab.com\/blog\/wp-content\/uploads\/2011\/05\/DS1631OK-550x216.jpg 550w\" sizes=\"auto, (max-width: 560px) 100vw, 560px\" \/><\/a><p id=\"caption-attachment-2603\" class=\"wp-caption-text\">Testing DS1631 temperature sensor<\/p><\/div>\n<div id=\"attachment_2602\" style=\"width: 570px\" class=\"wp-caption aligncenter\"><a href=\"http:\/\/embedded-lab.com\/blog\/wp-content\/uploads\/2011\/05\/DevNotFound.jpg\"><img loading=\"lazy\" decoding=\"async\" aria-describedby=\"caption-attachment-2602\" class=\"size-full wp-image-2602\" title=\"DevNotFound\" src=\"http:\/\/embedded-lab.com\/blog\/wp-content\/uploads\/2011\/05\/DevNotFound.jpg\" alt=\"\" width=\"560\" height=\"220\" srcset=\"https:\/\/embedded-lab.com\/blog\/wp-content\/uploads\/2011\/05\/DevNotFound.jpg 560w, https:\/\/embedded-lab.com\/blog\/wp-content\/uploads\/2011\/05\/DevNotFound-550x216.jpg 550w\" sizes=\"auto, (max-width: 560px) 100vw, 560px\" \/><\/a><p id=\"caption-attachment-2602\" class=\"wp-caption-text\">DS1631 taken out from the bus<\/p><\/div>\n<div id=\"attachment_2612\" style=\"width: 570px\" class=\"wp-caption aligncenter\"><a href=\"http:\/\/embedded-lab.com\/blog\/wp-content\/uploads\/2011\/05\/ReadingTemp.jpg\"><img loading=\"lazy\" decoding=\"async\" aria-describedby=\"caption-attachment-2612\" class=\"size-full wp-image-2612\" title=\"ReadingTemp\" src=\"http:\/\/embedded-lab.com\/blog\/wp-content\/uploads\/2011\/05\/ReadingTemp.jpg\" alt=\"\" width=\"560\" height=\"203\" srcset=\"https:\/\/embedded-lab.com\/blog\/wp-content\/uploads\/2011\/05\/ReadingTemp.jpg 560w, https:\/\/embedded-lab.com\/blog\/wp-content\/uploads\/2011\/05\/ReadingTemp-550x199.jpg 550w\" sizes=\"auto, (max-width: 560px) 100vw, 560px\" \/><\/a><p id=\"caption-attachment-2612\" class=\"wp-caption-text\">Reading temperature from DS1631<\/p><\/div>\n<div id=\"attachment_2610\" style=\"width: 570px\" class=\"wp-caption aligncenter\"><a href=\"http:\/\/embedded-lab.com\/blog\/wp-content\/uploads\/2011\/05\/MSByte.jpg\"><img loading=\"lazy\" decoding=\"async\" aria-describedby=\"caption-attachment-2610\" class=\"size-full wp-image-2610\" title=\"MSByte\" src=\"http:\/\/embedded-lab.com\/blog\/wp-content\/uploads\/2011\/05\/MSByte.jpg\" alt=\"\" width=\"560\" height=\"218\" srcset=\"https:\/\/embedded-lab.com\/blog\/wp-content\/uploads\/2011\/05\/MSByte.jpg 560w, https:\/\/embedded-lab.com\/blog\/wp-content\/uploads\/2011\/05\/MSByte-550x214.jpg 550w\" sizes=\"auto, (max-width: 560px) 100vw, 560px\" \/><\/a><p id=\"caption-attachment-2610\" class=\"wp-caption-text\">Writing temperature MS Byte to EEPROM1<\/p><\/div>\n<div id=\"attachment_2609\" style=\"width: 570px\" class=\"wp-caption aligncenter\"><a href=\"http:\/\/embedded-lab.com\/blog\/wp-content\/uploads\/2011\/05\/LSByte.jpg\"><img loading=\"lazy\" decoding=\"async\" aria-describedby=\"caption-attachment-2609\" class=\"size-full wp-image-2609\" title=\"LSByte\" src=\"http:\/\/embedded-lab.com\/blog\/wp-content\/uploads\/2011\/05\/LSByte.jpg\" alt=\"\" width=\"560\" height=\"228\" srcset=\"https:\/\/embedded-lab.com\/blog\/wp-content\/uploads\/2011\/05\/LSByte.jpg 560w, https:\/\/embedded-lab.com\/blog\/wp-content\/uploads\/2011\/05\/LSByte-550x223.jpg 550w\" sizes=\"auto, (max-width: 560px) 100vw, 560px\" \/><\/a><p id=\"caption-attachment-2609\" class=\"wp-caption-text\">Writing temperature LS Byte to EEPROM2<\/p><\/div>\n<div id=\"attachment_2611\" style=\"width: 570px\" class=\"wp-caption aligncenter\"><a href=\"http:\/\/embedded-lab.com\/blog\/wp-content\/uploads\/2011\/05\/ReadingEEPROM.jpg\"><img loading=\"lazy\" decoding=\"async\" aria-describedby=\"caption-attachment-2611\" class=\"size-full wp-image-2611\" title=\"ReadingEEPROM\" src=\"http:\/\/embedded-lab.com\/blog\/wp-content\/uploads\/2011\/05\/ReadingEEPROM.jpg\" alt=\"\" width=\"560\" height=\"212\" srcset=\"https:\/\/embedded-lab.com\/blog\/wp-content\/uploads\/2011\/05\/ReadingEEPROM.jpg 560w, https:\/\/embedded-lab.com\/blog\/wp-content\/uploads\/2011\/05\/ReadingEEPROM-550x208.jpg 550w\" sizes=\"auto, (max-width: 560px) 100vw, 560px\" \/><\/a><p id=\"caption-attachment-2611\" class=\"wp-caption-text\">Reading recorded samples<\/p><\/div>\n<div id=\"attachment_2613\" style=\"width: 570px\" class=\"wp-caption aligncenter\"><a href=\"http:\/\/embedded-lab.com\/blog\/wp-content\/uploads\/2011\/05\/Sample1.jpg\"><img loading=\"lazy\" decoding=\"async\" aria-describedby=\"caption-attachment-2613\" class=\"size-full wp-image-2613\" title=\"Sample1\" src=\"http:\/\/embedded-lab.com\/blog\/wp-content\/uploads\/2011\/05\/Sample1.jpg\" alt=\"\" width=\"560\" height=\"234\" srcset=\"https:\/\/embedded-lab.com\/blog\/wp-content\/uploads\/2011\/05\/Sample1.jpg 560w, https:\/\/embedded-lab.com\/blog\/wp-content\/uploads\/2011\/05\/Sample1-550x229.jpg 550w\" sizes=\"auto, (max-width: 560px) 100vw, 560px\" \/><\/a><p id=\"caption-attachment-2613\" class=\"wp-caption-text\">First temperature sample<\/p><\/div>\n<div id=\"attachment_2614\" style=\"width: 570px\" class=\"wp-caption aligncenter\"><a href=\"http:\/\/embedded-lab.com\/blog\/wp-content\/uploads\/2011\/05\/Sample5.jpg\"><img loading=\"lazy\" decoding=\"async\" aria-describedby=\"caption-attachment-2614\" class=\"size-full wp-image-2614\" title=\"Sample5\" src=\"http:\/\/embedded-lab.com\/blog\/wp-content\/uploads\/2011\/05\/Sample5.jpg\" alt=\"\" width=\"560\" height=\"222\" srcset=\"https:\/\/embedded-lab.com\/blog\/wp-content\/uploads\/2011\/05\/Sample5.jpg 560w, https:\/\/embedded-lab.com\/blog\/wp-content\/uploads\/2011\/05\/Sample5-550x218.jpg 550w\" sizes=\"auto, (max-width: 560px) 100vw, 560px\" \/><\/a><p id=\"caption-attachment-2614\" class=\"wp-caption-text\">Fifth sample<\/p><\/div>\n<p><strong>Conclusion<\/strong><\/p>\n<p>In this tutorial, we briefly looked at what I2C is  and how it is used to communicate data to and from a PIC Microcontroller  and I2C compatible slave devices. We explored the Read, Write, and addressing schemes for multiple devices on a common I2C bus, and its implementation using mikroC Pro for PIC compiler. I2C has become so popular in embedded world that there are hundreds of I2C compatible devices  available in market in the form of ADC, DAC, SRAM, I\/O expander,  humidity sensor, etc. Now we understand how this protocol works, it&#8217;s time to play with these other devices.<\/p>\n<p><strong>References<\/strong><\/p>\n<ul>\n<li><a href=\"http:\/\/ww1.microchip.com\/downloads\/en\/devicedoc\/i2c.pdf\" target=\"_blank\">I2C Master mode<\/a> from Microchip<\/li>\n<li><a href=\"http:\/\/www.nxp.com\/documents\/application_note\/AN10216.pdf\" target=\"_blank\">I2C Manual<\/a> from Philips<\/li>\n<li>Datasheets of 24LC512 (Microchip) and DS1631 (MAXIM)<\/li>\n<\/ul>\n<p>Thanks to <em>Jonathan Dillon<\/em> (Microchip) for providing free samples of 24LC512.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>I2C (Inter-Integrated Circuit) is a short distance serial interface that requires only 2 bus lines for data transfer. It was invented by Philips in 1980&#8217;s, originally to provide easy on-board communications between a CPU and various peripheral chips in a TV set. Today, it is widely used in varieties of embedded systems to connect low speed peripherals (external EEPROMs, digital sensors, LCD drivers, etc) to the main controller. In this experiment, we will cover an overview of I2C protocol, its implementation in PIC microcontrollers, and the method of connecting single and multiple devices on a common I2C bus. We will<\/p>\n","protected":false},"author":1,"featured_media":2584,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[38,105,183],"tags":[269,268,266,270,247,267,259],"class_list":["post-2583","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-pic-tutorials","category-pic18f","category-tips-and-tricks","tag-24lc512","tag-ds1631","tag-i2c-protocol","tag-microchip","tag-pic18f2550","tag-serial-eeprom","tag-startusb-for-pic"],"_links":{"self":[{"href":"https:\/\/embedded-lab.com\/blog\/wp-json\/wp\/v2\/posts\/2583","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/embedded-lab.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/embedded-lab.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/embedded-lab.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/embedded-lab.com\/blog\/wp-json\/wp\/v2\/comments?post=2583"}],"version-history":[{"count":33,"href":"https:\/\/embedded-lab.com\/blog\/wp-json\/wp\/v2\/posts\/2583\/revisions"}],"predecessor-version":[{"id":2641,"href":"https:\/\/embedded-lab.com\/blog\/wp-json\/wp\/v2\/posts\/2583\/revisions\/2641"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/embedded-lab.com\/blog\/wp-json\/wp\/v2\/media\/2584"}],"wp:attachment":[{"href":"https:\/\/embedded-lab.com\/blog\/wp-json\/wp\/v2\/media?parent=2583"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/embedded-lab.com\/blog\/wp-json\/wp\/v2\/categories?post=2583"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/embedded-lab.com\/blog\/wp-json\/wp\/v2\/tags?post=2583"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}