Shop OBEX P1 Docs P2 Docs Learn Events
Small I2C driver — Parallax Forums

Small I2C driver

deSilvadeSilva Posts: 2,967
edited 2008-01-22 17:27 in Propeller 1
I have looked through the current I2C drivers and found them all - well - quite corpulent...
So I decided to post my "small footprint driver" - including a test program exercising the well known PCF8574A port expander. (Note the PCF8574 has a different device address; I have A-types as they were a bargain....)

It is still "version 1", so I should be grateful for problem reports..
'' MPE_I2C_001 (mod)
'' Minimal I2C driver 2008-01 by deSilva


' ----- The following section is a test routine
 _clkmode        = xtal1 + pll8x
 _xinfreq        = 10_000_000
  EEPROM = $A0
  DEVICE = $70
  LEDPIN = 25

PUB checkOut |  x , status
{
 This checks my minimal I2C driver, using a PCF8574A port expander
 When an LED is connected from LEDPIN to Vcc it will indicate a device error.  

 +───A───────┐
 +───B─────┐ │
 +───C───┐ │ │
 +─  ─┐ │ │ │
          │ │ │ │
  + D C I │ │ │ │
 ┌┴─┴─┴─┴─┴─┴─┴─┴┐
 │(8574)  7 6 5 4│
 │      0 1 2 3  │
 └┬─┬─┬─┬─┬─┬─┬─┬┘ 
  - - -     -
          C B A

 I/O 4,5,6,7 of the PCF will be configured as OUTPUT (0)
 I/O 0,1,2,3 as INPUT / active low
 Connect LEDs to 4,5,6 (resistors to high, as this is a kind of open drain chip)
 Each of them will light when I/O 1,2,3 resp. are set LOW
 As those pins are just opposite, I reversed the bits to make it look better

 I/O 0 is special: As long as it's low a 1.5 kHz signal is output at I/O 7
 and I/O 4,5,6 are all three on.

 Note that inputs are HIGH by default as with the old TTLs  
}
 
  REPEAT
    REPEAT 
       engage 
       status := snd(DEVICE)
       status |= snd(%0000_1111|(x><8))  ' 8 I/O pins: 
                                         ' 0: output (driven low)
                                         ' 1: input (tri-state)
      'release

       engage     
       status |= snd(DEVICE+1)
       x := rcv
      'release
       DIRA[noparse][[/noparse]LEDPIN]:=status
    WHILE x&1


    engage 
    snd(DEVICE)
    REPEAT 1500
       snd(%1000_1111)
       snd(%0000_1111)
    release     


     
' ===========Here starts deSilva's small I2C driver
CON
  SCL = 28
  SDA = 29
 
PUB engage
' Pulls SDA to LOW whilst CLK is HIGH
  
   dira[noparse][[/noparse]SCL]~~
   outa[noparse][[/noparse]SDA]~  
  'The former two instructions need be done only once, if all is o.k.

   outa[noparse][[/noparse]SCL]~~   
   dira[noparse][[/noparse]SDA]~    ' Pulse SDA; HIGH by pullup (default)
   dira[noparse][[/noparse]SDA]~~   ' Enable = LOW
   outa[noparse][[/noparse]SCL]~    ' Keep SCL LOW
  
PUB snd(by) : status 
' Send a byte (and get status: 0: ACK  1: NAK)

  by := (!by) >< 8             ' Reverse bits and invert pattern
  REPEAT 8       
    dira[noparse][[/noparse]SDA] := by
    outa[noparse][[/noparse]SCL]~~                ' Transfer on rising edge
    by >>= 1
    outa[noparse][[/noparse]SCL]~ 
 
' Returns "acknowledge bit": 0 = ACK, 1 = NAK.
  dira[noparse][[/noparse]SDA]~            ' release SDA
  outa[noparse][[/noparse]SCL]~~           ' puls-in ACK
  status := ina[noparse][[/noparse]SDA]
  outa[noparse][[/noparse]SCL]~            ' keep CLK low
  
PUB release
' Assert stop condition.
' SDA transits from LOW to HIGH whilst SCL is HIGH
  dira[noparse][[/noparse]SDA]~~           ' LOW
  outa[noparse][[/noparse]SCL]~~
  dira[noparse][[/noparse]SDA]~            ' release SDA (HIGH)
   
PUB rcv : val
' Get a byte
  REPEAT 8
    outa[noparse][[/noparse]SCL]~~        ' Request bit
    val <<= 1
    val |= ina[noparse][[/noparse]SDA]
    outa[noparse][[/noparse]SCL]~         ' Keep CLK low

PUB nak
' Send ackbit
  dira[noparse][[/noparse]SDA]~~           ' LOW
  outa[noparse][[/noparse]SCL]~~           ' Pulse SCL
  outa[noparse][[/noparse]SCL]~            ' keep CLK low
  dira[noparse][[/noparse]SDA]~            ' release SDA
  
PUB ack
' Send ackbit
  dira[noparse][[/noparse]SDA]~          ' HIGH
  outa[noparse][[/noparse]SCL]~~         ' Pulse SCL
  outa[noparse][[/noparse]SCL]~          ' keep CLK low 
  dira[noparse][[/noparse]SDA]~          ' release SDA

Post Edited (deSilva) : 1/22/2008 12:46:14 AM GMT

Comments

  • RaymanRayman Posts: 14,162
    edited 2008-01-22 01:07
    Nice, but I'm not sure it's any better than my stripped down version of Mike Green's code:
    http://www.rayslogic.com/propeller/Programming/i2c/i2c.htm
  • RaymanRayman Posts: 14,162
    edited 2008-01-22 01:12
    Well, it may be a bit smaller...

    PS:· The PCA9554·is a newer device with the same pinout but better in several ways...

    Post Edited (Rayman) : 1/22/2008 1:21:22 AM GMT
  • deSilvadeSilva Posts: 2,967
    edited 2008-01-22 01:38
    @Rayman: I am sure, your driver is fine. My idea was more educational: To have it all "in a nutshell". It had also furthered my own understanding.. As I am just converting it to ASM; I needed a reference to program it straight forwardly.

    I am aware that the PCA9554 is newer, but I miss its true advantages. The 8574 is extremely versatile and most simple to program... And as I said, I got a lot of them for little money smile.gif
  • RaymanRayman Posts: 14,162
    edited 2008-01-22 13:25
    The 8574 is much simpler... I was going to stick with it, but I found it had a fatal flaw for me: Bad commands make the I/O on all pins go bezerk. I'm trying to recall what made it go crazy... I think it was trying to do a read while one of the pins was set low... The project I needed it for had to be bullet-proof, so I had to switch to PCA9554.
  • deSilvadeSilva Posts: 2,967
    edited 2008-01-22 17:27
    Just thinkinkg about it: The 8574 behaves very similar as the Propeller without an OUTA register!!
    You have an INA, giving you all the pin states, and a DIRA, allowing you to select either high impedance, or driving an external resistor low @15 mA.

    For some projects it could be a problem not being able to drive from high.. Also 100 kHz might be slow. As seen I can generate 1.5 kHz square waves at the moment. Even with machine code this will not exceed 5 kHz (100kHz clock /10 clocks /2). The 9554 on the other hand could sample 40 kHz.
Sign In or Register to comment.