3 Master Mode Code Example
Example 3.1 shows the use of the MSSP in 7-bit I2C
Master mode. The example uses bit polling to determine when to issue a Start condition,
load data and other I2C functions. The functions used in the code example are
used to read and write a single data byte to a specific address location within the
slave’s memory. In the ‘I2C_WriteByte()
’ routine, the byte following
the address byte represents the register or memory address within the slave that will
receive the data. In the ‘I2C_ReadByte()
’ routine, the byte following
the address is also the register or memory address within the slave’s memory that will
be read by the master. In this routine, once the slave acknowledges the register
address, the master must issue a Restart condition and transmit the slave address again
with the R/W bit set.
MSSP in I2C Master Mode
// main() routine uint8_t slaveAddress = 0x30; // 7-bit slave address uint8_t regAddress = 0x00; // Register location uint8_t writeVal = 0xCB; // Value to write uint8_t readVal = 0x00; // Value from slave void main(void) { SYSTEM_Initialize(); while (1) { I2C_WriteByte(slaveAddress, regAddress, writeVal); // Write to slave __delay_ms(100); // Short delay readVal = I2C_ReadByte(slaveAddress, regAddress); // Read back data __delay_ms(1000); // 1 second delay } } // I2C initialize routine void I2C_Initialize(void) { SSP1STAT = 0x80; // Sample end of data output SSP1CON1 = 0x08; // SCL =FOSC/4(SSPxADD+1) SSP1CON3 = 0x00; SSP1ADD = 0x4F; // 0x4F = 100 kHz Clock @ 32 MHz PIR3bits.SSP1IF = 0; // Clear the interrupt flag PIE3bits.SSP1IE = 0; // Disable the interrupt SSP1CON1bits.SSPEN = 1; // Enable MSSP } // Master write routine void I2C_WriteByte(uint8_t deviceADDR, uint8_t registerADDR, uint8_t val) { while (!Idle); // Wait until MSSP module is idle I2C_Start = 1; // Set START bit while (I2C_Start); // Wait until hardware clears SEN SSP1BUF = deviceADDR; // Load device address (write) while (!Idle); // Wait until MSSP module is idle SSP1BUF = registerADDR; // Send register address (write) while (!Idle); // Wait until module is idle SSP1BUF = val; // Send data to slave while (!Idle); // Wait until module is idle I2C_Stop = 1; // Set STOP bit while (!Idle); // Wait until module is idle } // Master read routine uint8_t I2C_ReadByte(uint8_t deviceADDR, uint8_t registerADDR) { uint8_t data; // Data byte while (!Idle); // Wait until module is idle I2C_Start = 1; // Set START bit while (I2C_Start); // Wait until hardware clears SEN SSP1BUF = deviceADDR; // Load device address (write) while (!Idle); // Wait until module is idle SSP1BUF = registerADDR; // Send register address (write) while (!Idle); // Wait until module is idle I2C_Restart = 1; // Restart condition while (I2C_Restart); SSP1BUF = (deviceADDR | 0x01); // Send device address (read) while (!Idle); // Wait until module is idle SSP1CON2bits.RCEN = 1; // Set RCEN (Master receiver) while (!Idle); // Wait until module is idle data = SSP1BUF; // Read SSPBUF SSP1CON2bits.ACKDT = 1; // ACK bit, 1 = Not acknowledge SSP1CON2bits.ACKEN = 1; // Start ACK sequence while (SSP1CON2bits.ACKEN); // Wait for end of ACK sequence SSP1CON2bits.ACKDT = 0; // ACK bit, 0 = acknowledge I2C_Stop = 1; // Set STOP bit while (!Idle); // Wait until module is idle return data; // Return the data }