2.3 Part Three: The I2C Master
The final part of this project is the I2C master. The job of the master is to read the data from each of the two slaves, convert the data back into the proper variable type, and display the results on a PC terminal program.
The MSSP is configured in Master mode as shown in MSSP Initialization. The master
            begins by requesting the data from the slave device that controls the pH sensor. Once
            the master receives the pH data, it reconstructs the three bytes back into a
            floating-point number and writes the pH value to the PC terminal program. Next, the
            master requests data from the slave device that controls the temperature and water level
            sensors. Once the data is received, the master rebuilds the temperature data back into a
            floating-point number and writes the value to the terminal program. Then, the master
            converts the water level sensor data back into a 16-bit unsigned integer and compares
            the value to the expected values that represent either a “pass” or “fail” condition.
            Once the status has been selected, it is displayed on the PC terminal program. MSSP Master Routines shows the
            routines in 
        main() that handle the calculations and display the
                data.Important: When
                    creating the master project, the C99 standard must also be changed to the C90
                    standard following the same steps as in Part One.
MSSP Initialization
void I2C_Init(void) { SSP1STAT = 0x80; // Sample end of data output time SSP1CON1 = 0x28; // SSPEN enabled; I2C master clk =FOSC/4(SSPxADD+1) SSP1CON3 = 0x00; SSP1ADD = 0x09; // 0x4F = 100 kHz Clock @ 32 MHz PIR1bits.SSP1IF = 0; // Clear the master interrupt flag PIE1bits.SSP1IE = 0; // Disable the master interrupt }
MSSP Master Routines
// MSSP defines and macros #define Idle !(SSP1STATbits.R_nW | (0x1F & SSP1CON2)) // I2C Idle #define I2C_Start (SSP1CON2bits.SEN) // I2C Start #define I2C_Restart (SSP1CON2bits.RSEN) // I2C Restart #define I2C_Stop (SSP1CON2bits.PEN) // I2C Stop #define PH_ADDRESS 0x30 #define THERM_ADDRESS 0x32 #define PH_READS 0x3 #define THERM_READS 0x5 void main(void) { SYSTEM_Initialize(); while (1) { I2C_Read(PH_ADDRESS, 0x00, PH_READS); // Read pH sensor (uint24_t)newpH = ((uint24_t)I2CData[2] << 16); (uint24_t)newpH = (uint24_t)newpH + ((uint16_t)I2CData[1] << 8); (uint24_t)newpH = (uint24_t)newpH + I2CData[0]; (float)pHValue = (uint24_t)newpH; pHValue /= 100.00; printf("pH Value = %1.1f \r\n", pHValue); I2C_Read(THERM_ADDRESS, 0x00, THERM_READS); // Read temp sensor (uint24_t)newTherm = ((uint24_t)I2CData[2] << 16); (uint24_t)newTherm = (uint24_t)newTherm + ((uint16_t)I2CData[1] << 8); (uint24_t)newTherm = (uint24_t)newTherm + I2CData[0]; (float)thermValue = (uint24_t)newTherm; thermValue /= 100.00; printf("Therm Value = %1.1f \r\n", thermValue); (uint16_t)lvlSensor = ((uint16_t)I2CData[4] << 8); (uint16_t)lvlSensor = (uint16_t)lvlSensor + I2CData[3]; if(lvlSensor > 1010) { printf("WARNING: WATER LEVEL LOW!! ADD WATER! \r\n"); } else { printf("Water level OK! \r\n"); } __delay_ms(3500); } }
