Difference between revisions of "PIC32MX: I2C"
Andrew Long (talk | contribs) |
Andrew Long (talk | contribs) |
||
(3 intermediate revisions by the same user not shown) | |||
Line 2: | Line 2: | ||
I2C can be used in the following cases: |
I2C can be used in the following cases: |
||
*As a slave device |
|||
*As a master in a single master system |
|||
*As a master in a multi-master system |
|||
I2C for PIC32 is discussed in more detail in the [http://ww1.microchip.com/downloads/en/DeviceDoc/61116D.pdf Microchip I2C documention]. |
I2C for PIC32 is discussed in more detail in the [http://ww1.microchip.com/downloads/en/DeviceDoc/61116D.pdf Microchip I2C documention]. |
||
Line 28: | Line 28: | ||
The master then sends a stop condition. |
The master then sends a stop condition. |
||
==C Code == |
|||
===I2C Master Code=== |
|||
==I2C |
===I2C Slave Code=== |
||
This section details the master code for I2C between two PICs. The slave has a 7 bit address in this example. |
This section details the master code for I2C between two PICs. The slave has a 7 bit address in this example. |
||
The code commented out can be used to communicate with [http://en.wikipedia.org/wiki/EEPROM EEPROM]. |
|||
==Associated Circuitry== |
|||
Include the standard header files |
|||
The SDAx and SCLx pins must be connected to Vdd (power) with a resistor typically 2.4k Ohm. They must also be connected from the master to the slave. |
|||
#include "GenericTypeDefs.h" |
|||
#include "Compiler.h" |
|||
#include "HardwareProfile.h" |
|||
#include <plib.h> |
|||
Define constants for the system and peripheral bus clocks. |
|||
#define SYSCLK (80000000) |
|||
#define PBCLK (SYSCLK/2) |
|||
The Baud Rate Generator is used to set the SCL clock frequency. The equations used for the BRG are shown below: |
|||
FSCK = (PBCLK) / ((I2CxBRG+2) * 2) |
|||
I2CBRG = (PBCLK / (2 *FSCK)) - 2 |
|||
Define constants for BRG. Fsck is chosen to be 50 kHz. |
|||
#define Fsck 50000 |
|||
#define BRG_VAL ((PBCLK/2/Fsck)-2) |
|||
Define a function to wait a little bit. (May not be necessary) |
|||
void i2c_wait(unsigned int cnt) |
|||
{ |
|||
while(--cnt) |
|||
{ |
|||
Nop(); |
|||
Nop(); |
|||
} |
|||
} |
|||
Start main function |
|||
int main(void) |
|||
{ |
|||
Set up some variables |
|||
unsigned char SlaveAddress; |
|||
char i2cData[10]; |
|||
int DataSz; |
|||
Initialize LEDs |
|||
mInitAllLEDs(); |
|||
Turn on I2C - Enable channel |
|||
OpenI2C1( I2C_EN, BRG_VAL ); |
|||
Set up slave address (7 bits in this case) |
|||
SlaveAddress = 0x50; //0b1010000 Slave address |
|||
Set up data to be sent (commented is for eeprom) |
|||
i2cData[0] = (SlaveAddress << 1) | 0; //Slave Device Address and WR Command |
|||
//i2cData[1] = 0x05;//eeprom location to program (high address byte) |
|||
//i2cData[2] = 0x40;//eeprom location to program (low address byte) |
|||
//i2cData[3] = 0xAA; //data to write |
|||
//DataSz = 4; |
|||
i2cData[1] = 0xAA; // data to write |
|||
DataSz = 2; |
|||
Assert a Start Condition |
|||
StartI2C1(); //Send the Start Bit |
|||
IdleI2C1(); //Wait to complete |
|||
Send Address and Data (after each transmission check for an acknowledge) |
|||
int Index = 0; |
|||
while( DataSz ) |
|||
{ |
|||
MasterWriteI2C1( i2cData[Index++] ); |
|||
IdleI2C1(); //Wait to complete |
|||
DataSz--; |
|||
//ACKSTAT is 0 when slave acknowledge. if 1 then slave has not acknowledge the data. |
|||
if( I2C1STATbits.ACKSTAT ) |
|||
break; |
|||
} |
|||
Send Stop condition |
|||
StopI2C1(); //Send the Stop condition |
|||
IdleI2C1(); //Wait to complete |
|||
Wait for Slave to complete write process by polling the ack status |
|||
while(1) |
|||
{ |
|||
i2c_wait(10); |
|||
StartI2C1(); //Send the Start Bit |
|||
IdleI2C1(); //Wait to complete |
|||
MasterWriteI2C1( i2cData[0] ); |
|||
IdleI2C1(); //Wait to complete |
|||
if( I2C1STATbits.ACKSTAT == 0 ) //eeprom has acknowledged |
|||
{ |
|||
StopI2C1(); //Send the Stop condition |
|||
IdleI2C1(); //Wait to complete |
|||
break; |
|||
} |
|||
StopI2C1(); //Send the Stop condition |
|||
IdleI2C1(); //Wait to complete |
|||
} |
|||
Now we are going to read back the data from the slave (commented is for EEPROM) |
|||
i2cData[0] = (SlaveAddress << 1) | 0; //Device Address and WR Command (to write the address) |
|||
//i2cData[1] = 0x05; //eeprom location to read (high address byte) |
|||
//i2cData[2] = 0x40; //eeprom location to read (low address byte) |
|||
//DataSz = 3; |
|||
DataSz = 1; |
|||
StartI2C1(); //Send the Start Bit |
|||
IdleI2C1(); //Wait to complete |
|||
Send the address to read from the Slave (if you are not using EEPROM, you do not need to have a while loop) |
|||
Index = 0; |
|||
while( DataSz ) |
|||
{ |
|||
MasterWriteI2C1( i2cData[Index++] ); |
|||
IdleI2C1(); //Wait to complete |
|||
DataSz--; |
|||
//ACKSTAT is 0 when slave acknowledge. if 1 then slave has not acknowledge the data. |
|||
if( I2C1STATbits.ACKSTAT ) |
|||
break; |
|||
} |
|||
StopI2C1(); //Send the Stop condition |
|||
IdleI2C1(); //Wait to complete |
|||
Now send a start sequence again |
|||
RestartI2C1(); //Send the Restart condition |
|||
//wait for this bit to go back to zero |
|||
IdleI2C1(); //Wait to complete |
|||
Transmit Read Command |
|||
MasterWriteI2C1( (SlaveAddress << 1) | 1 ); //transmit read command |
|||
IdleI2C1(); //Wait to complete |
|||
Read from the Slave |
|||
unsigned char i2cbyte; |
|||
i2cbyte = MasterReadI2C1(); |
|||
Stop transmission |
|||
StopI2C1(); //Send the Stop condition |
|||
IdleI2C1(); //Wait to complete |
|||
Check to see if correct data was sent back |
|||
if( i2cbyte != 0xAA ) |
|||
{ |
|||
while(1) //error: verify failed |
|||
{ |
|||
mLED_3_On(); |
|||
} |
|||
} |
|||
while(1) // Success |
|||
{ |
|||
mLED_2_On(); |
|||
mLED_4_On(); |
|||
} |
|||
} |
|||
==I2C Slave Code== |
|||
This section details the master code for I2C between two PICs. The slave has a 7 bit address in this example. |
Latest revision as of 13:44, 28 September 2009
Inter-Integrated Circuit, or I2C (pronounced I squared C), is used as a serial communication between other devices including other PICs.
I2C can be used in the following cases:
- As a slave device
- As a master in a single master system
- As a master in a multi-master system
I2C for PIC32 is discussed in more detail in the Microchip I2C documention.
Available Pins
There are two sets of pins for I2C. Each consists of SDAx and SCLx where x is either 1 or 2. SDA is the data pin and SCL is the clock pin.
Methodology: Single Master System
This section discusses the general approach for I2C between a single master and a slave.
To begin communication, the master first transmits a start command.
Each slave has a unique address. For the PIC32, the slaves can have either 7 bit or 10 bit addresses. For communicating with 10 bit addresses, see the Microchip I2C documention. The master transmits an 8 bit number. Bits 7-1 make up the slave address and bit 0 indicates whether or not the slave is expected to read or write. If bit 0 is a 1, the data transfer is output from the slave. If bit 0 is a 0, the data transfer is input to the slave.
When the master transmits the 8 bit number, the slaves compare their address to the sent address. If there is a match, the slave automatically generates an acknowledge that is sent to the master.
The slave then must read the address and R/W bit. This is done to clear the buffer.
The master then either waits for a response (output from slave) or sends up to 8 bits of data (input to slave). If output is from the slave, after each transmission the master sends an acknowledge. The slave continues to send data until the master does not acknowledge.
The master then sends a stop condition.
C Code
I2C Master Code
I2C Slave Code
This section details the master code for I2C between two PICs. The slave has a 7 bit address in this example.
Associated Circuitry
The SDAx and SCLx pins must be connected to Vdd (power) with a resistor typically 2.4k Ohm. They must also be connected from the master to the slave.