CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to support@ccsinfo.com

I2C fast problems
Goto page 1, 2  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
Tim Bobbins
Guest







I2C fast problems
PostPosted: Sat Jul 28, 2007 3:43 pm     Reply with quote

I am having I2C speed problems. The trouble is I cannot reach any speed but the slow 100kHz - which is posing a big problem for my current application. I am using the ex_slave.c ccs example file with my PIC877a. For the master side I am using the code below (a copy of the code found elsewhere in this forum). This pic is a 873a. Both PICs use a 20Mhz external crystal.

The communication works perfectly using the FAST=100000 statement. If I alter it even by one, communication halts. Typical values I have tried are 200000, 400000. A buffer chip recommended in this forum has even been inserted with no change.

I am at a loss to explain, much less fix this problem. Can someone please shed some light on this?
I am using CCS compiler 4.032, and reverted back to 3.247 with no success with either.

Code:
#include <16F873A.h>

  #fuses HS                         // High speed external oscillator
//  #fuses WDT                        // Using the watchdog timer
  #fuses PUT                        // Using the power up timer
  #fuses NODEBUG                    // Do not use debug mode
  #fuses NOBROWNOUT                 // Do not use brownout detect
  #fuses NOLVP                      // Do not use low voltage programming
  #fuses NOCPD                      // Do not use code protect
  #fuses NOWRT                      // Do now use write protect

#use delay(clock=2000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS)
#use i2c(Master, sda=PIN_C4, scl=PIN_C3,FORCE_HW,FAST=200000)

//====================================
void main()
{
int8 data;

while(1)
{
// Write the letter 'B' to the slave board.
i2c_start();
i2c_write(0xA0);
i2c_write(0x00);
i2c_write('B');
i2c_stop();

// Read from the slave board and display the data.
i2c_start();
i2c_write(0xA0);
i2c_write(0x00);
i2c_start();
i2c_write(0xA1);
data = i2c_read(0);
i2c_stop();
printf("read %c \n\r", data);
}

}
Ttelmah
Guest







PostPosted: Sun Jul 29, 2007 4:11 am     Reply with quote

Big mistake in code as posted, is the #use delay statement...
You have the clock as _2MHz_, not 20MHz.
If the RS232 is working, you need to check your crystal...
At 2MHz, timing will be very borderline on the receive. It typically takes about 30 instructions to arrive in an interrupt handler. Add the handler itself, and for even the simple demo, you can easily be talking in excess of 100 instructions. At 2MHz, 0.2mSec. Using the only I2C clock available (with a 2MHz clock, the hardware can do 500000bps, or 125000bps - I suspect the compiler is selecting the first, as soon as the rate you request goes above 125000). At 500000bps, a byte, only takes 16uSec....

Best Wishes
Tim Bobbins
Guest







i2c
PostPosted: Tue Jul 31, 2007 3:05 pm     Reply with quote

Yup. thanks for that. I am using the '20M' value now so its unmistakable.
That did the trick. Spending too long at looking at the same code over and over sometimes guarantees you dont find the obvious.
Tim Bobbins
Guest







optimal speeds
PostPosted: Wed Aug 08, 2007 5:07 pm     Reply with quote

Although I did get the communications speed running to near 250kHz, anything over would prove unreliable. The goal is to reach the high speed of 450kHz.
Has anyone been successful at doing this?

Once again:
873A-> master 877A -> slave. both operate at 20Mhz
both are connected with a short 1" wire using a 1k pullup (experiemented with a bus driver too)

I am using a 50us delay between writes. No delay results in no communication.
Ttelmah
Guest







PostPosted: Thu Aug 09, 2007 5:12 am     Reply with quote

It is important to understand the limitations of the BRG on the MSSP. At 20MHz, the only rates available to you, are:
5MHz
1.25MHz
312.5KHz

Unless you use Timer2.
If you want to go faster than 312KHz, the next 'step', is 1.25Mhz, and if you select this, the chip will give this speed. However if you select rates below this, the fastest it can give you is the 312KHz rate.

Best Wishes
ckielstra



Joined: 18 Mar 2004
Posts: 3680
Location: The Netherlands

View user's profile Send private message

PostPosted: Thu Aug 09, 2007 6:04 am     Reply with quote

Ttelmah wrote:
It is important to understand the limitations of the BRG on the MSSP. At 20MHz, the only rates available to you, are:
5MHz
1.25MHz
312.5KHz
This is true for the older PIC models. The 16F87xA types have a baudrate generator using the formula
Code:
Baud Rate = Fosc / (4 * (SSPADD + 1) )
Giving the possible rates of:
5.00MHz
2.25MHz
1.67MHz
1.25MHz
1.00MHz
833kHz
etc

Selecting 450kHz the compiler will give you either 417kHz or 455kHz.
Tim Bobbins
Guest







need for speed
PostPosted: Thu Aug 09, 2007 11:05 am     Reply with quote

Thank-you for the responses.

I still am not clear as to why I cannot achieve >250kHz. Now, I can not verify I am getting those speeds, as I do not have a scope to verify. However, the simple test code works at FAST=100000 through FAST=250000. Anything above these it becomes more and more unreliable.

Has anyone been able to achieve the 'high' speed of 400kHz or greater using two PICs to communicate?

Different pull up resistor values have been tried, as well as the LTC1694 chip with no differences.

I am still at a loss.
Ttelmah
Guest







PostPosted: Thu Aug 09, 2007 12:20 pm     Reply with quote

ckielstra wrote:
Ttelmah wrote:
It is important to understand the limitations of the BRG on the MSSP. At 20MHz, the only rates available to you, are:
5MHz
1.25MHz
312.5KHz
This is true for the older PIC models. The 16F87xA types have a baudrate generator using the formula
Code:
Baud Rate = Fosc / (4 * (SSPADD + 1) )
Giving the possible rates of:
5.00MHz
2.25MHz
1.67MHz
1.25MHz
1.00MHz
833kHz
etc

Selecting 450kHz the compiler will give you either 417kHz or 455kHz.

Read the data sheet again. These rates are only available in I2C mode, not SSP mode. In SSP mode, only the /4, /16 etc., rates are available...
Page 71 of the data sheet. Note that it says the other bit patterns (which allow the extended rates to be selected), are only available in I2C mode.
This is the 'A' data sheet.

Best Wishes
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Fri Aug 10, 2007 12:14 am     Reply with quote

Quote:

Although I did get the communications speed running to near 250kHz,
anything over would prove unreliable. The goal is to reach the high
speed of 450kHz. Has anyone been successful at doing this?

I tested this with two PicDem2-Plus boards with 16F877's running at
20 MHz, with vs. 3.249, and I got the same results. I'll look at it on
Friday with a scope and/or logic analyzer and see what I can find.
GDetienne



Joined: 20 Sep 2003
Posts: 47
Location: Brussel - Belgium

View user's profile Send private message

PostPosted: Fri Aug 10, 2007 2:01 am     Reply with quote

Mister Ckielstra,
could you confirm that the formula is valid for 16F88 and 18F4680 ?
I don't find this information in the data sheet.

Have a nice week end.
Thanks.
Ttelmah
Guest







PostPosted: Fri Aug 10, 2007 2:31 am     Reply with quote

Yes, apologies...

This is an example of trying to multi-task, and having a 'leak' between the tasks.... :-(
Unfortunately, I also post on half a dozen private university groups, and I have been suffering for the last fortnight, from trying to get a person there to understand why he cannot have a 1MHz SPI rate, on a 20MHz crystal. He posted a claim, almost exactly like Ckielstra's post, that the divider was available on latter chips for SPI, and I crossed over, and posted here, forgetting this thread was about _I2C_.

I'd guess the the I2C problem is with the pull up's, and bus capacitance. I think PCM programmer will find that the signals, instead of having square edges, have relatively slow rise times.
It is critical to remember that originally I2C, was only specified to 100K. Then 400K was added, and 'ratified' in the 1995 specifications, with the requirement for slope control on the lines being added, and a reduction in the pull up value (for lower line capacitances), or use of a current source being suggested. For example, on a bus with 100pF capacitance, the maximum pull up resistor value, drops from 8KR, to 3K for 400KHz operation. I'd suspect the boards concerned have a capacitance in this region on the lines, and probably 4K7 pull ups.
Going even faster, pushes this area of the spec yet further, and at 1MHz, active pull-ups, or very low resistances, become necessary.

Best Wishes
Tim Bobbins
Guest







quick info
PostPosted: Fri Aug 10, 2007 9:12 pm     Reply with quote

My coworker apparently has tried the same code, but eliminated the FORCE_HW tag in the #use i2c line. He was easily able to ramp up to 450kHz with no difficulties.
I will try it tomorrow myself.
This is mystifying since you'd think the hardware would do a better job that the software bit banging.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Fri Aug 10, 2007 10:02 pm     Reply with quote

The problem is that the software i2c routines can't go that fast. The
actual SCL clock frequency is much less than the specified speed.

For example, I did a test just now with the following #use statement,
with a 16F877 running at 20 MHz. This will generate software i2c code.
Code:
#use i2c(Master, sda=PIN_C4, scl=PIN_C3, FAST=450000)

I measured 6.4 us between clock edges on SCL. That's about 156 KHz.
We know the slave has no problem with that low of a clock speed.

If you look at the code below and count cycles, it looks like the shortest
path through the main loop is 31 cycles, which is 6.2 us at 20 MHz, and
about 161 KHz. This is the CCS library code for a software i2c write.
Code:

0013:  MOVLW  08
0014:  MOVWF  78

0015:  NOP               
0016:  NOP           
0017:  BCF    07.3
0018:  BCF    21.3
0019:  MOVF   21,W
001A:  BSF    03.5
001B:  MOVWF  07
001C:  NOP
001D:  BCF    03.5
001E:  RLF    23,F
001F:  BCF    07.4
0020:  BTFSS  03.0
0021:  GOTO   028
0022:  BSF    21.4
0023:  MOVF   21,W
0024:  BSF    03.5
0025:  MOVWF  07
0026:  GOTO   02C
0027:  BCF    03.5
0028:  BCF    21.4
0029:  MOVF   21,W
002A:  BSF    03.5
002B:  MOVWF  07
002C:  NOP
002D:  BCF    03.5
002E:  BSF    21.3
002F:  MOVF   21,W
0030:  BSF    03.5
0031:  MOVWF  07
0032:  BCF    03.5
0033:  BTFSC  07.3
0034:  GOTO   037
0035:  BSF    03.5
0036:  GOTO   032
0037:  DECFSZ 78,F
0038:  GOTO   015


I looked at the problem for about 20-30 minutes on Friday morning.
Most of that time was spent setting up the logic analyzer and boards.
I modified the Ex_slave isr to set Pin B0 high at the start, and low at
the end of the isr. I think I was running the master at 100 KHz.
(I don't remember for sure). I noticed that sometimes the slave isr
took up to 82 us to complete. That's not including the 10 us of overhead
in the CCS interrupt dispatcher. So it's really more like 92 us.
There are two places in the isr where a delay could occur. These are
in the i2c_read() and i2c_write() routines. Each one of those has a
tight loop where they poll the BF flag in SSPSTAT.

At that point it required more time that I could commit on Friday. I can
do more on Sunday. It's an interesting problem to find out why there
are limits to the CCS i2c slave code with respect to the SCL clock
speed. If someone else has already researched this problem and
wants to answer, that's fine with me. But if not, I can look at it more
later in the weekend.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Tue Aug 14, 2007 11:51 am     Reply with quote

I looked at this problem some more.

If you increase the Master PIC's SCL clock frequency beyond about
250 KHz, then byte transactions will finish before the end of the Slave isr.
In the Slave PIC, an SSPIF interrupt occurs at the end of each byte that
is transmitted or received. CCS puts a line of code near the end of the
Slave isr which clears the SSPIF flag. So if a byte finishes before
the end of the isr, it will set the SSPIF flag, but then the flag will be
cleared at the end of the isr. The PIC won't see that next interrupt.

One fix for this is to clear the SSPIF flag at the start of the Slave isr
instead of the end. This can be done by adding the NOCLEAR directive
and by calling clear_interrupt() at the start of the Slave isr. Example:
Code:

#INT_SSP  NOCLEAR    // Disable automatic clearing of SSPIF
void ssp_interrupt(void)
{
BYTE incoming, state;

clear_interrupt(INT_SSP);  // Clear SSPIF flag at start of isr

With these changes, I was able to boost the SCL frequency to 350 KHz.
I couldn't go beyond that, because there's another problem with the
i2c_write() section of the isr code that I haven't yet analyzed.

To look at this problem, I used the following logic analyzer.
It's low cost and it has a very useful i2c interpreter.
http://www.pctestinstruments.com/
I also used Pins B0, B1, and B2 as markers for the entire slave isr,
the i2c_read(), and the i2c_write() operations inside the isr, respectively.
I set a pin high at the beginning and low at the end of each operation.
Then the logic analyzer will show the duration of the operation.
Example:
Code:

if(state < 0x80)      // Master is sending data
  {
   output_high(PIN_B1); // *** Start of i2c_read marker
   incoming = i2c_read();
   output_low(PIN_B1);  // *** End of i2c_read marker


The original poster seems to have lost interest in this, so I'm not going
to do any more on it in the short term.
Tim Bobbins
Guest







on the contrary!
PostPosted: Tue Aug 14, 2007 12:28 pm     Reply with quote

No nooo! I have anything but lost interest in this topic. I am loosing sleep over it as a matter of fact. I've been very busy the past few days, so i havent had time to continue my work, plus I didnt feel I had anything else constructive to contribute just yet.

I do not have the needed equipment to diagnose so I am very appreciative of PCM Programmer to take his time to look into this problem!

That is a wonderful find! I will try it tonight.

Was it the I2C hardware, or software method you tried?
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page 1, 2  Next
Page 1 of 2

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group