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

I2C query

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



Joined: 19 Jan 2006
Posts: 22

View user's profile Send private message

I2C query
PostPosted: Fri Feb 03, 2006 12:52 pm     Reply with quote

Hi,

CCS comes with "off the shelf" I2C functions, but many people seem to write their own manipulating the hardware registers manually. Since so many people do it, there must be a significant advantage to doing it this way, but it seems far more complex. I can see that using the "built in" functions on pins other than the hardwired I2C pins would give a large overhead, but if we use them on the hardware pins, is there any difference?

Also, in the datasheets for my PIC (PIC18F452) it states that the SCL and SDA lines should be set up as inputs/outputs using the TRIS register. SCL is obviously an output from the master, but SD is bidirectional, so what does that make it an input or an output...?

Cheers,

Ben
jds-pic



Joined: 17 Sep 2003
Posts: 205

View user's profile Send private message

PostPosted: Fri Feb 03, 2006 2:23 pm     Reply with quote

ben,
barkerben wrote:
CCS comes with "off the shelf" I2C functions, but many people seem to write their own manipulating the hardware registers manually. Since so many people do it, there must be a significant advantage to doing it this way, but it seems far more complex. I can see that using the "built in" functions on pins other than the hardwired I2C pins would give a large overhead, but if we use them on the hardware pins, is there any difference?


for 99.9% of applications, CCS's builit-in i2c functions are fine. only in boundary cases of time or code space will it become necessary to roll your own.

barkerben wrote:
Also, in the datasheets for my PIC (PIC18F452) it states that the SCL and SDA lines should be set up as inputs/outputs using the TRIS register. SCL is obviously an output from the master, but SD is bidirectional, so what does that make it an input or an output...?

yes. the tri-state register is manipulated as needed during the i2c transaction.

jds-pic
Ttelmah
Guest







PostPosted: Fri Feb 03, 2006 3:44 pm     Reply with quote

Generally, you won't see many people using 'third party' drivers for I2C. The CCS functions pretty much work fine. However there have been quite a few chips in the past, where the configuration values were incorrect, and these then have to be set manually. You _will_ see quite a few people going 'DIY', in the past, when they wanted to use interrupt control, for which support has improved recently (with the 'I2C state' function), and quite a few more, when using the same hardware for SSP, where the functions do not handle the hardware in a way that really suits the operation of the bus in many applications...

Best Wishes
Guest








PostPosted: Fri Feb 03, 2006 5:40 pm     Reply with quote

Thanks. I ask partly because I have been trying to interface to a CMPS03 compass module. I don't know if anyone has any experience with this - but if they do...


However much I debug it, I seem to get very odd compass readings. I was wondering whether it might be something to do with the I2C commands - such as an inability of the master to cope with clock stretching by the slave...?

I'm pretty certain the hardware is ok. My code is:

Code:

#include <18f452.h>
#include <stdio.h>

#define CMP_ADDR_LOW      0xC0               // Factory supplied default address
#define CMP_ADDR_HI     0xC1
#define PC_TX PIN_D2
#define CLK PIN_C3
#define DATA PIN_C4
#define REG 1

long bearing;

#BYTE high_byte = bearing
#BYTE low_byte = bearing + 1

#fuses HS,NOWDT,NOPROTECT,NOLVP
#use Delay(Clock=20000000)
#use rs232(baud=9600, xmit=PC_TX,stream=PC)   //TX line to level converter and PC
#use i2c(master, SCL=CLK, SDA=DATA)


void get_cmps03(void);


void main(void)
{


   while(1) {                     
      get_cmps03();            
      fprintf(PC,"Bearing: %Lu \n\r",bearing);
      delay_ms(500);

   }
}

void get_cmps03()
{
I2C_START();
I2C_WRITE(CMP_ADDR_LOW);
delay_us(50);
I2C_WRITE(REG);
delay_us(50);
I2C_START();
I2C_WRITE(CMP_ADDR_HI);
high_byte=I2C_READ();
low_byte=I2C_READ();
I2C_STOP();
}


Another possible problem is the voltages I'm using. The PIC and most of the rest of my circuity is running at 3v3. The Compass is running at 5v, but the SCL lines have been tied up only to 3v3. But I don't really see why this should be a problem...

The data I'm reading comes as two bytes - high and low. The values should be between 0-3599, but with the compass stationary you can see they are all over the place:


    Bearing: 58879
    Bearing: 0
    Bearing: 2560
    Bearing: 705
    Bearing: 52248
    Bearing: 997
    Bearing: 65280
    Bearing: 836
    Bearing: 39170
    Bearing: 58879
    Bearing: 0
    Bearing: 2560
    Bearing: 704
    Bearing: 45848
    Bearing: 997
    Bearing: 65280
    Bearing: 835
    Bearing: 44034
    Bearing: 58879
    Bearing: 0
    Bearing: 2560
    Bearing: 703
    Bearing: 47128
    Bearing: 997
    Bearing: 65280
    Bearing: 835
    Bearing: 39426
    Bearing: 58879
    Bearing: 0
    Bearing: 2560
    Bearing: 703
    Bearing: 44824
    Bearing: 65535


The values are very odd, with an apparent pattern every 5 reads or so. This seems to be independant of how often I request a reading...

Any ideas floating in the ether?

Cheers,

Ben
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Fri Feb 03, 2006 6:13 pm     Reply with quote

Quote:
long bearing;

#BYTE high_byte = bearing
#BYTE low_byte = bearing + 1

You have the addresses of the LSB and MSB reversed.
16-bit values are stored in Lo-Hi format. The LSB
comes first. Then the MSB. i.e., the LSB is stored
at the lower address.

Also, normally you wouldn't return a 16-bit value
in the way you're doing it. You would combine
the MSB and LSB inside the routine and return
a 16-bit value from the function, and not by
putting it into a global variable.
Guest








PostPosted: Fri Feb 03, 2006 6:32 pm     Reply with quote

Yes - I realise global variabes are a bit ugly :-(

However, I've fixed the byte order, but still get random looking values, with a regular pattern of zeros, 255's , or 10's thrown in. The only thing left not to be working seems to be the compass itself, but that's brand new...

Hmmmmm...... :-p
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Fri Feb 03, 2006 6:47 pm     Reply with quote

There is one other thing.

The spec sheet here, doesn't show a NACK on the last i2c read.
http://www.robot-electronics.co.uk/htm/cmps3doc.shtml

But the sample code here, says "Not acknowledge for last byte".
http://www.robot-electronics.co.uk/files/cmps03_lcd03.c

So the spec sheet may be in error, in which case you need to
use a zero parameter on the last i2c read. Example:
Code:
high_byte=I2C_READ();
low_byte=I2C_READ(0);


Doing a NACK on the last read is the standard method for 99% of
i2c devices.
Guest








PostPosted: Fri Feb 03, 2006 7:14 pm     Reply with quote

I tried that, but unfortunately it had no effect :-(

I checked the PWM pins on the module (alternative output) using a multimeter however, and they seem to be working, so at least some of the compass is behaving itself.

I noticed that the data from the compass doest seem to follow a pattern - 8 readings before either 0 or 255, then another 8.

Eight of things is always suspicious, ut in this case I can't see what might be going wrong. I've emailed the compass company to see if they have any ideas...and I'll keep trying myself!

Cheers,

Ben
Ttelmah
Guest







PostPosted: Sat Feb 04, 2006 3:32 am     Reply with quote

Pulling the line to 3.3v, should be fine from the 3.3v _PICs_ point of view, but might give problems with the writes to the compass itself. At the very least, it'll mean that the signals will take longer to reach the 'high' level into the module. Now the module itself is using a PIC, and assuming it is using the hardware port here for the I2C slave, and running at 5v, the inputs, are normally 'Schmitt trigger' types. These have a required 'high' voltage, on most of the I2C inputs, of 0.7Vdd. With 5v, this is 3.5v...
I suspect you are not reliably addressing the chip, and are perhaps 'cycling through' an internal counter, and retrieving something else at intervals. I'd try pulling the lines to 5v, rather than to 3.3, and adding your own clamp diodes to the 3.3v rails (rather than relying on the internal diodes in the PIC). This will then give you a 'high', of about 3.9v, on the I2C lines.

Best Wishes
Guest








PostPosted: Sat Feb 04, 2006 5:39 am     Reply with quote

So simple... It turns out my original order of high and low bytes was in fact correct. However, the main problem was that the PIC was booting up before the compass, and starting I2C comms before the compass was ready. This then messed up all future I2C comminication I think... does this sound plausible?

Cheers,

Ben
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