Shop OBEX P1 Docs P2 Docs Learn Events
PCF8574.java included with Java Stamp IDE — Parallax Forums

PCF8574.java included with Java Stamp IDE

m817m817 Posts: 11
edited 2004-12-07 16:18 in General Discussion
This is about the class PCF8574, which was part of the ide stuff downloaded from Parallax's web site.

I don't know if anyone else already found this, but if not.....

I have bread boarded the pcf8574 to the Javelin, along with some LED's to try setting output pins on the pcf8574.

I found that member function isPresent() kept returning false:
········· public class PCF8574
············ public boolean isPresent()

Digging into the class, I found this bug:

· public PCF8574 (I2C bus, int devAddr, int dirs) {
··· this.bus = bus;
··· this.addr = this.addr | ((devAddr & 0x07) << 1);
··· this.dirs = dirs;
· }

This should be:
· public PCF8574 (I2C bus, int devAddr, int dirs) {
··· this.bus = bus;
··· this.addr = (this.addr | (devAddr & 0x07)) << 1;
··· this.dirs = dirs;
· }
The difference being that the entire address should be shifted to the left to make space for bit 8 (R/!W).· This is confirmed by looking at the routine for reading from PCF8574:

· public int read() {
··· int dataIn;
··· bus.start();
··· bus.write(addr | 1);················· // send read address (bit zero is set)
··· bus.read(bus.ACK);··················· // read buffer
··· dataIn = bus.read(bus.NAK);·········· // read current inputs
··· bus.stop();
··· return (dataIn & dirs);
· }
Note the last bit of the address is set high for a read operation.

Comments

  • Peter VerkaikPeter Verkaik Posts: 3,956
    edited 2004-12-05 10:25
    I checked the PCF8574 class.

    In that class the base address (variable addr) is set to 0x40

    which is already shifted 1 bit to the left.

    So addr | ((devAddr & 0x07) << 1) is correct

    unless you changed addr to 0x20.

    With addr being 0x40 the above gives

    0x40, 0x42, 0x44, 0x46, 0x48, 0x4A, 0x4C, 0x4E

    which are the correct addresses for PCF8574.

    regards peter
  • Jack HudlerJack Hudler Posts: 6
    edited 2004-12-06 21:04
    Make sure your using the PCF8574 and not the PCF8574A.

    If the latter then change to; this.addr = 0x070 | ((devAddr & 0x07) << 1);
  • m817m817 Posts: 11
    edited 2004-12-07 01:56
    Well, I am using the A version. I had changed the base address from 0x40 to 0x38, matching the documentation.

    I hadn't considered the address to be pre-shifted.

    I would suggest that hard coding a shifted value is a bit unclear. Better coding
    practice would be:
    final int BaseAddress = ( 0x20 << 1 );
    final int AddrMask = 0x07;

    this.addr = BaseAddress | ((devAddr & AddrMask) << 1);

    Doesn't cost any bytes, but this would be clearer and more maintainable.

    But setting the base address as a constant is also not so good. The base address
    should be passed into the constructor.
  • m817m817 Posts: 11
    edited 2004-12-07 14:42
    Hi, again.
    I changed my mind about passing the base value in the constructor,
    since there are only two possible values.

    Another poster created class PCF8574A extends PCF8574
    and made the base address protected, allowing "A" version to
    change the base addr.
  • Peter VerkaikPeter Verkaik Posts: 3,956
    edited 2004-12-07 16:18
    Take a look at my I2C classes
    http://groups.yahoo.com/group/JavelinCode/files/Javelin%20Stamp%20IDE/lib/stamp/protocol/i2c/

    These work for any I2C device and only require a single definition line
    in your main class.
    For a PCF8574 you would define

    import stamp.protocol.i2c.*;

    static I2CsmFastDevice PCF8574_0 = new I2CsmFastDevice(pinSDA,pinSCL,0x40,32767,1,1);

    You supply the device address as an 8bit value with bit 0 (r/w bit) cleared.
    The device address can be ORed with I2Cdevice.ADDR8 or I2Cdevice.ADDR16
    for devices with up to 256 or 65536 internal addresses.

    The definition for a MC24LS32A eeprom (4096 bytes) is
    static I2CsmFastDevice MC24LC32A_0 = new I2CsmFastDevice(pinSDA,pinSCL,0xA0|I2Cdevice.ADDR16,32,128,53); //5 ms pagewrite delay

    The definition for a DS1307 rtc is
    static I2CsmFastDevice DS1307 = new I2CsmFastDevice(pinSDA,pinSCL,0xB0|I2Cdevice.ADDR8,64,1,1); //64 internal addresses

    The I2CsmFastDevice uses the shiftIn and shiftOut methods
    like the I2C primer used in the PCF8574 class.
    To comply with I2C standards you should use I2CsmDevice instead
    (pins are low outputs or inputs)

    regards peter

    ·
Sign In or Register to comment.