PCF8574.java included with Java Stamp IDE
m817
Posts: 11
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.
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
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
If the latter then change to; this.addr = 0x070 | ((devAddr & 0x07) << 1);
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.
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.
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
·