PIC18F26K22 i2c hardware help please

Thread Starter

portreathbeach

Joined Mar 7, 2010
143
I've managed to get the SPI hardware function of the PIC18F26K22 to work on serial 1, and the DAC function to work on the DAC output pin, but I can't get the i2c to work on serial 2.

Please can someone tell me which registers need to be changed to get it to work.

So far I have this:
Rich (BB code):
    TRISC = 0x00;
    TRISB = 0x00010010;             // RB4 and RB1 inputs (i2c)
    TRISA = 0b00001100;

    ANSELA = 0b00001100;            // All digital apart from RA3
    ANSELB = 0x00;                  // All digital
    ANSELC = 0x00;                  // All digital

    ADCON0bits.CHS = 0b11110;       // DAC

    CM1CON0 = 0x00;                 // comparitor 1 off
    
    CCP1CON = 0x00;

    PWM1CON = 0x00;
    SRCON0 = 0x00;                  // SR latch control
    SRCON1 = 0x00;                  // SR latch control

    PMD1 = 0b0001000;               // peripheral module disable CCP5
    SSP1STAT = 0b01000000;          // data transfer on rising edge (bit 6 = 1)
    SSP1CON1 = 0b00100000;          // SPI enable, master mode FOSC/4

    SSP2ADD = 0b00011000;           // i2c speed
    SSP2CON1 = 0b00101000;          // i2c master mode
    SSP2CON2 = 0;                   // clear control bits


    OSCCON |= 0b01110000;            // 16MHz (bits 6,5,4 set to 111)

// CM2CON1bits.C1RSEL = 1;         // FVR BUF1 is routed to C1 Vref (RA3)

    VREFCON0bits.FVREN = 1;         // fixed voltage reference enabled
    VREFCON0bits.FVRST = 1;         // fixed voltage output is ready to use
// VREFCON0bits.FVREN = 0b10;      // voltage reference is 2.048v

    VREFCON1bits.DACEN = 1;         // DAC enabled
    VREFCON1bits.DACLPS = 1;        // positive reference source
    VREFCON1bits.DACOE = 1;         // DAC voltage output enabled
    VREFCON1bits.DACPSS = 0b00;     // use VDD as reference
// VREFCON1bits.DACPSS = 0b01;     // use VREF+ as reference
    VREFCON1bits.DACNSS = 0;        // use VSS as -ve reference
This sets up the registers for the SPI on serial 1, the DAC, but the i2c on serial 2 doesn't seem to work.

Also, has anyone got any sample code to get the bus running, I have this so far:

Rich (BB code):
void i2c_start( void ){

    SSP2CON2bits.SEN = 1;
    while(SSP2CON2bits.SEN == 0);       // Wait for condition to be sent
}

//....................................................................
// Sends the Repeated Start condition
//....................................................................
void i2c_repstart( void ){

    SSP2CON2bits.RSEN = 1;              // Enable Repeated Start condition
    while(SSP2CON2bits.RSEN);        // Wait for condition to be sent
}

//....................................................................
// Sends the Stop condition
//....................................................................
void i2c_stop( void )
{
    SSP2CON2bits.PEN = 1;               // Enable Stop condition
    while(SSP2CON2bits.PEN == 0);       // Wait for condition to be sent
}

//....................................................................
// Writes a byte to the I2C bus
//....................................................................
unsigned char i2c_write( unsigned char data )
{
//    i2c_idle();
        PIR3bits.SSP2IF = 0;            // clear the SSP transmit finished interrupt flag
        SSP2BUF = data;          // Loads the buffer with provided data
        while(!PIR3bits.SSP2IF);        // wait for SSP interrupt flag to say transmit is finished
    return(!SSP2CON2bits.ACKSTAT);  // Returns 1 if slave acknowledged
}

Basically, after I setup the registers, I call the i2c_start function and then the the i2c_write function with some data, then the stop function over and over and try to scope what I see. I see nothing on either pin.

I would really like to get this working, or I'll have to return to my trusty bit banging routine which works perfectly.
 

Thread Starter

portreathbeach

Joined Mar 7, 2010
143
I know how the i2c protocol works as I have a bitbang version I wrote which communicates with a real time clock module to read and write to it, but I cannot get the hardware version on my PIC to work.

Basically, I can't get my clock pulses of data pulses to display on my scope.

To try to see if the SSP2 port is working I am simply calling

i2c_Start, then sending some data with i2c_write, then i2c_stop. I am sending this in a loop just to see if anything is happening. Here is the updated code as I realise some of it was wrong:

Rich (BB code):
//....................................................................
// Waits for the I2C bus to go into Idle mode
//....................................................................
void i2c_idle()
{
    while ( ( SSP2CON2 & 0x1F ) || ( SSP2STAT & 0x04 ) ); //only continues when there is not imortant bit set
}

//....................................................................
// Sends the Start condition
//....................................................................
void i2c_start( void ){

     i2c_idle(); 
     SSP2CON2bits.SEN=1; 
     while(SSP2CON2bits.SEN);
}

//....................................................................
// Sends the Repeated Start condition
//....................................................................
void i2c_repstart( void ){

    SSP2CON2bits.RSEN = 1;              // Enable Repeated Start condition
    while(SSP2CON2bits.RSEN);        // Wait for condition to be sent
}

//....................................................................
// Sends the Stop condition
//....................................................................
void i2c_stop( void )
{
     i2c_idle();
     SSP2CON2bits.PEN=1;
     while(SSP2CON2bits.PEN);
}

//....................................................................
// Writes a byte to the I2C bus
//....................................................................
unsigned char i2c_write(unsigned char data)
{
    i2c_idle();
    SSP2BUF = data;                     // Loads the buffer with provided data
    return(!SSP2CON2bits.ACKSTAT);      // Returns 1 if slave acknowledged
}
I'm sure it's something to do with the configuration of the PIC, but I have made changes to all the relevent register, I think.
 

Thread Starter

portreathbeach

Joined Mar 7, 2010
143
Yes, I have 4.7K on each line, like when I was bitbanging.

I know tried this just to see if the port is working:
Rich (BB code):
while(1){
            SSP2BUF = 0xFF;
            SSP2CON2bits.SEN=1;
            __delay_us(20);
            SSP2CON2bits.PEN=1;
            __delay_us(20);
}
But nothing. Both lines are staying high.
 

Thread Starter

portreathbeach

Joined Mar 7, 2010
143
OK. I had a slight config error. I had set RB1 and RB4 as inputs instead of RB1 and RB2, I changed this but still seeing high level on both pins.

EDIT: Finally got something working. I am sending the address of the real time clock module and when I remove the SDAT line, the acknowledge bit changes, so I know it must be communicating. It was a stupid config error, and not quite reading the datasheet properly.

Thanks again for your help.
 
Last edited:
Top