8

I've installed RPi.GPIO. It doesn't support I²C yet, but can I use it to bit bang I²C?

I would just need the Raspberry Pi to be the master.

Peter Mortensen
  • 1,984
  • 2
  • 14
  • 17
John La Rooy
  • 11,847
  • 9
  • 46
  • 74
  • 1
    Why not add support? The chip supports it and there are drivers around. Seems silly to bit bang it! – Alex Chamberlain Jul 18 '12 at 21:15
  • How about this: http://raspberrypi.stackexchange.com/questions/1190/how-to-make-raspbian-load-the-i2c-dev-module-on-boot-up – Brian Carlton Aug 22 '12 at 16:23
  • I want to do bit banging using Python. Did you succeed to do that? Using RPi.GPIO and switching the pin between GPIO.OUT/False (down state) and GPIO.IN (out state) makes the trick? – Pygmalion Feb 11 '18 at 11:40

1 Answers1

4

As one of the commenters pointed out, using a native/hardware I²C implementation is much preferred, as the produced I²C signals would be much nicer (read: compatible). The CPU load would be negligible as you do not have to busy wait to produce delays, and often faster (400 kHz is one standard speed).

However, bit-banging is useful sometimes, when you need to produce a particular signal pattern or when simply hardware I²C does not exist or or is not suitable for some reason. A nice example of bitbanging code can be found in the Wikipedia article I²C.

A simpler design, and preferred one, if performance is not the most critical, is to follow the algorithm from the Wikipedia article (and comments below). You need to pick two lines, one for SCL one for SDA, provide suitable pull-up resistors. Remember that idle line state is "high". You would configure the lines as "out" and toggle them any way you need. For polling the lines for ACK or clock stretch you should set them high, switch to "input" mode and then check the line state. The steps to produce start, stop and data states are in the Wikipedia link above.

If you need to get that last bit of performance out of your design, you can use four pins, SDA in, SDA out, SCL in and SCL out. The 'in' ones are permanently set to input and 'out' ones permanently set to output. This saves you the calls to switch pin modes.

[Edited to first offer simpler design as pointed out in the comments below.]

mikijov
  • 141
  • 3
  • 2
    I think you can use just two IO pins with the pullups. Instead of setting pins high and low you simulate open drain by switching a pin between out(low) and in(high via the pullup). – John La Rooy Jul 21 '12 at 11:02
  • 2
    This is a bad answer but I'm new and don't have enough rep to downvote. You can do it with 2 I/Os the way gnibbler says. I2C is a multidrop bus, and driving it high with a push-pull output while another device drives it low will cause a short-circuit. – stevenvh Jul 21 '12 at 11:35
  • 1
    @gnibbler You are absolutely correct regarding how to drive the lines. I will edit my answer as soon as I have a minute. However, the "in" pins are needed if you want to detect ACK or clock-stretch, both of which are needed for any more serious communication. – mikijov Jul 21 '12 at 17:59
  • 1
    @stevenvh I never suggested push-pull, and I will edit my answer to be more explicit. But the additional pins are needed to detect ACK and clock-stretch. – mikijov Jul 21 '12 at 18:00
  • 1
    @MikiJ, I don't think you need additional pins, you can just look at the value on the pin when it's switch to an input. That's what they do in the code on wikipedia. Look for the `while (read_SCL() == 0) { // Clock stretching` – John La Rooy Jul 21 '12 at 21:05
  • 1
    @MikiJ - BroadCom doesn't like us to see the datasheet, so I don't know about the BCM2835, but most controllers only *have* push-pull outputs. Like *gnibbler* says you don't need separate input pins. Drive the output low with the pin as output low, and release the bus (high) by switching the pin to input. Then you can read data, ACK, and clock-stretching. – stevenvh Jul 22 '12 at 06:19
  • 1
    Mostly agree. I admit I come from a non-hobby scenario where performance was very important. In, out and pin setting oprtations are very slow for my usage. Each operation is at least a kernel call, sometimes a task switch... On an older chip, I was reaching only 140KHz I2C frequency, and that was without checking for clock stretch. If peformance is not that important (or if the latest chips+kernel have improved performance) then the simpler design is preferred, I agree. – mikijov Jul 23 '12 at 13:55