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

How do you set FM+ (1MHz) I2C for PIC24FJ32GU205??

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



Joined: 25 Mar 2009
Posts: 47

View user's profile Send private message

How do you set FM+ (1MHz) I2C for PIC24FJ32GU205??
PostPosted: Tue Jan 23, 2024 10:18 am     Reply with quote

Hello all,

I have been using my HW I2C port on my PIC24FJ32GU205 without issues up to fast mode (400kHz) but as soon as I switch speed to 1MHz, it tops out at about 570.342kHz. I am using the "i2c_speed(1000000) function (which works with 100000 and 400000.

I know this device is capable of operating in FM+ 1MHz but I don't know if the CCS compiler is capable of handling the higher clock speed.

Here's main code:
Code:

#include <FMPlusIC.h>
#include <stdio.h>

void main()
{
   char selection, data1;
   
   do{
   i2c_speed(I2C_PORT2, 1000000);
    printf("I2C Speed = 1000.000KHz \r\n");
         
    //Read TCA9536 input port register(0x00)
    i2c_start(I2C_PORT2);
    i2c_write(I2C_PORT2,0x82);
    i2c_write(0x00);              //command byte for input port reg.
    i2c_start(I2C_PORT2);
    i2c_write(I2C_PORT2,0x83);
    data1=i2c_read(I2C_PORT2, FALSE);
    i2c_stop(I2C_PORT2);
    printf("TCA9536 Input Port Register:0x%2X\r\n\r\n", data1);
   delay_ms(500);
   }
   while(TRUE);
}


Here's include code:
Quote:

#include <FMPlusIC.h>
#device ICSP=1
#use delay(clock=32MHz,int=8000000, USB_FULL,restart_wdt)

#FUSES WDT //Watch Dog Timer

#pin_select U1TX=PIN_A10
#pin_select U1RX=PIN_B13
#use rs232(baud=115200,parity=N,xmit=PIN_A10,rcv=PIN_B13,bits=8,stream=PORT1,restart_wdt)

#use i2c(MASTER, I2C2, FAST=1000000, RESTART_WDT, stream=I2C_PORT2)
#use i2c(MASTER, SCL=PIN_B8, SDA=PIN_B9, SLOW, RESTART_WDT, stream=I2C_PORT2)
Code:
temtronic



Joined: 01 Jul 2010
Posts: 9221
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Tue Jan 23, 2024 11:02 am     Reply with quote

I don't use that PIC, but silly question is the PIC HW designed for 1MHz (FM+) operation ?
robleso7473



Joined: 25 Mar 2009
Posts: 47

View user's profile Send private message

PostPosted: Tue Jan 23, 2024 11:07 am     Reply with quote

Hi Temtronic,
Thanks for your response.

There's no silly questions, only stupid responses.

Yes, this part is specified for 1MHz I2C bus. Page 458 of Microchip DS30010221D spec.

I am using a level shifter on this I2C bus and am scoping out the waveform after it's level shifted so maybe the speed I am reading is affected by it. Let me solder some more wires on this board and measure the actual I2C_CLK out of the MCU.

Be right back....
Ttelmah



Joined: 11 Mar 2010
Posts: 19496

View user's profile Send private message

PostPosted: Tue Jan 23, 2024 11:51 am     Reply with quote

How is your termination done?.
Operation above 400KHzm imposes tighter limits on capacitance, and
termination. Given you have a level shifted bus, you have requirements
for termination on both sides of the shiftrer. Also reliable operation above
400K may be more likely using active termination (HS mode requires
this). Fast Mode plus tightens the rise time and fall time specifications
of the bus. How is your shifter done?. Speed specifications for this?.
Required rise time falls from 300nSec to 120nSec. Can you look at
your bus and see if the termination achieves this?.
robleso7473



Joined: 25 Mar 2009
Posts: 47

View user's profile Send private message

PostPosted: Tue Jan 23, 2024 11:58 am     Reply with quote

Hi Ttelmah,

Well, I am using a TCA9517A I2C level shifter which has an odd vih requirement. It's definitely affecting the timing (basically it's holding the MCU I2C_CLK low for approximately 200ns). The level shifted external I2C_CLK is pulled up with 1.6k, and the internal non-level shifted MCU I2C_CLK output is also pulled up to about 1.5k..ish.

I'm also using the 2nd I2C HW bus to drive a DAC. There's no level shifting there so I will scope that I2C_CLK to see how it looks.

I suspect that the TCA9517A is somehow affecting I2C_CLK frequency. Is there a feedback mechanism in this MCU that determines when I2C_CLK has gone high then adjusts the period based on that? That would be too smart for these MCUs so I suspect not but maybe you know.

When you say 'active termination, are you talking/typing about just adjusting the pull up value? Or does this involve capacitance?

thanks,
O
robleso7473



Joined: 25 Mar 2009
Posts: 47

View user's profile Send private message

PostPosted: Tue Jan 23, 2024 12:01 pm     Reply with quote

Forgot to ask this.

Is there a way for me to post a .bmp or .jpg image on these replies? I would like to upload the scope waveform i'm seeing.
Ttelmah



Joined: 11 Mar 2010
Posts: 19496

View user's profile Send private message

PostPosted: Tue Jan 23, 2024 12:05 pm     Reply with quote

No,active termination is using a dynamic current source to pull the lines
high faster. Remember with FM+, the pull up current goes up from 3mA
max to 12mA. The active pull up dynamically pulls the line up faster
when it is low. Look at the TCA9416.

On pictures just put them up on a photo sharing site, and post a link.
robleso7473



Joined: 25 Mar 2009
Posts: 47

View user's profile Send private message

PostPosted: Tue Jan 23, 2024 12:11 pm     Reply with quote

Hi Ttelmah,

Ok I understand. I'm just now discovering that the TCA9517A level shifter is designed for tandard and fast mode I2C :(

I am getting FM+ devices to respond at 1MHz but I have to crank up I2C speed to 1.4MHz to account for the lost low time required to drive the external bus high. I'm also not using a strong enough pull-up on the level shifted(external) side. It's 1.6K, I'm going to drop it to 500 Ohms.

thanks,
O
robleso7473



Joined: 25 Mar 2009
Posts: 47

View user's profile Send private message

PostPosted: Tue Jan 23, 2024 1:27 pm     Reply with quote

I am using the two HW I2C buses. Do you know if i2c_speed() function sets clock speed on both I2C ports? I tried changing speed on I2C_PORT1 but it doesn't change while on I2C_PORT2 it does change.

When I use it on I2C_PORT2, you can see the machine code moves #12 to 498
Code:

....................             I2c_speed(I2C_PORT2, 400000);
3146:  MOV     #12,W4
3148:  MOV     W4,498


..And when I run the same function on I2C_PORT1 it writes exactly the same value to the same register:

Code:

....................            i2c_speed(I2C_PORT1, 400000);
2F60:  MOV     #12,W4
2F62:  MOV     W4,498


I can change the speed on I2C_PORT2 but nothing happens on I2C_PORT1.

Here is the I2C #use functions in my .h header file:

Code:

//Internal DAC I2C Bus Initialization//
#use i2c(MASTER, I2C1, RESTART_WDT, stream=I2C_PORT1)
#use i2c(MASTER, SCL=PIN_A7, SDA=PIN_A8, RESTART_WDT, stream=I2C_PORT1)

//Main external I2C Bus Initialization//
#use i2c(MASTER, I2C2, FAST, RESTART_WDT, stream=I2C_PORT2)
#use i2c(MASTER, SCL=PIN_B8, SDA=PIN_B9, RESTART_WDT, stream=I2C_PORT2)
jeremiah



Joined: 20 Jul 2010
Posts: 1345

View user's profile Send private message

PostPosted: Tue Jan 23, 2024 2:14 pm     Reply with quote

One thing is you shouldn't double up on #use i2c for them same one. You only need one #use i2c for each device. The calls are not cumulative, they are overwriting and your 2nd call for each has the potential to use a SW I2C if the compiler decides. I would recommend:

Code:

//Internal DAC I2C Bus Initialization//
#use i2c(MASTER, I2C1, RESTART_WDT, stream=I2C_PORT1)

//Main external I2C Bus Initialization//
#use i2c(MASTER, I2C2, FAST=400000, RESTART_WDT, stream=I2C_PORT2)


It'll know where the pins are based on the I2C1 and I2C2 parameters.

Also, it depends on the compiler version but you may have a bug in the chip database specifications. When I try with version 5.113 I get:

Code:

....................
....................    i2c_speed(I2C_PORT1, 400000);
0276:  MOV     #12,W4
0278:  MOV     W4,498
....................    i2c_speed(I2C_PORT2, 400000);
027A:  MOV     #12,W4
027C:  MOV     W4,4A8


Notice how port 2 uses a different address than port 1 for this version of the compiler. They do look very similar, but are indeed different for this version of the compiler.
robleso7473



Joined: 25 Mar 2009
Posts: 47

View user's profile Send private message

PostPosted: Tue Jan 23, 2024 2:27 pm     Reply with quote

Hi Jeremiah,
Thanks for this information.

If I follow you single #use i2c definition where do I assign the I2C pins for both ports? I tried entering them all on a single line but it wouldn't compile. I thought I could remap I2C2 to alternate pins but it's not allowing it on a single line, have to use two - very odd isn't it? Unless I'm doing something wrong.
Ttelmah



Joined: 11 Mar 2010
Posts: 19496

View user's profile Send private message

PostPosted: Wed Jan 24, 2024 2:41 am     Reply with quote

Read the sticky at the top of the forum.

Now, there are three ways pins move. The first is by fuses, the second by
software 'SEL' bits, the third is by PPS.
This chip has the I2C moved by a fuse bit. You need to set this yourself.

I2C2 is not movable. Only I2C1, to two pairs of pins.

What is happening is your two line solution is over-ridding the hardware
I2C setup, and instead setting up software I2C on your new pins.
This is why the speed won't go up. Software is always slower than
hardware.

You need to read the data sheet, and understand what the hardware
actually allows. Possibly change to a later PIC with the I2C supporting
PPS.
jeremiah



Joined: 20 Jul 2010
Posts: 1345

View user's profile Send private message

PostPosted: Wed Jan 24, 2024 9:14 am     Reply with quote

robleso7473 wrote:
Hi Jeremiah,
Thanks for this information.

If I follow you single #use i2c definition where do I assign the I2C pins for both ports?


Ttelmah went over the details, but wanted to highlight what I said in my earlier post: For hardware I2C, simply specifying either I2C1 or I2C2 in your #use will select the correct pins.

If you want to use alternate pins for I2C1 (you cannot for I2C2), then set the correct #FUSES for it. For this chip that means
Code:

#fuses ALTI2C1           //I2C1 mapped to ASDA1/ASCL1 pins
Ttelmah



Joined: 11 Mar 2010
Posts: 19496

View user's profile Send private message

PostPosted: Wed Jan 24, 2024 11:18 am     Reply with quote

and, understand that you must read the data sheet.
The compiler will do it's absolute best to allow you to do things not
supported by the hardware, so offering you software I2C, if you try to
use pins not supported by the hardware, but to get the best performance
from the hardware, you have to use the hardware resources.
So hardware I2C pins, UART pins etc. etc..
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