{"id":716,"date":"2016-07-22T15:12:00","date_gmt":"2016-07-22T15:12:00","guid":{"rendered":"https:\/\/ibex.tech\/embedded\/?p=716"},"modified":"2022-02-18T15:37:48","modified_gmt":"2022-02-18T15:37:48","slug":"i2c-master","status":"publish","type":"post","link":"https:\/\/ibex.tech\/embedded\/microchip\/pic32\/xc32-v2-old\/i2c\/i2c-master","title":{"rendered":"I2C Master"},"content":{"rendered":"<p>\nThe legacy versions of Plib I2C has code for I2C1 and I2C2 only. &nbsp;When you try and use fro I2C3, I2C4 etc you&#39;re buggered. &nbsp;You have to use the modern I2C functions instead which is just great because they are horribly documented and don&#39;t have direct equivalents for things like&nbsp;IdleI2C1().\n<\/p>\n<h4>\nSetup I2C Bus<br \/>\n<\/h4>\n<pre>\r\n<code>\r\n\t\/\/----- SETUP I2C 4 -----\r\n\t\/\/Used for: \r\n\tI2CConfigure(I2C4, I2C_ENABLE_HIGH_SPEED);\r\n\tI2CSetFrequency(I2C4, PERIPHERAL_CLOCK_FREQUENCY, 400000);\t\t\t\/\/400kHz I2C bus\r\n\tI2CEnable(I2C4, TRUE);\r\n<\/code><\/pre>\n<h4>\nI2C Access&nbsp;Defines We Use<br \/>\n<\/h4>\n<pre>\r\n<code>\r\n\r\n\/\/PIC32\r\n#define\tLED_DRIVER_I2C_SEND_START\t\t\t\t\twhile(!I2CBusIsIdle(I2C4));I2CStart(I2C4)\t\t\t\/\/Generate bus start condition\r\n#define\tLED_DRIVER_I2C_START_IN_PROGRESS_BIT\t\tI2C4CONbits.SEN\t\t\t\t\t\t\t\t\t\t\/\/Bit indicating start is still in progress\r\n#define\tLED_DRIVER_I2C_SEND_RESTART\t\t\t\t\tI2CRepeatStart(I2C4)\t\t\t\t\t\t\t\t\/\/Generate bus restart condition\r\n#define\tLED_DRIVER_I2C_RESTART_IN_PROGRESS_BIT\t\tI2C4CONbits.RSEN\t\t\t\t\t\t\t\t\t\/\/Bit indicating re-start is still in progress\r\n#define\tLED_DRIVER_I2C_SEND_STOP\t\t\t\t\tI2CStop(I2C4)\t\t\t\t\t\t\t\t\t\t\/\/Generate bus stop condition\r\n#define\tLED_DRIVER_I2C_STOP_IN_PROGRESS_BIT\t\t\tI2C4CONbits.PEN\t\t\t\t\t\t\t\t\t\t\/\/Bit indicating Stop is still in progress\r\n#define\tLED_DRIVER_I2C_WRITE_FUNCTION(a)\t\t\twhile(!I2CTransmitterIsReady(I2C4));I2CSendByte(I2C4, a)\t\t\/\/Write byte to I2C device\r\n#define\tLED_DRIVER_I2C_TX_IN_PROGRESS_BIT\t\t\t(!I2CTransmissionHasCompleted(I2C4))\t\t\t\t\/\/Bit indicating transmit byte is still in progress\r\n#define\tLED_DRIVER_I2C_ACK_NOT_RECEIVED_BIT\t\t\t(!I2CByteWasAcknowledged(I2C4))\t\t\t\t\t\t\/\/Bit that is high when ACK was not received\r\n#define\tLED_DRIVER_I2C_READ_FUNCTION(a)\t\t\t\tI2CReceiverEnable(I2C4, TRUE); while(!I2CReceivedDataIsAvailable(I2C4)); a=I2CGetByte(I2C4)\t\/\/Read byte from I2C device function \/ result byte of TCN75_I2C_READ_FUNCTION_START (I2CReceiverEnable will only cause 1 byte to be read, you have to use it again for multiple bytes)\r\n#define LED_DRIVER_I2C_SEND_ACK\t\t\t\t\t\tI2CAcknowledgeByte(I2C4, TRUE)\t\t\t\t\t\t\/\/Generate bus ACK condition\r\n#define LED_DRIVER_I2C_SEND_NACK\t\t\t\t\tI2CAcknowledgeByte(I2C4, FALSE)\t\t\t\t\t\t\/\/Generate bus Not ACK condition\r\n#define\tLED_DRIVER_I2C_ACK_IN_PROGRESS_BIT\t\t\t(!I2CAcknowledgeHasCompleted(I2C4))\t\t\t\t\t\/\/Bit indicating ACK is still in progress\r\n#define\tLED_DRIVER_I2C_WAIT_FOR_IDLE\t\t\t\t\/\/while(!I2CBusIsIdle(I2C4))\t\t\t\t\t\t\/\/Test if I2C module is idle (FOR XC32 THIS CAN&#39;T BE USED AFTER START CONDITION SO WE DON&#39;T USE IT)\r\n<\/code><\/pre>\n<h4>\nWrite Access<br \/>\n<\/h4>\n<pre>\r\n<code>\r\n\r\n\t\/\/----- SEND THE START CONDITION -----\r\n\tLED_DRIVER_I2C_WAIT_FOR_IDLE;\r\n\tLED_DRIVER_I2C_SEND_START;\r\n\twhile(LED_DRIVER_I2C_START_IN_PROGRESS_BIT)\r\n\t\t;\r\n\r\n\t\/\/----- SEND THE I2C DEVICE ADDRESS WITH THE WRITE BIT SET -----\r\n\tLED_DRIVER_I2C_WAIT_FOR_IDLE;\r\n\tLED_DRIVER_I2C_WRITE_FUNCTION(LED_DRIVER_I2C_BASE_ADDRESS &amp; 0xfe);\t\t\t\/\/Bit 0 low for write\r\n\twhile(LED_DRIVER_I2C_TX_IN_PROGRESS_BIT)\r\n\t\t;\r\n\tif(LED_DRIVER_I2C_ACK_NOT_RECEIVED_BIT)\r\n\t\tgoto led_driver_init_write_fail;\r\n\r\n\t\/\/----- WRITE THE DATA BYTE -----\r\n\tLED_DRIVER_I2C_WAIT_FOR_IDLE;\r\n\tLED_DRIVER_I2C_WRITE_FUNCTION(0x80);\r\n\twhile(LED_DRIVER_I2C_TX_IN_PROGRESS_BIT)\r\n\t\t;\r\n\tif(LED_DRIVER_I2C_ACK_NOT_RECEIVED_BIT)\r\n\t\tgoto led_driver_init_write_fail;\r\n\t\t\r\n\t\/\/----- SEND STOP -----\r\n\tLED_DRIVER_I2C_WAIT_FOR_IDLE;\r\n\tLED_DRIVER_I2C_SEND_STOP;\r\n\twhile(LED_DRIVER_I2C_STOP_IN_PROGRESS_BIT)\r\n\t\t;\r\n<\/code><\/pre>\n<h4>\nWrite Address Then Read<br \/>\n<\/h4>\n<pre>\r\n<code>\r\n&lt;pre&gt;&lt;code&gt;\r\n\r\n\t\/\/Send Start\r\n\tLED_DRIVER_I2C_IDLE_I2C;\t\t\t\t\t\/\/Wait for I2C bus to be ready\r\n\tLED_DRIVER_I2C_START_I2C;\r\n\twhile(LED_DRIVER_I2C_START_IN_PROGRESS_BIT)\r\n\t\t;\r\n\r\n\t\/\/Write Slave address and with RW bit 0 for write\r\n\tLED_DRIVER_I2C_IDLE_I2C;\r\n\tLED_DRIVER_I2C_WRITE_BYTE(LED_DRIVER_I2C_BASE_ADDRESS);\r\n\twhile(LED_DRIVER_I2C_TX_IN_PROGRESS_BIT)\r\n\t\t;\r\n\tif(LED_DRIVER_I2C_ACK_NOT_RECEIVED_BIT ==1)\r\n\t\tgoto led_driver_fail;\r\n\t\r\n\tLED_DRIVER_I2C_IDLE_I2C;\r\n\tLED_DRIVER_I2C_WRITE_BYTE(0x00);\r\n\twhile(LED_DRIVER_I2C_TX_IN_PROGRESS_BIT);\r\n\tif(LED_DRIVER_I2C_ACK_NOT_RECEIVED_BIT == 1)\r\n\t\tgoto led_driver_fail;\r\n\r\n\t\/\/Send Restart\r\n\tLED_DRIVER_I2C_IDLE_I2C;\r\n\tLED_DRIVER_I2C_RESTART_I2C;\r\n\twhile(LED_DRIVER_I2C_RESTART_IN_PROGRESS_BIT)\r\n\t\t;\r\n\r\n\t\/\/Write Slave address and with RW bit 1 for read\r\n\tLED_DRIVER_I2C_IDLE_I2C;\r\n\tLED_DRIVER_I2C_WRITE_BYTE(LED_DRIVER_I2C_BASE_ADDRESS | 0x01);\r\n\twhile(LED_DRIVER_I2C_TX_IN_PROGRESS_BIT)\r\n\t\t;\r\n\tif(LED_DRIVER_I2C_ACK_NOT_RECEIVED_BIT == 1)\r\n\t\tgoto led_driver_fail;\r\n\r\n\t\/\/Get byte 0\r\n\tLED_DRIVER_I2C_IDLE_I2C;\r\n\tLED_DRIVER_I2C_READ_BYTE(b_temp);\r\n\tour_reg1 = b_temp;\r\n\r\n\r\n\t\/\/Send Ack\r\n\tLED_DRIVER_I2C_IDLE_I2C;\r\n\tLED_DRIVER_I2C_ACK;\r\n\twhile(LED_DRIVER_I2C_ACK_IN_PROGRESS_BIT)\r\n\t\t;\r\n\r\n\tLED_DRIVER_I2C_IDLE_I2C;\r\n\tLED_DRIVER_I2C_READ_BYTE(b_temp);\r\n\tour_reg2 = b_temp;\r\n\r\n\t\/\/Send NAK\r\n\tLED_DRIVER_I2C_IDLE_I2C;\r\n\tLED_DRIVER_I2C_NOT_ACK;\r\n\twhile(LED_DRIVER_I2C_ACK_IN_PROGRESS_BIT)\r\n\t\t;\r\n\r\n\t\/\/Send Stop\r\n\tLED_DRIVER_I2C_IDLE_I2C;\r\n\tLED_DRIVER_I2C_STOP_I2C;\r\n\twhile(LED_DRIVER_I2C_STOP_IN_PROGRESS_BIT)\r\n\t\t;\r\n\r\n&lt;\/code&gt;&lt;\/pre&gt;\r\n\r\n<\/code><\/pre>\n<p>\n&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>The legacy versions of Plib I2C has code for I2C1 and I2C2 only. &nbsp;When you try and use fro I2C3, I2C4 etc you&#39;re buggered. &nbsp;You have to use the modern I2C functions instead which is just great because they are horribly documented and don&#39;t have direct equivalents for things like&nbsp;IdleI2C1(). Setup I2C Bus \/\/&#8212;&#8211; SETUP [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[63],"tags":[],"class_list":["post-716","post","type-post","status-publish","format-standard","hentry","category-i2c"],"_links":{"self":[{"href":"https:\/\/ibex.tech\/embedded\/wp-json\/wp\/v2\/posts\/716","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/ibex.tech\/embedded\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/ibex.tech\/embedded\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/ibex.tech\/embedded\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/ibex.tech\/embedded\/wp-json\/wp\/v2\/comments?post=716"}],"version-history":[{"count":3,"href":"https:\/\/ibex.tech\/embedded\/wp-json\/wp\/v2\/posts\/716\/revisions"}],"predecessor-version":[{"id":719,"href":"https:\/\/ibex.tech\/embedded\/wp-json\/wp\/v2\/posts\/716\/revisions\/719"}],"wp:attachment":[{"href":"https:\/\/ibex.tech\/embedded\/wp-json\/wp\/v2\/media?parent=716"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/ibex.tech\/embedded\/wp-json\/wp\/v2\/categories?post=716"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/ibex.tech\/embedded\/wp-json\/wp\/v2\/tags?post=716"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}