View previous topic :: View next topic |
Author |
Message |
leem
Joined: 16 Jan 2008 Posts: 7
|
Slowing down the i2c Bus |
Posted: Fri Nov 20, 2009 3:16 pm |
|
|
Hey Everyone,
Having a slight problem with a 18f14k50 chip and i2c bus.
I am using complier ver 4.099. I am trying to use the hardware i2c pins on the micro to talk to a chip that specifically says it can only communicate at a speed of no more then 50khz. I have tried numerous ways to set the bus speed. I tried
Code: | #include <18F14K50.h>
#use delay (clock=20MHZ)
#define I2C_SCL PIN_B6
#define I2C_SDA PIN_B4
#use I2C(master, scl=I2C_SCL, sda=I2C_SDA, slow=45000, force_sw, stream=AUTHCHIP)
|
but still doesn't work. I measured clock speed is around 365khz then jumps up to 400khz when trying to talk to the device. Doesn't seem to matter if I specify slow, fast, fast=, slow=, it still runs the speeds listed above. I am pretty new to the i2c but I am thinking there is some other register I have to set. Can someone point me into the right direction on where I need to look to set it.
Thanks
-Lee |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Fri Nov 20, 2009 3:53 pm |
|
|
I took your code and made it into a test program. The CCS manual
doesn't say that different speed settings for the "Slow" parameter are
supported. They might actually be supported, but it's best to just
follow what the manual says. So I changed "Slow" to "Fast" in your code.
I then compiled the program and looked at the .LST file code starting
at address 0004. This is the #use i2c() library code.
The delays for the high and low period of the SCL clock are 10 us each.
The remaining instructions take about 3 us more, giving 23 us total,
which gives a clock speed of about 43.5 KHz. So, I think it should be
working. Are you looking at the SCL pin with your oscilloscope ?
Code: |
0004: MOVLW 08 // Send 8 bits
0006: MOVWF @01
0008: MOVLW 10 // 10 usec delay (50 clocks / 5 clks per usec)
000A: MOVWF @00
000C: DECFSZ @00,F
000E: BRA 000C
0010: BCF LATB.6 // SCL = 0
0012: BCF TRISB.6
0014: MOVLW 10 // 10 usec delay
0016: MOVWF @00
0018: DECFSZ @00,F
001A: BRA 0018
001C: RLCF 06,F // Rotate data byte
001E: BCF LATB.4 // Send 0 or 1 based on data bit
0020: BTFSC STATUS.C
0022: BSF TRISB.4
0024: BTFSS STATUS.C
0026: BCF TRISB.4
0028: BSF TRISB.6 // SCL = 1 (float high)
002A: BTFSS PORTB.6 // Check for clock stretching
002C: BRA 002A
002E: DECFSZ @01,F // Decrement bit count
0030: BRA 0008 // Loop until all 8 bits are sent
|
Code: |
#include <18F14K50.h>
#fuses HS, NOWDT, PUT, BROWNOUT, NOLVP
#use delay (clock=20MHZ)
#define I2C_SCL PIN_B6
#define I2C_SDA PIN_B4
#use I2C(master, scl=I2C_SCL, sda=I2C_SDA, FAST=45000, force_sw, stream=AUTHCHIP)
//======================================
int8 main ()
{
while(1)
{
i2c_write(AUTHCHIP, 0xF0);
delay_us(50);
}
while(1);
} |
|
|
|
leem
Joined: 16 Jan 2008 Posts: 7
|
|
Posted: Fri Nov 20, 2009 4:21 pm |
|
|
I took your code and tried it and low and behold it was actually clocking at 32.33 khz. I have a meter that can measure frequency so yes I am measuring the SCL line clock speed.
Apparently I have some other setting in my code that is affecting the clocking and I will have to look for it.
Playing around with your code sample, I decided to try changing it to force_hw since it has it built in but that makes to clock at 368Khz. So I am guessing that need to do it via software as opposed to hardware.
-Lee |
|
|
FvM
Joined: 27 Aug 2008 Posts: 2337 Location: Germany
|
|
Posted: Fri Nov 20, 2009 5:13 pm |
|
|
Force_hw is working as well, down to about 40 kHz (fast =40000) with a 20 MHz crystal. |
|
|
leem
Joined: 16 Jan 2008 Posts: 7
|
|
Posted: Fri Nov 20, 2009 6:04 pm |
|
|
Can you give me the code you used exactly to get that. I just tried pcm's code and changed it FAST=40000 and force_hw and I still am getting over 300Khz clocking on the SCL line.
-Lee |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Fri Nov 20, 2009 6:25 pm |
|
|
I changed my test program to "Force_hw" and compiled it with vs. 4.099.
There appears to be a bug in the start-up code. This is the init code that
CCS puts at the beginning of main(). It sets up the hardware i2c baud
rate register (to 0x6F), but then it clobbers it later by setting it to 0xFF.
Quote: |
0022: CLRF TBLPTRU
0024: BCF RCON.IPEN
0026: CLRF FSR0H
0028: CLRF FSR0L
002A: BSF TRISB.6
002C: BSF TRISB.4
002E: MOVLW 6F
0030: MOVWF SSPADD
0032: MOVLW 29
0034: MOVWF SSPCON1
0036: BSF SSPSTAT.SMP
0038: BCF SSPSTAT.CKE
003A: MOVLW FF
003C: MOVWF SSPADD
003E: MOVLW 28
0040: MOVWF SSPCON1
0042: MOVLW 00
0044: MOVWF ANSEL
0046: BCF ADCON1.NVCFG0
0048: BCF ADCON1.NVCFG1
004A: BCF ADCON1.PVCFG0
004C: BCF ADCON1.PVCFG1
004E: MOVWF ANSELH
0050: CLRF FB4 |
However, there is a work-around. You can manually set the i2c baud
rate (in Force_hw mode) by calling the i2c_speed() function at the
start of main(). That will reset the baud rate to the correct value.
This occurs after the start-up code has been executed, so it fixes the
problem with the incorrect baud rate.
Code: |
.......... i2c_speed(AUTHCHIP, 45000);
0052: MOVLW 6F
0054: MOVWF SSPADD
0056: MOVLW 29
0058: MOVWF SSPCON1
005A: BSF SSPSTAT.SMP
|
|
|
|
leem
Joined: 16 Jan 2008 Posts: 7
|
|
Posted: Fri Nov 20, 2009 7:31 pm |
|
|
So from what you said It should be this
Code: | #include <18F14K50.h>
#fuses HS, NOWDT, PUT, BROWNOUT, NOLVP
#use delay (clock=20MHZ)
#define I2C_SCL PIN_B6
#define I2C_SDA PIN_B4
#use I2C(master, scl=I2C_SCL, sda=I2C_SDA, FAST=45000, force_hw, stream=AUTHCHIP)
//======================================
int8 main ()
{
i2c_speed(AUTHCHIP, 45000);
while(1)
{
i2c_write(AUTHCHIP, 0xF0);
delay_us(50);
}
while(1);
} |
Tried it at still clocking at 368khz for me
-Lee |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Fri Nov 20, 2009 8:01 pm |
|
|
Well, I don't have the hardware. All I can do is look at the .LST file. |
|
|
leem
Joined: 16 Jan 2008 Posts: 7
|
|
Posted: Fri Nov 20, 2009 9:18 pm |
|
|
That cool, figured you didn't. Just reporting what I am experiencing. I appreciate the help.
-Lee |
|
|
FvM
Joined: 27 Aug 2008 Posts: 2337 Location: Germany
|
|
Posted: Sat Nov 21, 2009 4:20 am |
|
|
I wonder, how measure the I2C clock frequency with a frequency meter, because it comes in short bursts.
Did you ever see the fast clocking with an oscilloscope?
According to the datasheet, the wrong SSPADD setting of 0xff would give a low rather than a high frequency. |
|
|
electron_plumber
Joined: 18 Jun 2008 Posts: 2 Location: Washington, USA
|
SSPADD rewrite... |
Posted: Fri Jul 09, 2010 1:33 am |
|
|
I have a very similar issue - hardware I2C running WAY slow. (The direction you would expect.) I too found that SSPADD was getting clobbered, so I manually reset it by directly writing to SSPADD. However, some values worked, while others just locked it up (i.e. the port stopped sending data entirely).
I will try using i2c_speed tomorrow, and see if that helps. It hadn't occurred to me that the other registers might need to be reloaded as well...
I am using the latest version of the compiler, and I'm a bit surprised that this hasn't been fixed yet...
Anyhow, glad to see I wasn't the only one with this problem... |
|
|
electron_plumber
Joined: 18 Jun 2008 Posts: 2 Location: Washington, USA
|
i2c_speed(400000) doesn't work either! |
Posted: Fri Jul 09, 2010 1:22 pm |
|
|
i2c_speed(400000) did not solve my problem! Looking at the listing file (including the one above), it puts 0x29 into SSPCON1 which is a disallowed value (at least on the PIC18F14K50 I am using...).
I manually went in and set SSPADD=0x0c (~400kHz on a 20MHz clock) and SSPCON1=0x28 (the 8 coresponding to master mode). That seems to have solved my problem! |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Fri Jul 09, 2010 4:02 pm |
|
|
I tested your code with vs. 4.109 and found the same problems.
You should report these bugs to CCS support. Show them the
.LST file in your email, and point out where it's programming
the registers incorrectly. |
|
|
|