Documente Academic
Documente Profesional
Documente Cultură
A
= = = =
DATA
A ... DATA
A/A
Acknowledge (SDA = Low) Not Acknowledge (SDA = Hi) Start Condition Stop Condition
DATA
A ... DATA
/A
I2CCommunicationbetweenTwoPICMicrocontrollers
PICasI2CMaster
PICasI2CSlave
SSPInterrupt
// I2C Example: Pseudo-code within Master PIC for 2-byte read and 2-byte // write transactions. #define ACK 1 #define NO_ACK 0 union IO { struct { unsigned int8 lsb; unsigned int8 msb; } abyte; unsigned int16 aword; }; union IO R, W; void main() { // Main program in Master : // Master receive-code immediately follows. // Master reads 2-bytes transmitted by the Slave and saves as variable, W. // The Slave.c code is on the next page. i2c_start(); i2c_write(0xA1); // // // W.abyte.lsb=i2c_read(ACK); // // W.abyte.msb=i2c_read(NO_ACK); // // i2c_stop(); // : Start I2C transaction Least significant bit (1) specifies read from the Slave with address 0xA0/0xA1 Read first/next byte from slave with ACK asserted by the Master Read LAST byte from slave with NO_ACK by the Master End I2C transaction
// Master transmit-code immediately follows. // The Master transmits 2-bytes (that comprise the variable, R) to the Slave. ?? The Slave.c code, is on the next page. R=16-bit signed value; i2c_start(); i2c_write(0xA0); i2c_write(R.abyte.lsb); i2c_write(R.abyte.msb); i2c_stop(); : } // // // // // // Start I2C transaction Least significant bit (0)specifies write to the Slave with address 0xA0/0xA1 Write first/next byte to Slave Write last byte to Slave End I2C transaction
// // // // // // // //
Pseudo Code within the Slave PIC. The SSP interrupt routine implements the operation of the I2C Slave. The interrupt routine reads or write 2-bytes with each transaction that is initiated by the Master. Whenever a read transaction is initiated (by the Master) the Slave will write the two bytes that comprise the 16-bit variable, X. Whenever a write transaction is initiated (by the Master) the Slave will read the two bytes that comprise the 16-bit variable (sent by the Master) and stores as variable Rslave.
union IO { struct { unsigned int8 lsb; unsigned int8 msb; } abyte; unsigned int16 aword;}; union Rslave, X; // Globals unsigned int8 SendBuffer(2), ReceiveBuffer(2); void main() { // Main program in Slave : X=16-bit value; } #INT_SSP // I2C Interrupt handler within the slave. void i2c_interrupt() { BYTE state, incoming; state = i2c_isr_state(); // Note: state increments with each subsequent byte received or sent. // state == 0: address match detected by slave. // state 0x01 to 0x7F: Slave should read the first/next byte transmitted by // the Master. // state == 0x80 to 0xFF: Slave should write the first/next byte of a read // transaction initiated by the Master. if(state >= 0x80) { if(state > 0x82) {I2C_Errror=1; break;} // Error because the Master was programmed to read/receive 2-bytes only. else { if(state == 0x80) { // Starting a new 2-byte transaction. SendBuffer[0]=X.abyte.lsb; // Load SendBuffer[] within the SendBuffer[1]=X.abyte.msb; // interrupt handler as an atomic } // operation. i2c_write(SendBuffer[state-0x80]; } else { incoming = i2c_read(); if(state > 2) { I2C_Errror=2; break;} // Error because the Master was programmed to send/transmit 2-bytes only. else { ReceiveBuffer[state-1]=incoming; if(state == 2) { // Update Rslave within Rslave.abyte.lsb=ReceiveBuffer[0]; // interrupt handler as Rslave.abyte.msb=ReceiveBuffer[1]; // an atomic operation. } } }
I2CusingaPICasMasterandaPICasSlaveWriteTransactionbyMaster
SDAdrivenby Slave
z ACK*
z ACK*
z ACK*
0/1
I2CusingaPICasMasterandaPICasSlaveReadTransactionbyMaster
SDAdrivenby Slave
z ACK*