# Using C18 software I²C libraries, is there any smart way to set bus speed?

After encountering problems with hardware I²C as described here, I decided to try software I²C using MPLAB C18 compiler's library functions. Fortunately, the libraries do generate good-looking signal at the pins, but I'm a bit worried about the timings used by them.

The documentation and source files of the C18 compiler do not explicitly say for which bus speed and oscillator frequency the delays in functions are set, so I'm wondering if there's a better way to adjust them than diving through source files and calculating by hand the number of delays I need.

• I wouldn't go near C18 IIC libraries. I don't know what sort of tradeoffs they chose for me. IIC is too simple to take a chance on some canned libraries. Even if you do, by the time you verify they really do what they want and understand exactly how, you could have written it yourself. Go to embedinc.com/pic/dload.htm and install the PIC Development Tools and PIC 18F USB Framework releases. My generic firmware IIC module of the U1EX firmware will be in the SOURCE > USB, called U1EX_IIC.ASPIC. It is easy to customize, and you can see exactly what is going on. – Olin Lathrop Apr 12 '12 at 17:52
• @Olin Lathrop Thanks for the link. Looks interesting. – AndrejaKo Apr 12 '12 at 18:09
• @OlinLathrop what sort of tradeoffs are you referring to? I guess my general lack of a deep understanding of I2C made me go for the C18 I2C library, and it sure seems to work fine for my serial EEPROM. But now I've got to take a look at your lib to see what sort of customization is possible. :) – Dave Oct 15 '12 at 4:55
• @Dave: If you don't understand IIC, then this is the first thing you need to fix before trying to use it. Unlike on large systems with a OS layer and lots of library calls, you have no business using something you don't understand on small systems. In the end you'll spend more time trying to get canned libraries to do what you want to do, chasing bugs that don't make sense, or even find field failures later, all because you missed a important detail that you got away with on the small quantity of prototypes with their limited use cases. – Olin Lathrop Oct 15 '12 at 15:35
• @Dave: Maybe they did it right for the case you care about, but by the time you check it you could have written the code yourself and then you know exactly what it is doing. Also, on these small systems it's a bad idea to blindly use layers without understanding what is going on underneath. – Olin Lathrop Oct 16 '12 at 12:31

Typically what I will do is create a macro that defines my system clock frequency.

#define GetSytemClock() (41666667ul)

Then create a macro using the formula in the datasheet for calculating clock speed.

#define GetSSPBRG(i2c_clk) (((GetSystemClock()/i2c_clk)/4)-1)

Pass the i2c clock rate (Hz) you want to the macro GetSSPBRG() and it will provide the correct value for the SSPxADD register.

Initializing communication requires checking all your assumptions. . . CHeck signal integrity at both ends using two probes A-B in differential mode. Use comm mode ferrite beads or core to ensure no stray CM noise gets converted to differential signal. Ensure impedance is terminated properly and levels are good. . Is the clock on RTC tuned with caps? and set properly? Did you allow a long enough reset for the clock to startup. Is it running at the right rate? Check both ends and choose some test patterns like U=55h = 01010101 3=33h= 00110011 verify with scope you are sending ok.

THen send the general call command 00h.

THen call for pizza.

• Actually this answer isn't very relevant to the question as it assumes that there is actually a correctly working $I^2C$ bus that needs troubleshooting. The problem is that with no settings the clock frequency, in my case, is 125 kHz and I need to set it to 100 kHz. Some sources say that I should use the SSPADD register even in software mode to set the clock frequency, but I didn't have enough time to confirm that. – AndrejaKo Apr 17 '12 at 22:42