Difference between revisions of "PIC32MX: I2C"

From Mech
Jump to navigationJump to search
 
(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 slave device
**As a master in a single master system
*As a master in a single master system
**As a master in a multi-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 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. 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.
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.