View previous topic :: View next topic |
Author |
Message |
stephanhwolf
Joined: 03 Sep 2012 Posts: 4
|
#use i2c not changing pins with 18f4520 |
Posted: Mon Sep 03, 2012 3:48 pm |
|
|
Hi,
I want to be able to change the i2c pins with #use i2c for different hardware revisions.
This simple code does not work:
Code: |
//UseFastI2c defaults to FALSE
temp=read_eeprom(FastI2cInstalledAddr);
if (temp!=1){
UseFastI2c=FALSE;
write_eeprom(FastI2cInstalledAddr,0);
#use i2c(master, sda=PIN_C4, scl=PIN_D3))
output_float(PIN_D3);
}else{
UseFastI2c=TRUE;
#use i2c(master, sda=PIN_C4, scl=PIN_C3))
output_float(PIN_C3);
MinorVersion|=16;
}
|
As you can see, sda stays on PIN_C4, but scl changes between PIN_C3 and PIN_D3; depending upon the state of the internal eeprom read. I have breakpointed the if statement and verified reading eeprom does execute both cases, but an o-scope shows scl stays on PIN_D3 regardless.
I'm using compiler version 4.3.0.275 and am using a 18F4520. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Mon Sep 03, 2012 4:21 pm |
|
|
Quote: | This simple code does not work. |
#use i2c statements do not globally change the mode of the runtime code.
Each statement generates a new instance of the CCS i2c library code
and all i2c functions that occur after the current #use i2c statement
will use the parameters in that statement. That's why your code doesn't work.
You can do what you want by using "streams". See the CCS manual in
the #use i2c section. Look at the 'streams' parameter. See this thread
for an example:
http://www.ccsinfo.com/forum/viewtopic.php?t=43577
Quote: | I'm using compiler version 4.3.0.275
|
That's not your version. Your version is 4.101. It's given at the top of
the .LST file, which is in your project directory after a successful
compilation. |
|
|
stephanhwolf
Joined: 03 Sep 2012 Posts: 4
|
|
Posted: Mon Sep 03, 2012 5:17 pm |
|
|
PCM-Programmer,
Thanks for the tip.
I see how to use stream in #use i2c.
Code: |
#use i2c(master, sda=PIN_C4, scl=PIN_D3, stream=SlowI2c))
#use i2c(master, sda=PIN_C4, scl=PIN_C3, stream=FastI2c))
|
However, it seems like I'll have to hardcode two separate sections of code to deal with each stream. Unless there is a way to pass stream in as an argument. The manual does not spec the datatype for stream. Is it possible to do something like this:
Code: |
ReadExEepromInt (long addr, unknown-type stream){
int data;
i2c_start(stream);
i2c_write(stream,0xa0);
i2c_write(stream,addr>>8);
i2c_write(stream,addr);
i2c_start(stream);
i2c_write(stream,0xa1);//control byte with R/#W set to 1
data= i2c_read(stream,0); //sequential reads
i2c_stop(stream);
return(data);
} |
|
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Mon Sep 03, 2012 6:04 pm |
|
|
The compiler doesn't allow streams to be passed as a parameter. |
|
|
stephanhwolf
Joined: 03 Sep 2012 Posts: 4
|
|
Posted: Mon Sep 03, 2012 6:49 pm |
|
|
Yup, that's what I thought.
Thanks again for your help. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19552
|
|
Posted: Tue Sep 04, 2012 1:37 am |
|
|
Remember though, you can encapsulate the I2C routines. So:
Code: |
int1 second_stream=FALSE;
#separate
void my_i2c_stop() {
if (second_stream) i2c_stop(STREAM2);
else i2c_stop(STREAM1);
}
|
and similarly for each of the other routines.
Then you just call 'my_i2c_start', 'my_i2c_stop' etc., and change 'second_stream' to TRUE/FALSE, according to which stream you want.
This way the required two separate code copies are produced just once (hence the #separate).
Best Wishes |
|
|
stephanhwolf
Joined: 03 Sep 2012 Posts: 4
|
|
Posted: Tue Sep 04, 2012 10:28 am |
|
|
Hi Ttelmah,
I don't really get the #separate directive. Seems to me subroutines ought to be separate by default, and only #inline if so directed.
Or, does the compiler decide whether to make subroutines separate or inline based on frequency of occurrence? |
|
|
|