1
\$\begingroup\$

I got PIC24FJ192GB106 (64 pin package) and I cannot get the I2C module working at all. What is the easiest and most straight forward way of testing, whether the module is OK?

I am using I2C1 module, (SCL1 - pin 44, SDA1 - pin 43).

BRG register = 39; // 100 kHz for Fosc = 8 MHz

// Control register
    I2C1CONbits.I2CEN = 1;    
    I2C1CONbits.I2CSIDL = 0;   
    I2C1CONbits.SCLREL = 1; 
    I2C1CONbits.IPMIEN = 0;   
    I2C1CONbits.A10M = 0;    
    I2C1CONbits.DISSLW = 1;   
    I2C1CONbits.SMEN = 0;     
    I2C1CONbits.GCEN = 0;   
    I2C1CONbits.STREN = 0;   
    I2C1CONbits.ACKDT = 0;    
    I2C1CONbits.ACKEN = 0;   
    I2C1CONbits.RCEN = 0;   
    I2C1CONbits.PEN = 0;
    I2C1CONbits.RSEN = 0;      
    I2C1CONbits.SEN = 0;


// starting the module
I2C1CONbits.I2CEN = 1;

// setting the START CONDITION
I2C1CONbits.SEN = 1;

There is no response. The Start Condition is not executed. The I2C pheripheral is on NON-remappable pins. Whole TrisD register (pin 43 = D9, pin 44 = D10) is set as input (after reset). The pins has pull-ups (3.3 V, 4.7 kOhm). I have also tried to set corresponding bit in ODCD to 1 (digital pin), and 0 (open drain).

Have I missed something? Microcontroller is working fine (UART, PWM, reference clock, ADC, ...).

I would appriciate any guidance.

\$\endgroup\$
  • \$\begingroup\$ Try it by hand ...youtube.com/watch?v=8ZYMrcHm91s \$\endgroup\$ – Spoon Feb 4 '15 at 12:35
  • \$\begingroup\$ I2C1CONbits.PEN doesn't initiate a start condition - that's for a stop. Use SEN for a start. \$\endgroup\$ – brhans Feb 4 '15 at 14:06
  • \$\begingroup\$ Thank you, mistake is corrected but the problem remains \$\endgroup\$ – Martin G Feb 4 '15 at 20:51
  • \$\begingroup\$ Does your I2C1CON.BCL bit ever get set? \$\endgroup\$ – brhans Feb 4 '15 at 21:36
0
\$\begingroup\$

Go the hard way.

Write the test routine for sending start or stop bits and put it in a while loop.

Your main code will look like this.

main
{
initialize i2c();//Configure the I2C module in this function
while(1)
{
 i2c_send(); //Learn how the I2C transmits data and send the data   accordingly.
}

}

Now take an oscilloscope and observe the wave forms.

If have not messed up with configurations or initializations you will see the magic waves.

\$\endgroup\$
  • 1
    \$\begingroup\$ That is the first thing I have tried. I already coded my own functions for filling I2C1TMR (transmission register) and checking, whether data are send and conditions executed. \$\endgroup\$ – Martin G Feb 4 '15 at 12:14
1
\$\begingroup\$

If you are using XC16, you can #include <i2c.h> and try using the OpenI2C1() library call to do the dirty work of configuring the peripheral instead of writing directly to the SFR.

Here is code I use to open I2C1 as a master:

#include <i2c.h>

u16Clk = 39; // specified by OP

OpenI2C1(
    I2C1_ON &
    I2C1_IDLE_CON &
    I2C1_7BIT_ADD &
    I2C1_STR_EN &
    I2C1_SLW_DIS &
    I2C1_GCALL_DIS &
    I2C1_SM_EN &
    I2C1_IPMI_DIS,
    u16Clk
);

Once it's open, you can see if it works by sending a start, sending an arbitrary (non-reserved address), then send a stop (while scoping the lines).

StartI2C1();
MasterWriteI2C1(data);
MasterWaitForIntrI2C1();
StopI2C1();
\$\endgroup\$
0
\$\begingroup\$

Thank you for all the answers.

The module is definitely dead. The code works for I2C2 module just fine.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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