Difference between revisions of "PIC32MX: I2C"
Andrew Long (talk | contribs) |
Andrew Long (talk | contribs) |
||
Line 45: | Line 45: | ||
The Baud Rate Generator is used to set the SCL clock frequency. The equations used for the BRG are shown below: |
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) |
FSCK = (PBCLK) / ((I2CxBRG+2) * 2) |
||
I2CBRG = (PBCLK / (2 *FSCK)) - 2 |
I2CBRG = (PBCLK / (2 *FSCK)) - 2 |
||
Revision as of 11:10, 18 August 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
This section details the master code for I2C between two PICs. The slave has a 7 bit address in this example. What we are going to do is send a message to the slave and then read the same message back from the slave. If the correct message is read LEDs 2 and 4 will turn on. If there is an error, LED 3 will turn on. The code commented out can be used to communicate with EEPROM.
Include the standard header files
#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.
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.