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

Truncated match.
PICList Thread
'Which Port For I2C?'
1998\01\13@124913 by Charles Laforge

picon face
Okay... you guys have been great so far; don't die on me now. :)

I will be using a 16C84 (or F84) to experiment with my I2C rountines. Is
there a prefered port to use for the two lines?  The docs say port A is
bi-directional I/O.  Port B is bi-directional I/O with optional
programable pull-up.  RB4 - RB7 have interupt on change.  Would RB4 -
RB7 be my best bet as the PIC would be able to sense when the master is
trying to send data?

If you can help I'd love to hear from you.

Charles

______________________________________________________
Get Your Private, Free Email at http://www.hotmail.com

1998\01\13@135459 by Stevenson, Brad

flavicon
face
Hi Charles,

I'm new on this list, so I haven't seen all of the previous messages on
this topic. I may be repeating info that has already been discussed, but
maybe there will be something useful for you.

First I'll make a couple of assumptions:
1) Your obviously writing 'slave' code.
2) Using a PIC with a slave i2c port is not an option.

Anyway, I would say which pins you use is probably dependent on the rest
of your application. If all this micro has to do is be an i2c slave you
probably don't have to use external interrupts. You can just poll the
pins. If your application is pretty busy doing other things most of the
time, you might want to use an interrupt (on the SCL pin maybe).

I recently wrote some 'master' i2c code to access a serial eeprom. For
the two pins (sda and scl) needed, I set the corresponding bits in the
port data registers to zero, and set the corresponding tristate
registers to inputs (I guess this is the standard way of doing i2c in a
pic). I pulled the two pins to Vcc with 10k resistors. To create a logic
1, I did nothing. To create a logic zero, I changed the tristate
register bit to be an output (since the data bit was set to zero).

One 'gotcha' to be careful of if you're doing it this way: avoid using
read-modify-write commands (such as bsf, bcf) on any of the other pins
on the same port as your i2c pins. Since your i2c pins are set as inputs
and pulled high (with the data bits set to zero), a read modify write
command will 'see' the logic one's on the inputs during the read, and
change your data bits from 0 to 1 on the write portion of the opcode.
The sympton you'll see when trouble shooting is: absolutely nothing will
happen on your port pins when you call your i2c routines.

I hope that helped and  wasn't completely redundant.

Brad Stevenson, CET
The DPL Group - Telecom Techniques
506-635-1055 or 1-800-561-8880
http://www.dpl.ca

> {Original Message removed}

1998\01\13@143913 by )

flavicon
face
In my application, I used RB2 for SDATA and RB3 for SCL. I found that I
still had to add an external pull up resistor (10k - 15k) on SDATA, even
with pull ups on. I kept thinking that it should work without an
external pull up, but without it, I only saw a flat line on a scope.

The routines are similar to the Microchip App note (bit banging).

-Frank


Frank Richterkessing

spam_OUTFRANK.RICHTERKESSINGTakeThisOuTspamAPPL.GE.COM



{Quote hidden}

1998\01\14@052557 by Frank A. Vorstenbosch

flavicon
face
On Wed 14 Jan, "Stevenson, Brad" <.....STEVENSBKILLspamspam.....DPL.CA> wrote:

> I recently wrote some 'master' i2c code to access a serial eeprom. For
> the two pins (sda and scl) needed, I set the corresponding bits in the
> port data registers to zero, and set the corresponding tristate
[snip]
>
> One 'gotcha' to be careful of if you're doing it this way: avoid using
> read-modify-write commands (such as bsf, bcf) on any of the other pins
> on the same port as your i2c pins. Since your i2c pins are set as inputs
> and pulled high (with the data bits set to zero), a read modify write
> command will 'see' the logic one's on the inputs during the read, and
> change your data bits from 0 to 1 on the write portion of the opcode.
> The sympton you'll see when trouble shooting is: absolutely nothing will
> happen on your port pins when you call your i2c routines.

When the I2C bus is idle, the two pins float, which means that it is
then safe to use BSF/BCF on other pins of the port.  Before you send the
next I2C message you have to clear the two I2C data bits agin -- I
usually have that code in the subroutine which generates the I2C start
condition.  One thing NOT to do there is this:

SendI2CStart   bcf    SDA       ; clear both data bits
              bcf    SCL       ; ** WRONG **
              .
              .
              etc.

The second instruction will of course set the SDA data bit to high
again <scenes of programmer hitting his head to the wall>.
Instead, my I2C file goes like this:

SendI2CStart   movlw   ~(SDA_MASK|SCL_MASK)    ; make sure output lines are low
              andwf   I2CPORT                 ; when outputs are enabled

              <20us delay here for benefit of slow PIC slaves>
              bsf     status_rp
              bcf     SDA                     ; pull SDA low while SCL is high
              bcf     status_rp
              <20us delay here for benefit of slow PIC slaves>
              retlw   0

The delays in the start condition allow PICs running at 4MHz to detect
start conditions more easily; when the PIC sees one, it then can read the
I2C message at high speed.  I'm using this code in all my PICs now so
that in the future I won't have to replace any I2C code when I want to
add a PIC slave to a device.

Frank
------------------------------------------------------------------------
Frank A. Vorstenbosch                           Phone:  +44-181-636 3391
Electronics & Software Engineer                 Home:   +44-181-544 1865
Eidos Technologies Ltd., Wimbledon, London      Mobile:  +44-976-430 569

1998\01\14@094833 by Keith Howell

flavicon
face
> [snip lot of text about using bsf and bsf for twiddling SDA and SCL]

No, it really is okay to use bsf and bcf to twiddle SDA and SCL.
I do.
I twiddle the bits in the TRIS registers.
AFAIK this does not disturb other bits in the register, or I/O bits.
So I2C events do not disturb other I/O bits.

The disturbances discussed previously only happen if you twiddle
the PORT register bits.
Which you should not be doing, because
the I2C signals are open collector!
You should be twiddling the TRIS bits,
and keeping the corresponding PORT bits low.

You have to avoid other I/O bits disturbing the I2C PORT bits.

BTW, the last chap's I2C file looks flaky for a start.
Look at the code:
> SendI2CStart
>       movlw   ~(SDA_MASK|SCL_MASK)   ; make sure output
>                                       ; lines are low
>       andwf   I2CPORT                 ; when outputs are enabled

There's nothing to guarantee the timing.
The I2C spec says the start condition is SCL falling when SDA is low.
AND the time between SDA falling and SCL falling must be
at least 4 microseconds! I use something like this:

I2C_SCL_HI      MACRO
       bsf     TRISC, I2C_SCL          ; Set SCL high
       ENDM
I2C_SCL_LO      MACRO
       bcf     TRISC, I2C_SCL          ; Set SCL low
       ENDM
I2C_SDA_HI      MACRO
       bsf     TRISC, I2C_SDA          ; Set SDA high
       ENDM
I2C_SDA_LO      MACRO
       bcf     TRISC, I2C_SDA          ; Set SDA low
       ENDM
doWait3microseconds     MACRO
       nop
       nop
       nop
       ENDM


So that you do a START like so:

       page1                           ; meaning data page
       I2C_SDA_LO                      ; SDA goes low during SCL high
       doWait3microseconds             ;
       I2C_SCL_LO                      ; Start clock train
       page0                           ; return with data page == 0

1998\01\14@100940 by Najemy, Daniel

flavicon
face
I'm triyng to use the SSP Module's I2C implementation. It seems like a
lot of the hardware should be implemented within the SSP module - but
Microchip doesn't provide much help in documentation.

Daniel Najemy - Numaliine Power Systems

> {Original Message removed}

1998\01\14@104312 by Roger Anderson

flavicon
face
Lots of good ideas for I2C.  I am wondering about the pull ups
required when using a PIC 16C/F84.  Someone said that
turning on the port B weak pull-ups won't work.  Is this so?
and if so why doesn't it work?

Roger H. Anderson
Bioengineering
The University of Iowa
54 Medical Research Facility
Iowa City, IA  52242-1183

1998\01\14@183638 by )

flavicon
face
Uh, that would be me. I said that I found I had to use (in my design) a
~12k pull up resistor on SDA (none on SCL) in order to get things to
work. I never had the time to investigate why. It was my first PIC
project and my first experience with I2C. Perhaps one of the list
members with more experience knows for sure. I do know my design worked
well and we used for several months in the lab.

-Frank


Frank Richterkessing

EraseMEFRANK.RICHTERKESSINGspam_OUTspamTakeThisOuTAPPL.GE.COM



{Quote hidden}

1998\01\15@053006 by Frank A. Vorstenbosch

flavicon
face
On Thu 15 Jan, Keith Howell <KILLspamkeithhKILLspamspamARCAM.CO.UK> wrote:
> Subject: Re: Which Port For I2C?
>
> No, it really is okay to use bsf and bcf to twiddle SDA and SCL.
> I do. I twiddle the bits in the TRIS registers.
> AFAIK this does not disturb other bits in the register, or I/O bits.
> So I2C events do not disturb other I/O bits.

True, but it is _the_other_way_around_ that might be giving headaches,
like having an interrupt routine twiddle some bits on the same port as
you're using for I2C, right in the middle of an I2C transaction.

[snip]

> BTW, the last chap's I2C file looks flaky for a start.
> Look at the code:

Look again.

> > SendI2CStart
> >       movlw   ~(SDA_MASK|SCL_MASK)   ; make sure output
> >                                       ; lines are low
> >       andwf   I2CPORT                 ; when outputs are enabled
>
> There's nothing to guarantee the timing.
> The I2C spec says the start condition is SCL falling when SDA is low.
> AND the time between SDA falling and SCL falling must be
> at least 4 microseconds!

[snip the macros]

> So that you do a START like so:
>
>         page1                           ; meaning data page
>         I2C_SDA_LO                      ; SDA goes low during SCL high
>         doWait3microseconds             ;
>         I2C_SCL_LO                      ; Start clock train
>         page0                           ; return with data page == 0

But you never set the state of the data register!!
OK, since you are so eager to point out that my code is wrong, here is
the full routine (heavily macro'd as usual).  Note the two 20us delays;
these are to make life easier on PIC slaves, and also go guarantee the
required I2C bus timing.  This code runs on 12 and 14 bit PICs.


; +---------------------------------------------------------------------+
; |                                                                     |
; |   Send I2C start condition.                                         |
; |                                                                     |
; +---------------------------------------------------------------------+
;
; In:   -
;       SDA and SCL floating high
; Act:  Generate a slow but otherwise normal I2C start condition.
; Out:  W=0
;       SDA pulled low, SCL floating high

SendI2CStart    movlw   ~(SDA_MASK|SCL_MASK)        ; make sure output lines are
low
               andwf   I2C_PORT                    ; when outputs are enabled

               if CLOCK_RATE>=600000
               ldw     CounterI2C,CLOCK_RATE/(3*200000)
               loop    CounterI2C,$                ; 20us delay
               endif

               ifdef __14BIT__
               bsf     status_rp
               bcf     SDA                         ; pull SDA low while SCL is
high
               bcf     status_rp
               else
               ifdef TrisCopy
               ld      TrisCopy
               andlw   ~SDA_MASK
               str     TrisCopy
               else
               movlw   SCL1_SDA0_TRIS
               endif
               tris    I2C_PORT                    ; pull SDA low while SCL is
high
               endif

               if CLOCK_RATE>=600000
               ldw     CounterI2C,CLOCK_RATE/(3*200000)
               loop    CounterI2C,$                ; 20us delay
               endif

               retlw   0


; +---------------------------------------------------------------------+

Note:   LDW is MOVLW <constant>:STR <reg>
       LD is MOVF <reg>,w
       STR is MOVWF <reg>
       LOOP is DECFSZ <reg>:GOTO <label>


Of course, there is nothing in my code to protect the I2C from rogue
interrupt routines doing RMW instructions on the same port.

Frank
------------------------------------------------------------------------
Frank A. Vorstenbosch                           Phone:  +44-181-636 3391
Electronics & Software Engineer                 Home:   +44-181-544 1865
Eidos Technologies Ltd., Wimbledon, London      Mobile:  +44-976-430 569

1998\01\15@074043 by Keith Howell

flavicon
face
Frank A. Vorstenbosch wrote:

> True, but it is _the_other_way_around_ that might be giving headaches,
> like having an interrupt routine twiddle some bits on the same port as
> you're using for I2C, right in the middle of an I2C transaction.
Yes, you're quite right old bean. I did mention
"You have to avoid other I/O bits disturbing the I2C PORT bits."

> But you never set the state of the data register!!

Well, I do (just once) in the initialisation phase of my system.
I omitted this from my posting because twiddling the data register
bits is not done elsewhere in my general I2C code.
What you are doing is putting them in the right state (low)
at the start of an I2C message.
Which is probably easier than making every other routine
(that uses that port) leave things tidy for the I2C bits.


> OK, since you are so eager to point out that my code is wrong,

No offence meant.
I just thought you were doing the I2C bus by twiddling
the PORTB bits, rather than the TRISB bits.
I couldn't see if SDA was defined so that
       bcf     SDA
expanded to
       bcf     PORTB,2
or
       bcf     TRISB,2

> Of course, there is nothing in my code to protect the I2C from
> rogue interrupt routines doing RMW instructions on the same port.

I find a lot of difficulty lies with having to get lots of things
running together, properly choreographed.
I think I will eventually have to write some foundation code
like a real-time kernel that can manage processes and block/unblock
them. Time to dig out my M.Sc. notes I think! :-O

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