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); } }