0
\$\begingroup\$

I have a problem seeing SCL and SDA signals on the oscilloscope. I am using PIC18LF in Master mode and the bus is pulled up to Vcc. I beleive i have programmed correctly but all I see 3.3V on the Oscilloscope SDA and SCL lines.

I cannot figure out where I screwed up!

Here's my code:

//i2cdem.c


void init_oscillator(void)
{
    // NOSC HFINTOSC; NDIV 1; 
    OSCCON1 = U8_SET_HFINTOSC_NDIV_1;
    // CSWHOLD may proceed; SOSCPWR Low power; 
    OSCCON3 = 0x00;
    // TUN 0; 
    OSCTUNE = 0x00;

    OSCEN   = 0x00;                   // MFOEN disabled; LFOEN disabled; ADOEN disabled; SOSCEN disabled; EXTOEN disabled; HFOEN disabled;
    OSCFRQ  = U8_NOMINAL_CLK_FRQ_8M;  // Setting OSCFRQ register to 0x03 --> 8MHz

}

void set_I2C_baud_rate(unsigned int freq_KHZ)
{    
    volatile unsigned int F=8000;
    volatile unsigned int temp=0; 
    temp = 80;
    temp -= 4;
    temp /= 4;
    //temp=( (Fosc/freq_KHZ) - 4)/4 ; 
    SSP1ADD = temp;      
}
void I2C_Inititalise()
{
    SSP1CON1       = 0x28;  //I2C Mode
    PORTCbits.RC3    = 1; //SCL
    PORTCbits.RC4    = 1; //SDA

    TRISCbits.TRISC3 =0;
    TRISCbits.TRISC4 =0;

    TRISCbits.TRISC3 =1;
    TRISCbits.TRISC4 =1;

    LATCbits.LATC3 = 1;
    LATCbits.LATC4 = 1;


    SSP1CON2       = 0x00; 

    SSP1STAT       = 0x80;   
//    SSP1BUF =( (U8_LDC_ADD<<1) | 0x00 );
}

void send_start()
{
    SSP1CON2bits.SEN=1;
    while(SSP1CON2bits.SEN);   

}

void send_stop(){

    SSP1CON2bits.PEN=1;
    while(SSP1CON2bits.PEN);

}

void I2C_wait(void)
{
    while( (SSP1STAT & 0x04) | (SSP1CON2 & 0x1F) );
    PIR3bits.BCL1IF=0;

}


void write_to_bus(unsigned char data)
{
    SSP1BUF = data;


}



//main.c
    void main(void) {

        init_oscillator();

        I2C_Inititalise();

        set_I2C_baud_rate(100); //set SCL to 100KHz


        while(1){

            send_start();
            I2C_wait();
            write_to_bus(U8_LDC_ADD<<1); //Address
            I2C_wait();
            send_stop();


        }



        return;
    }
\$\endgroup\$
0

2 Answers 2

1
\$\begingroup\$

The problem was not configuring PPS registers on initialization for I2C module.

Mentioned in PPS Chapter

PPS Outputs Each I/O pin has a PPS register with which the pin output source is selected. With few exceptions, the port TRIS control associated with that pin retains control over the pin output driver. Peripherals that control the pin output driver as part of the peripheral operation will override the TRIS control as needed. These peripherals include: • EUSART (synchronous operation) • MSSP (I2C)

And, not configuring ANSELC register. I had to explicitly clear ANSELC bits to get it working. Actually discovered it by accident when i was configuring Receive interrupt, read a Note in Datasheet which was in a corner.

Note: If the RX/DT function is on an analog pin, the corresponding ANSEL bit must be cleared for the receiver to function.

It seemed to work for USART, so I tried it for I2C as well. Took only a few days to figure it out, but now I see the corresponding SDA and SCL waveforms. :)

void I2C_Inititalise()
{

    ANSELCbits.ANSELC3 =0;
    ANSELCbits.ANSELC4 =0;

    RC3PPS         = 0x0D; //PPS OUTPUT CLK  
    RC4PPS         = 0x0E; //PPS OUTPUT SDA 

    SSP1CLKPPS     = 0x13; //PPS INPUT CLK
    SSP1DATPPS     = 0x14; //PPS INPUT SDA 

    SSP1CON1       = 0x28;  //I2C Mode
    SSP1CON2       = 0x00; 
    SSP1STAT       = 0x00;   
    SSP1ADD        = 0x04;
}
\$\endgroup\$
0
\$\begingroup\$

I think you problem is that in the I2C_Inititalise function you don't set the SCL/SDA pins to inputs after you set the I2C mode in the SSP1CON1 register but before.

From the datasheet

26.8.3 SDA AND SCL PINS

Selection of any I2C mode with the SSPEN bit set, forces the SCL and SDA pins to be open-drain. These pins should be set by the user to inputs by setting the appropriate TRIS bits.

Just move all the PORT/TRIS/LAT lines of code after setting the SSP1CON1 and you should be ok.

\$\endgroup\$
4
  • \$\begingroup\$ I set the Pins C to I/P after setting SSP1CON1 register. I dont see any change. Pullup resistors are 2.2k ohms, may be they are too low?! \$\endgroup\$
    – Abel Tom
    Jul 20, 2017 at 9:43
  • \$\begingroup\$ 2.2k should be ok, but you could always try 4.7k or 10k to be sure, especially if the bus capacitance is not too high. But I have updated the answer with sth else: I think your SCL clock period is way too high. I think this is the problem. \$\endgroup\$
    – nickagian
    Jul 20, 2017 at 10:40
  • \$\begingroup\$ Sorry, my bad... You had it correctly at 100kHz. Wrong calculation. Try perhaps different pull-up values. You never said, what do you have on the bus as slave? And sth else: Are you sure the PIC works, generally speaking? I'd put some short code to periodically turn on and off an LED to be sure. Perhaps there is something else going on that is not related with I2C. \$\endgroup\$
    – nickagian
    Jul 20, 2017 at 11:25
  • \$\begingroup\$ PIC seems to be working, LED Toggle seems to work just fine, slave device is a measurement IC. \$\endgroup\$
    – Abel Tom
    Jul 20, 2017 at 11:40

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.