' ========================================================================= ' ' File....... I2C PCF8591P.BS2 ' Purpose.... PCF8591P A/D & D/A converter demo for a BS2/BS2e/BS2sx ' Author..... Chris Vecchio, www.noisemantra.com ' ' {$STAMP BS2} ' {$PBASIC 2.5} ' ' ========================================================================= ' -----[ Program Description ]--------------------------------------------- ' ' This program can set the analog output of the PCF8591 ' and read the 4 analog inputs of the PCF8591 over the I2C bus ' It includes "bit banging" subroutines to support I2C communications ' using a BS2 BASIC Stamp (which does not support I2CIN and I2COUT commands) ' -----[ I/O Definitions ]------------------------------------------------- SDA PIN 0 ' I2C serial data line SCL PIN 1 ' I2C serial clock line ' -----[ Constants ]------------------------------------------------------- Ack CON 0 ' acknowledge bit Nak CON 1 ' no ack bit ' -----[ Variables ]------------------------------------------------------- i2cWork VAR Byte ' work byte for TX routine i2cData VAR Byte ' data byte for TX routine i2cAck VAR Bit ' Ack bit from device AnalogValues VAR Byte(4) 'array to retrieve analog input values y VAR Byte x VAR Byte freq VAR Word ' -----[ Initialization ]-------------------------------------------------- #IF ($stamp >= BS2P) #THEN #ERROR "Use I2COUT and I2CIN!" #ENDIF ' -----[ Program Code ]---------------------------------------------------- 'PCF8591 demonstration loop 'increment analog output (using y) 'repeated read analog inputs and print values in debug window DO y=y+1 i2cData = y 'put output value in i2cData GOSUB AnalogOut GOSUB GetAnalog FOR x = 0 TO 3 DEBUG DEC AnalogValues(x)," " NEXT DEBUG CR 'freq = 20*AnalogValues(1) 'FREQOUT 3,10,freq PAUSE 100 LOOP END '################################################################# ' *** Byte to D/A *** AnalogOut: 'write the byte in i2cData to the D/A converter GOSUB I2C_Start 'send Start i2cWork = %10010000 'address chip 000, last bit 0=write GOSUB I2C_TX_Byte i2cWork = %01000000 'enable output and no auto increment GOSUB I2C_TX_Byte i2cWork = i2cData 'write d/a value GOSUB I2C_TX_Byte GOSUB I2C_Stop 'stop I2C communications RETURN ' *** Fill Array with Bytes from 4 A/D inputs *** GetAnalog: 'read the 4 A/D converters GOSUB I2C_Start 'send Start i2cWork = %10010000 'address chip, last bit 0=write GOSUB I2C_TX_Byte i2cWork = %01000101 'enable output and auto increment 'i2cWork = %01000010 'enable output, no auto increment, read just channel 2 GOSUB I2C_TX_Byte GOSUB I2C_Stop 'stop I2C communications FOR x=0 TO 3 GOSUB I2C_Start 'send Start i2cWork = %10010001 'address chip, last bit 1=read GOSUB I2C_TX_Byte GOSUB I2C_RX_Byte_Nak AnalogValues(x) = i2cWork GOSUB I2C_Stop NEXT RETURN ' -----[ Subroutines ]----------------------------------------------------- ' *** Start Sequence *** I2C_Start: ' I2C start bit sequence INPUT SDA INPUT SCL LOW SDA DO : LOOP UNTIL (SCL = 1) ' wait for clock release LOW SCL RETURN ' *** Stop Sequence *** I2C_Stop: ' I2C stop bit sequence LOW SDA INPUT SCL INPUT SDA RETURN ' *** Transmit Byte *** I2C_TX_Byte: SHIFTOUT SDA, SCL, MSBFIRST, [i2cWork\8] ' send byte to device SHIFTIN SDA, SCL, MSBPRE, [i2cAck\1] ' get acknowledge bit 'DEBUG "ack=",BIN i2cAck, CR RETURN ' *** Receive Byte *** I2C_RX_Byte_Nak: i2cAck = Nak ' no Ack = high SHIFTIN SDA, SCL, MSBPRE, [i2cWork\8] ' get byte from device SHIFTOUT SDA, SCL, LSBFIRST, [i2cAck\1] ' send ack or nak RETURN