'**************************************************************************** '* I2C SUBROUTINES * '**************************************************************************** 'Author: Jordan Haralampopoulos 'E-mail: jordanis@ix.netcom.com ' ' 7/17/97 hacked to use only the 24c65 ' Dave Forrest dforrest@virginia.edu ' 'Version: 0.1 (more to come) 'Devices supported: 'Microchip 24C65 8Kbytes EEPROM ' 'Note_1 : 10K pull-up resistors used on the I2C data & clock lines ' ' To drive an LED you connect the anode through a resistor to ' +5V and the cathode to the PCF8574 pin. Drive the pin low ' to turn the LED on. To test for switch closure you put a ' pull-up resistor from the input pin to +5 and connect the switch ' between the input pin and ground. ' ' 'Note_3 : You must consult the Data Sheets of any I2C component ' that you want to use. You have to follow the sequences ' for read & write religiously. Speed is not critical. ' 'Note_4 : There is a bit variable named i2ack. After you call the ' ackrx you can test this bit to see if you received an ' acknowledge and act accordingly. I don't test it because ' so far I didn't have any nacks coming back. This may change. '******************************************************************* greenlight con 0 high greenlight func var byte ' function identifier i2addr var word '16 bit mem address i2addr1 var i2addr.highbyte '8 MSBs of mem address i2addr0 var i2addr.lowbyte '8 LSBs of mem address temp1 var byte 'temporary byte variable temp2 var nib ' temporary nibble variable i2data var byte 'byte for I2C I/O i2ack var bit 'I2C acknowledge bit i2dt con 15 'I2C data pin i2clk con 9 'I2C clock pin i2memWR con %10100000 'I2C mem write control byte chip address 000 ' 1010aaa0 where aaa = A2, A2, A0 of the 24C65 i2memRD con %10100001 'I2C mem read control byte chip address 000 ' 1010aaa1 where aaa = A2, A2, A0 of the 24C65 memtop con 8191 'I2C EEPROM memory top pause 20 'give the system time to settle 'Some stupid tests to demo the routines 'Remove the remark to run each test 'goto test3 'goto test4 ' Test3 writes a value to the 24C65 EEPROM and then reads back ' to verify test3: i2addr=125 'pick an address 0-8191 temp1=133 'pick a value 0-255 gosub wrmem 'go write debug bin ? i2ack,cr 'got ack=%0 (aknowledged) if i2ack=%1 then test3 'if not do it again temp1=0 'clear temp1 i2addr=125 'go to the same address gosub rdmem 'read and verify debug dec ? temp1,cr temp1 = 5 gosub pulser stop ' pulser flashes the light temp1 times ' pulser if temp1 = 0 then ret pulsout greenlight,5000 nap 5 debug ?temp1 temp1 = temp1 -1 goto pulser ret: return ' Test4 read & displays sequentialy all the values from the starting ' address that you supply to the end of memory (memtop) test4: i2addr=0 'start from the beginning 'max value is 8190 gosub rdmemsq 'do the sequential read stop ' This is the dosomething routines. In this case it displays ' the memory values trough debug. It could be a serial output ' to something else. dosomething: pause 100 'give some time to see the value debug dec ? temp1,cr return '**************************** '* I2C Routines begin here * '**************************** '********************************************** '* (wrmem) write a byte to I2C memory routine * '********************************************** 'Before you call wrmem 'Load i2addr with memory address word 'Load temp1 with variable byte to store '********************************************** wrmem: func = 1 gosub i2start 'send start contition i2data=i2memWR 'send wr command gosub i2tx gosub ackrx i2data=i2addr1 'send high address gosub i2tx gosub ackrx i2data=i2addr0 'send low address gosub i2tx gosub ackrx i2data=temp1 'send data byte gosub i2tx gosub ackrx gosub i2stop 'send stop condition return '*********************************************** '* (rdmem) read a byte from I2C memory routine * '*********************************************** 'Before you call rdmem 'Load i2addr with memory address word to retrieve from 'Returns the value from address in temp1 '****************************************************** rdmem: func = 2 gosub i2start 'send start condition i2data=i2memWR 'send wr command gosub i2tx gosub ackrx i2data=i2addr1 'send high address gosub i2tx gosub ackrx i2data=i2addr0 'send low address gosub i2tx gosub ackrx gosub i2start 'again start condition i2data=i2memRD 'send rd command now gosub i2tx gosub ackrx gosub i2rx 'get byte temp1=i2data 'put it in temp1 gosub i2stop 'send stop condition return '************************************* '* (rdmemsq) Sequential I2C mem read * '************************************* 'Before you call rdmemsq: 'Load i2addr with starting memory address word 'Gets constant memtop (top of memory) 'Returns value from memory in temp1 in the subroutine dosemething 'Example: 'This is used to upload data stored in the EEPROM to a PC 'through the serial port. Much faster than the single byte read '***************************************************************** rdmemsq: func =3 gosub i2start 'send start condition i2data=i2memWR 'send wr command gosub i2tx gosub ackrx i2data=i2addr1 'send high address gosub i2tx gosub ackrx i2data=i2addr0 'send low address gosub i2tx gosub ackrx gosub i2start 'send start condition again i2data=i2memRD gosub i2tx gosub ackrx for i2addr=i2addr to memtop-1 'loop to memtop-1 shiftin i2dt,i2clk,0,[i2data] 'get data 'shifin instead of gosub 'to i2rx speeds up things shiftout i2dt,i2clk,1,[%0\1] 'send ack temp1=i2data 'put data in temp1 gosub dosomething 'do something with the data next shiftin i2dt,i2clk,0,[i2data] 'get the last byte gosub i2stop 'send stop condition temp1=i2data 'put last byte in temp gosub dosomething 'do something with the data return '********************************* '* (i2start) I2C start contition * '********************************* i2start: high i2dt 'I2C data line high high i2clk 'I2C clock line high low i2dt 'I2C data line low return '******************************* '* (i2stop) I2C stop contition * '******************************* i2stop: low i2dt 'I2C data line low high i2clk 'I2C clock line high high i2dt 'I2C data line high return '******************************************** '* (i2tx & i2rx) I2C byte tensmit & receive * '******************************************** i2tx: shiftout i2dt,i2clk,1,[i2data] 'shift out byte to I2C return i2rx: shiftin i2dt,i2clk,0,[i2data] 'shift in byte from I2C return '****************************************************** '* (acktx & ackrx) I2C acknowledge transmit & receive * '****************************************************** acktx: shiftout i2dt,i2clk,1,[%0\1] 'send acknowledge to I2C return ackrx: shiftin i2dt,i2clk,0,[i2ack\1] 'receive acknowledge from I2C if i2ack = 0 then ret debug "ack failed " debug bin ?i2ack debug hex ?i2data nap 7 return