Michael, Sorry for the late response, but been tough to get to my email since I'm dual-booting with this machine to get to another OS. Thanks for the code. I did write some code of my own a few days ago and comparing some of the differences. - I kept my timing/spacing at 6us for now. - I notice you don't actually check for the ACK. Why not? - Also, you've mentioned 50% duty-cycle requirement. I've been thru some of the I2C specification doc (v2.1), but didn't see anything w.r.t. a duty-cycle requirement. - BTW, your comments for the read_eeprom routine state that you use a STOP in the middle of the routine. It should actually be a START, which you are doing correctly. - I also created a routine to check if the bus is free (both lines HI). - I am planning to check for clock stretching. FWIW, I have not been able to get the EEPROM working yet with my code -- need to do some debugging, which would be much simplified, so I'm considering building a simple logic analyzer. Cheers, -Neil. On Tuesday 20 September 2005 04:25 pm, michael brown scribbled: > #define SCLPIN 0 > #define SDAPIN 1 > #define SCL INDF, SCLPIN ;On PORTA simulating open > collector outputs > #define SDA INDF, SDAPIN ; ditto > > ;------------------------------------------------------ > ; > ; EEPROM routines > ; > ;------------------------------------------------------ > > ; > ; write_eeprom - Write the data in W to the currently selected slot > (eedevice-2, eepointerH-8, eepointerL-8) > ; > > write_eeprom > > movwf eevalue > movlw TRISA ;so we can easily point to > TRISA > movwf FSR > > call I2C_Start > > clrc > rlf eedevice, W ; shift the mess over one > bit > iorlw b'10100000' ; I2C /Write command to > page x of eeprom > call I2C_WriteByte > call I2C_Ack > > movfw eepointerH ; Set address to slot > number > call I2C_WriteByte > call I2C_Ack > > movfw eepointerL ; Set address to slot > number > call I2C_WriteByte > call I2C_Ack > > movfw eevalue ; get data to write > call I2C_WriteByte ; and write it > call I2C_Ack > > call I2C_Stop > > Wait 10 Millisecs, 0 ; wait worst case time > for now > > return > ; > ; read_eeprom - read currently selected location in W and eevalue > ; > > read_eeprom > > movlw TRISA ;so we can easily point to > TRISA > movwf FSR > > ; To read the eeprom, we have to set the address by pretending to do a > write. Once > ; we set the address, we abort the write by doing a STOP instead of > transferring a > ; byte to be written. > > ; Set address by starting a write procedure and then aborting it > > call I2C_Start > > clrc > rlf eedevice, W ; shift the mess over one > bit > iorlw b'10100000' ; I2C /Write command to > page x of eeprom > call I2C_WriteByte > call I2C_Ack > > movfw eepointerH ; Set address to slot > number > call I2C_WriteByte > call I2C_Ack > > movfw eepointerL ; Set address to slot > number > call I2C_WriteByte > call I2C_Ack > > call I2C_Stop ; Abort the write after > setting address pointer > > ; Now read from current address > > call I2C_Start > > clrc > rlf eedevice, W ; shift the mess over one > bit > iorlw b'10100001' ; I2C Read command > call I2C_WriteByte > call I2C_Ack > > call I2C_ReadByte ; Read in a byte > movwf eevalue ; and save it > > call I2C_SendNAck > > call I2C_Stop ; Done > > movfw eevalue > > return > > > > ;--------------------------------------------------- > ; > ; I2C Routines > ; > ;--------------------------------------------------- > > I2C_Start > Wait 5 Microsecs, 0 ; Tsu:start > bcf SDA ; bring data low > Wait 4 Microsecs, 0 ; Thold:start > bcf SCL ; followed by bring clock > low > return > I2C_Stop > bcf SDA ; make sure data is low > Wait 1 Microsecs, 0 ; Tsu:data > bsf SCL ; bring clock high > Wait 4 Microsecs, 0 ; Tsu:stop > bsf SDA ; then data high = STOP > return > I2C_Ack > bsf SCL ; pull clock up > Wait 5 Microsecs, 0 ; Thigh > bcf SCL ; bring clock low again > Wait 5 Microsecs, 0 ; Tlow > return > > I2C_SendAck > bcf SDA ; pull data low for ACK > Wait 5 Microsecs, 0 ; Thigh > bsf SCL ; pull clock up > Wait 5 Microsecs, 0 ; Thigh > bcf SCL ; bring clock low again > Wait 5 Microsecs, 0 ; Tlow > return > > I2C_SendNAck > bsf SDA ; set data line high for > NACK > Wait 5 Microsecs, 0 ; Thigh > bsf SCL ; pull clock up > Wait 5 Microsecs, 0 ; Thigh > bcf SCL ; bring clock low again > Wait 5 Microsecs, 0 ; Tlow > return > > I2C_WriteByte > movwf i2ctemp > movlw d'8' > movwf count > > _i2cwritenextbit > bcf SDA ; make low by default > rlf i2ctemp, F ; get a bit into CARRY > btfsc STATUS, C ; output the CARRY value > bsf SDA > Wait 5 Microsecs, 0 ; settle - Tsu > > bsf SCL ; bring clock high > Wait 5 Microsecs, 0 ; settle - Thigh > > bcf SCL ; and bring it low to > clock out the data > Wait 5 Microsecs, 0 ; settle - Tlow > > decfsz count, F ; see if any more to do > goto _i2cwritenextbit > return > > I2C_ReadByte > clrf i2ctemp > movlw d'8' > movwf count > > bsf SDA ; make SDA an input > (release data line for slave to control) > Wait 5 Microsecs, 0 ; give it time to float > high > > _i2creadnextbit > bsf SCL ; bring clock high > Wait 5 Microsecs, 0 ; Thigh > > clrc ; assume low by default > btfsc PORTA, SDAPIN ; check SDA > setc > rlf i2ctemp, F ; pull in the bit > > bcf SCL > Wait 5 Microsecs, 0 ; let data settle > > decfsz count, F > goto _i2creadnextbit > movfw i2ctemp > return > > > Obviously these routines aren't optimized for speed. If I was worried > about speed, I would have used the built in module. I just wanted to so > if I could get it to work and hopefully learn something. > > > > Whether a particular version is guaranteed to meet "fast" timing may > > > depend on supply voltage, or upon temperature, so if you're system > > Vcc > > > > is less than, for example, 2.5V, you may be forced to use "standard" > > > timing. > > > > Yep. There is also a note near the end of the datasheet about pull-up > > resistors -- smaller values for the fast mode, which is probably so it > > can > > > achieve the required slew rate. > > Yep, this little gem can really screw you up. My advice is to use stiff > resistors (1K or so) until you get it all working then raise the values > and take note as to how real reality is. ;-) > > I've been fairly lucky with my tinkerings using I2C and I haven't had > problems with stuck buses and the like. Of course I haven't implemented > anything I'd call real world with it either. > > > > No limit. From the slave's point of view, the interface is > > > static. It will make no further change on its own. SCL must change > > > to move its state forward. > > > > Gotcha. Only possible exception to that is a small note near the end > > of the > > > datasheet (section 7.3) that indicates that for power reduction, the > > eeprom > > > will power down automatically after a transaction. It can also do > > this > > > during error conditions or timeouts, so too long of a delay between > > changes > > > on the lines may possibly be interpreted as a timeout. I'll check the > > spec > > > to see for sure. > > Hmm, I'd expect it to not matter. It should just "power up" in the same > state it went to sleep in. > > > > ... You can even look at TAA > > > as a minimum for the master: the minimum time that it should wait > > > before sampling the data (beginning of setup time of the master's > > > input latch that will be clocked on rising SCL, if that's how you > > > choose to do it - a software implementation should simply sample > > with > > > > SCL high and let clock low time requirements govern). > > > > "clocked on rising SCL" ? > > Let me clarify this -- Master sends SDA HI (to free that line), then > > sends SCL > > > HI, then back LO, then wait Taa, then the master reads the SDA line. > > ... > > > right? > > No, you read SDA when the clock is high. You never have to wait Taa > time AFAIK. Look at my code, it works. It's for large EEPROMS so it > uses the longish addressing scheme. > > > > The exception is Tr and Tf, which apply to both master and > > > slave, and also the system design (bus wiring capacitance, pull up > > > choice, driver capabilities). Note that for a single master system > > > you can use totem pole drive for SCL. > > > > > > I hope this helps. > > > > > > Bill > > > > Definitely does. Thanks. > > > > Cheers, > > -Neil. > > > > > > > > > > -- > > http://www.piclist.com PIC/SX FAQ & list archive > > View/change your membership options at > > http://mailman.mit.edu/mailman/listinfo/piclist -- http://www.piclist.com PIC/SX FAQ & list archive View/change your membership options at http://mailman.mit.edu/mailman/listinfo/piclist