Searching \ for 'I2C Serial EEPROM Problem...' in subject line. ()
Make payments with PayPal - it's fast, free and secure! Help us get a faster server
FAQ page: www.piclist.com/techref/i2cs.htm?key=i2c
Search entire site for: 'I2C Serial EEPROM Problem...'.

Truncated match.
PICList Thread
'I2C Serial EEPROM Problem...'
1998\10\22@050720 by Radboud Verberne

flavicon
face
Hi,

I'm sorry for the previous message which did not have a subject.

I'm trying to interface a 24c02 to a PIC16c62A... I thought it wouldn't be
that difficult but problably i'm doing something wrong... The I2C DOES
acknoledge the adress, but after i've done a write command the 24c02 does'nt
ack.... (Also not after a 65ms delay (TMR0)...
Can anyone check the code?
;---------------------------------------------------------------------------
;---------------------------------------------------------------------------
;*************************************************************************
;               I2C Routines
;*************************************************************************
i2cdelay
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
return
;-----------------------Make Stop Condition on i2c bus----------------------
i2cstop
bcf PORTC, SDA          ; SDA is Low
nop
bsf SCL                 ; SCL is high
call i2cdelay           ; delay
bsf PORTC, SDA          ; SDA is high
return
;---------------------------------------------------------------------------
;-----------------------Make Start Condition on i2c bus---------------------
i2cstart
bsf PORTC, SDA          ; SDA Line is High
nop
bsf SCL                 ; SCL is high
call i2cdelay           ; call a delay
bcf PORTC, SDA          ; SDA is low
nop
nop
bcf SCL                 ; Scl is low
return
;---------------------------------------------------------------------------
;--------------------------------Acknoledge---------------------------------
i2cack
bcf PORTC, SDA          ; SDA is Low
nop
bsf SCL                 ; SCL is High
call i2cdelay           ; Delay
bcf SCL                 ; SCL is Low
return
;---------------------------------------------------------------------------
;-------------------------------No Acknoledge-------------------------------
i2cnoack
bsf PORTC, SDA          ; SDA is High
nop
bsf SCL                 ; SCL is High
call i2cdelay           ; Delay
bcf SCL                 ; SCL is Low
return
;---------------------------------------------------------------------------
;-------------------------------Check for Acknowledge-----------------------
i2ccheckack
bsf STATUS, RP0         ; Select Bank 1
bsf TRISC, SDA          ; SDA Line is an input now
bcf STATUS, RP0         ; Select Bank 0
bsf SCL                 ; SCL is High
call i2cdelay           ; Delay
btfsc PORTC, SDA        ; Is the SDA Line Low?
call i2cerror           ; Error slave did not acknowledge!
bcf SCL                 ; SCL is Low
bsf STATUS, RP0         ; Select Bank 1
bcf TRISC, SDA          ; SDA Line is an output now
bcf STATUS, RP0         ; Select Bank 0
return
;---------------------------------------------------------------------------
;--------------------------I2C Error Detected, Powerdown--------------------
i2cerror
bsf ALO                 ; Set the Alarm Osc.
call updatebit5         ; Update bit 5
call displayerror       ; Write "Error" on display
call i2cstop            ; Stop the data on i2cbus
movlw 0x10              ; Load w with 0x10 (dec. 16)
movwf delaycount        ; Place it in delay count
call wait4timer         ; Delay 16 * 65.536 ms = 1.048 sec
bsf OFF1                ; Set the off signal
call updatebit3         ; Powerdown the Nokia
return
;---------------------------------------------------------------------------
;-----------------------------Output data (Must be in W!)-------------------
i2ccharout
movwf txbyte            ; Place w in Txbyte
movlw 0x08              ; 8 bits in a byte
movwf bitcount          ; Place it in bitcount
writemorebits
rlf txbyte, f           ; Rotate txbyte trough carry
bsf PORTC, SDA          ; Set the SDA Line Initally High
btfss STATUS, C         ; Is the carry bit Set?
bcf PORTC, SDA          ; No, SDA Low
nop
bsf SCL                 ; SCL is High
call i2cdelay           ; Delay
bcf SCL                 ; SCL is Low
decfsz bitcount, f      ; Done with 8 bits?
goto writemorebits      ; No, do some more
call i2ccheckack        ; Check for acknowledge
return
;---------------------------------------------------------------------------
;-----------------------------Read Char-------------------------------------
i2ccharin
bsf PORTC, SDA          ; SDA is High
movlw 0x08              ; Load w with 0x08
movwf bitcount          ; Place it into bitcount
clrf txbyte             ; CLear txbyte
bsf STATUS, RP0         ; Select bank 1 for TRIS reg.
bsf TRISC, SDA          ; SDA Line is an Input now
bcf STATUS, RP0         ; Go Back to bank 0
readmorebits
bsf SCL                 ; SCL is High
rlf txbyte, f           ; Rotate txbyte trough carry
call i2cdelay           ; Delay
btfsc PORTC, SDA        ; Is the SDA Line High?
bsf txbyte, 0           ; Yes, Set LSB
bcf SCL                 ; SCL is Low
decfsz bitcount, f      ; Done with 8 bits?
goto readmorebits       ; No, do some more
bsf PORTC, SDA
bsf STATUS, RP0         ; Select bank 1 for TRIS reg.
bcf TRISC, SDA          ; SDA is an output
bcf STATUS, RP0         ; Go Back to bank 0
movfw txbyte            ; Read data in w
movwf i2cdata           ; Read data in i2cdata
return
;---------------------------------------------------------------------------
;-------------------------------Write a Byte--------------------------------
i2cwritebyte                    ; Data to be written must be in i2cdata!
call i2cstart           ; Generate A start condition on the i2c bus
movlw 0xA0              ; Send 1010000 (Write the adress)
call i2ccharout         ; Put it on the bus
movfw i2cadress         ; Load the adress
call i2ccharout         ; Put it on the bus
movfw i2cdata           ; TX data in W
call i2ccharout         ; Put it on the bus
call i2cstop            ; Stop i2c transfer
call i2cdelay
call i2cdelay
movlw 0x02
call wait4timer
return
;writenotcomplete
;        call i2cstart           ; Generate A start condition on the i2c bus
;        movlw 0xA0              ; Send 1010000 (Write the adress)
;        movwf txbyte            ; Place w in Txbyte
;        movlw 0x08              ; 8 bits in a byte
;        movwf bitcount          ; Place it in bitcount
;writemore
;        rlf txbyte, f           ; Rotate txbyte trough carry
;        bsf PORTC, SDA          ; Set the SDA Line Initally High
;        btfss STATUS, C         ; Is the carry bit Set?
;        bcf PORTC, SDA          ; No, SDA Low
;        bsf SCL                 ; SCL is High
;        call i2cdelay           ; Delay
;        bcf SCL                 ; SCL is Low
;        decfsz bitcount, f      ; Done with 8 bits?
;        goto writemore          ; No, do some more
;
;        bsf STATUS, RP0         ; Select Bank 1
;        bsf TRISC, SDA          ; SDA Line is an input now
;        bcf STATUS, RP0         ; Select Bank 0
;        bsf SCL                 ; SCL is High
;        call i2cdelay           ; Delay
;        clrw                    ; W = 0x00
;        btfsc PORTC, SDA        ; Is the SDA Line Low?
;        goto writenotcomplete   ; Error slave did not acknowledge!
;        bcf SCL                 ; SCL is Low
;        bsf STATUS, RP0         ; Select Bank 1
;        bcf TRISC, SDA          ; SDA Line is an output now
;        bcf STATUS, RP0         ; Select Bank 0
;        call i2cstop
;        call i2cdelay
return
;---------------------------------------------------------------------------
;-------------------------Random read a location----------------------------
i2crandomread
call i2cstart           ; Generate A start condition on the i2c bus
movlw 0xA0              ; Send 1010000 (Write the adress)
call i2ccharout         ; Put it on the bus
movfw i2cadress         ; Load the adress
call i2ccharout         ; Put it on the bus
call i2creadcurrent     ; Read the data
call i2cstop            ; Stop condition on i2c bus
call i2cdelay
movfw i2cdata
return
;---------------------------------------------------------------------------
;---------------------------Read the current adress-------------------------
i2creadcurrent
call i2cstart           ; Generate A start condition on the i2c bus
movlw 0xA1              ; Send 1010-0001(read)
call i2ccharout         ; Put it on the bus
call i2ccharin          ; Read the byte
call i2cnoack           ; No Acknoledge
call i2cstop            ; Stop on i2c bus
movfw i2cdata
return
;---------------------------------------------------------------------------
Greetz,
       Radboud Verberne
ICQ     : 918640 (I Seek You)
HAM  : PE1RUH

1998\10\22@073435 by Keith H

flavicon
face
Radboud Verberne wrote:

> I'm trying to interface a 24c02 to a PIC16c62A... I found them a bit of a bugg
er to get working,
but only because there's more to them than
I saw at first glance.

> after I've done a write command the 24c02 doesn't
> ACK.... That's right, they don't respond to an address
while they are internally in programming time
(about 10 ms). They are 'off-line'.
You have to retry until they re-appear.

> Also not after a 65ms delay (TMR0)Hmm, worrying. Do they stop responding forev
er?
I guess not, else you'd assume you had a dead
device.

> Can anyone check the code?

When I had problems, I found these chips insist
you follow the I2C spec rigourously. You must
NACK the last byte you read, for example.

Also I see that when you negate an I2C signal,
you bsf the trisc reg bits and wait >= 5 us,
but you assume it has risen then proceed.

The I2C spec says you should wait until it has,
so that slaves can wait-state the master by
holding SCL low if they wish. Check the spec!
It's easy to do, instead of 5 nops,
use 3 nops and 2 instructions for the looping:

; 2 instructions, 5 us minimum at 4MHz.

I2C_SCL_doWaitForRisingEdge     macro
               doWait3microseconds     ; 3 us. Allow for rise time. 3 Nop codes
       local   doWait                  ; NB: must read in data page 0
doWait
       btfss   PORTC,I2C_SCL           ; 1 us. Skip if SCL is high
       goto    doWait                  ; 1 us. Wait if SCL is low
       endm

Take care hopping between the data page containing PORTC and TRISC.

1998\10\22@225541 by Paul Penrose

flavicon
face
I didn't see anything obviously wrong with your code, but I did not look
closely at it. Some general things though:
Remember that I2C is a multidrop interface which should have a passive
pull-up to generate logic 1's on both clock and data. In practice if you
only have a single slave that does not clock stretch (EEPROMs in general
don't) you can drive the clock high and low actively.
You should use an open drain to drive these lines which have passive
pull-ups. This allows you to simply wire-or two pins together, configure
one as input, and the other as output and avoid changing the tris register
for every byte transfered. This takes four PIC pins instead of two, but
the simplification in the code is worth it.
An oscilloscope is an excellent investment for this kind of work. A DSO
works best, of course.
Get the phillips spec for I2C, it's much better than what comes with the
EEPROM.

1998\10\23@160730 by Radboud Verberne

flavicon
face
>I didn't see anything obviously wrong with your code, but I did not look
>closely at it. Some general things though:
I've added some delay's at a few points and changed the start condition...
Now it is working OK.

>Remember that I2C is a multidrop interface which should have a passive
>pull-up to generate logic 1's on both clock and data. In practice if you
>only have a single slave that does not clock stretch (EEPROMs in general
>don't) you can drive the clock high and low actively.

Don't know where I read this but it was say that you should use a 10K
resistor for 100Khz and 2k2 for a 400Khz bus.

>You should use an open drain to drive these lines which have passive
>pull-ups. This allows you to simply wire-or two pins together, configure
>one as input, and the other as output and avoid changing the tris register
>for every byte transfered. This takes four PIC pins instead of two, but
>the simplification in the code is worth it.

I don't have any pins left...

>An oscilloscope is an excellent investment for this kind of work. A DSO
>works best, of course.
Ehh, I'm just a student... I don't have the money to buy a scope...
Unfortually

>Get the phillips spec for I2C, it's much better than what comes with the
>EEPROM.

I'll have a look, Thanx.


'I2C Serial EEPROM Problem...'
1998\12\31@131241 by John Payson
flavicon
face
|Then I had problems, I found these chips insist
|you follow the I2C spec rigourously. You must
|NACK the last byte you read, for example.

The requirement to NAK the last byte read is a function of physics
as much as of protocol.  Following an ACK, the EEPROM will drive the
data wire per the first bit of the next byte.  If that bit happens
to be zero, there will be no way to change the data wire while the
clock line is high other than by clocking data bits until the end of
the byte is reached or a "1" bit is encountered.

By the way, I've found that I2C works much more easily if the ACK
is regarded as an early part of the read command (i.e. generate an
ACK before each byte, rather than after).  If this is done, then
the read procedure doesn't have to know whether another byte is
going to be needed.

The write byte procedure is then:
 Assert data.  Raise and lower clock.
 Output first data bit.  Raise and lower clock.
 ...
 Output last data bit.  Raise and lower clock.
 Release data.

The read procedure is:
 Raise and lower clock.  Read first data bit.
 ...
 Raise and lower clock.  Read last data bit.
 Raise and lower clock.  Read ack/nak bit.

 Note that following a write operation, an ACK will be sitting on
 the data bus.

The start procedure is:
 Release data.
 Lower and raise clock until data reads high.
 Assert data.

 Note that at the end of the start procedure the clock is "high".
 This means that when the part is next written, the first "raise
 and lower clock" will merely assert the clock without generating
 a rising edge first.

The stop procedure is the same as the start procedure, except that
data is not asserted afterward.

I've found that restructuring the I2C start/write/read routines in
this way is a good way to simplify things.  The one potential dis-
advantage I've observed is that following any write operating the
data line will be externally held low until the next transaction,
and following any read or write the clock will be held low.  The
recommended pullups won't draw huge amounts of power, but in a bat-
tery-powered device it may be good to leave the I2C bus idle when-
ever possible (probably reduces the likelihood of glitches).


Attachment converted: wonderland:WINMAIL.DAT (????/----) (00024CA3)


'I2C Serial EEPROM Problem...'
1999\01\03@235438 by Tjaart van der Walt
flavicon
face
John Payson wrote:
>
> |Then I had problems, I found these chips insist
> |you follow the I2C spec rigourously. You must
> |NACK the last byte you read, for example.
>
> The requirement to NAK the last byte read is a function of physics
> as much as of protocol.  Following an ACK, the EEPROM will drive the
> data wire per the first bit of the next byte.  If that bit happens
> to be zero, there will be no way to change the data wire while the
> clock line is high other than by clocking data bits until the end of
> the byte is reached or a "1" bit is encountered.
>
> By the way, I've found that I2C works much more easily if the ACK
> is regarded as an early part of the read command (i.e. generate an
> ACK before each byte, rather than after).  If this is done, then
> the read procedure doesn't have to know whether another byte is
> going to be needed.

This is how I do it as well. The difference is, you probably
do it in 1/10 of the code than what I do it in ;)

When I write a byte, the startup sequence check for
an ACK to proceed, so I check for ACK before i write,
not afterwards. I get write speeds consistently
faster than the specs on most chips.

BTW : has someone got more info on the Philips PCF8583's timer
and alarm functions? The datasheet is very incomplete. I can't
figure out if the day-of-week is related to the date at all.

--
Friendly Regards          /"\
                         \ /
Tjaart van der Walt        X  ASCII RIBBON CAMPAIGN
spam_OUTtjaartTakeThisOuTspamwasp.co.za  / \ AGAINST HTML MAIL

|--------------------------------------------------|
|                WASP International                |
|R&D Engineer : GSM peripheral services development|
|--------------------------------------------------|
|SMS .....tjaartKILLspamspam@spam@sms.wasp.co.za  (160 chars max)|
|     http://www.wasp.co.za/~tjaart/index.html     |
|Voice: +27-(0)11-622-8686  Fax: +27-(0)11-622-8973|
|          WGS-84 : 26¡10.52'S 28¡06.19'E          |
|--------------------------------------------------|

More... (looser matching)
- Last day of these posts
- In 1999 , 2000 only
- Today
- New search...