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 CCS Technical Support

Cannot change speed of I2C

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
DireSpume



Joined: 07 Jan 2013
Posts: 31

View user's profile Send private message

Cannot change speed of I2C
PostPosted: Tue Apr 09, 2013 3:38 pm     Reply with quote

Hi all, I have a problem I hope I can get some advice on. I am using a PIC18F67K22 with compiler version 4.140. I am using I2C in master mode to communicate with a power supply. The communication is working fine. My problem is that I can't get the clock rate to change. No matter what I try, it is stuck at roughly 20 kHz. My PIC is running at 20 MHz.

This is the relevant #use i2c line:
Code:
#use i2c(Master,Fast=400000,sda=PIN_D5,scl=PIN_D6,FORCE_HW,stream=I2C_POWER)

I have tried Fast=100000 also, as well as slow, and none of the options seem to make a difference; clock speed remains at ~20kHz.
The only explanation I can come up with is that it is running in software mode despite the FORCE_HW option. Although even then it is mighty slow.
Any ideas?
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Tue Apr 09, 2013 4:46 pm     Reply with quote

Comment out the #nolist statement at the top of the 18F67K22.h file
and re-compile. Look at the .LST file and look at the code for an
i2c_write() statement. If it calls a routine, look at the routine.
Make sure the compiler .LST file format is set for Symbolic mode.
You should easily be able to to determine if the ASM code is referencing
hardware registers, or if it's doing bit-banging. Then you will know if
it's doing hardware or software i2c.
DireSpume



Joined: 07 Jan 2013
Posts: 31

View user's profile Send private message

PostPosted: Tue Apr 09, 2013 7:23 pm     Reply with quote

Okay, so it looks like it's using the hardware. This is what i2c_write() calls:

Code:

!#use i2c(Master,Fast=400000,sda=PIN_D5,scl=PIN_D6,FORCE_HW,stream=I2C_POWER)
0x403C: BCF SSP2CON1, 7, ACCESS
0x403E: BCF PIR2, 5, ACCESS
0x4040: MOVFF _invar3, SSP2BUF
0x4044: MOVLW 0x2
0x4046: BTFSC SSP2CON1, 7, ACCESS
0x4048: BRA 0x4054
0x404A: BTFSS PIR2, 5, ACCESS
0x404C: BRA 0x404A
0x404E: MOVLW 0x0
0x4050: BTFSC SSP2CON2, 6, ACCESS
0x4052: MOVLW 0x1
0x4054: MOVWF _invar21, ACCESS
0x4056: RETURN 0


So now I really have no clue what is going on.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Tue Apr 09, 2013 11:48 pm     Reply with quote

Quote:

My problem is that I can't get the clock rate to change. No matter what I
try, it is stuck at roughly 20 kHz.


How are you testing the i2c clock speed ? You should do an i2c_write()
continuously in a loop, and look at the SCL2 pin with an oscilloscope.
Example:
Code:

while(1)
  {
   i2c_write(I2C_POWER, 0x01);
   delay_us(50);
  }
DireSpume



Joined: 07 Jan 2013
Posts: 31

View user's profile Send private message

PostPosted: Tue Apr 09, 2013 11:58 pm     Reply with quote

I am using an oscilloscope to measure clock rate on SCL2.
Ttelmah



Joined: 11 Mar 2010
Posts: 19541

View user's profile Send private message

PostPosted: Wed Apr 10, 2013 12:43 am     Reply with quote

Have you something else in use on the chip that relies on 'time'. UART etc.?.

The first thing I'd suspect is that your master oscillator fuse configurations are wrong, or the crystal itself is not working as you think, and the chip is 'dropping back' to the internal oscillator at 1MHz. Hence the I2C is running at 1/20th the rate you are asking for.....

Start with a simple 'toggle a pin' test, and see if this gives the frequency as being for a 20MHz clock or not. If not then you need to tell us how your crystal is wired, what frequency it is (are you using PLL), and your fuses.

Best Wishes
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Apr 10, 2013 1:14 am     Reply with quote

Try changing the i2c speed in main(), using the macro shown in the
example below:
Code:

#include <18F67K22.h>
#fuses HSH, NOWDT, PUT, BROWNOUT
#use delay(clock=20M)   
#use i2c(Master,Fast=400000,sda=PIN_D5,scl=PIN_D6,FORCE_HW,stream=I2C_POWER)

// This macro sets the hardware i2c baudrate for SSP2.
#byte SSP2ADD  = getenv("SFR:SSP2ADD") 
#byte SSP2CON1 = getenv("SFR:SSP2CON1")
#define set_i2c_speed2(baud) \
SSP2CON1 = 0x28; \
SSP2ADD = (((getenv("CLOCK") + (baud *2))/ (baud * 4)) -1)

//==========================================
void main()
{
// Examples of how to call it.
set_i2c_speed2(100000);
set_i2c_speed2(400000);

while(1);
}


This macro first puts the MSSP in a mode such that SSP2ADD is treated
as the baudrate register. Then it calculates the baudrate value, and
rounds off the result, and then it writes it to the baudrate register.

Why not use i2c_speed() ? Because I'm not sure CCS is doing it correctly.
DireSpume



Joined: 07 Jan 2013
Posts: 31

View user's profile Send private message

PostPosted: Wed Apr 10, 2013 12:13 pm     Reply with quote

Even though I was 99.9% sure my oscillator was working as expected, I did double check it as you suggested, Ttelmah. Using FAST_IO, I was able to get 1.25 MHz on an output pin. The assembly code consists is 3 instructions, taking 4 cycles to complete = 20MHz/(4*4) = 1.25 MHz. So now I'm 100% sure the oscillator is working as expected, so that's good. (Incidentally, I did initially have problems with the fuses at first, as you suspected, and it defaulted to the internal oscillator (which is 8 MHz on the 18F67K22)).

PCM Programmer, your method worked! Any idea why the back-door method works but the normal method (i.e. Fast=100000) doesn't? Also, I tried the built-in i2c_speed() function, but that caused it to crash on i2c_start() for some reason. I'm both delighted to have a workaround and annoyed that I don't understand why it's necessary.

Also, when I use your macro at 100000, the actual frequency is around 92 kHz, and at 400000, the actual frequency is 285 kHz. I know the clock frequency has only certain discrete settings, but does this sound about right? Thanks for your help guys!
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Apr 10, 2013 12:38 pm     Reply with quote

Post your test program which you use to measure the SCL clock frequency.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
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