Small I2C driver
deSilva
Posts: 2,967
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..
Post Edited (deSilva) : 1/22/2008 12:46:14 AM GMT
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
http://www.rayslogic.com/propeller/Programming/i2c/i2c.htm
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
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
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.