|
|
View previous topic :: View next topic |
Author |
Message |
barkerben
Joined: 19 Jan 2006 Posts: 22
|
I2C query |
Posted: Fri Feb 03, 2006 12:52 pm |
|
|
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
|
|
Posted: Fri Feb 03, 2006 2:23 pm |
|
|
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
|
|
Posted: Fri Feb 03, 2006 3:44 pm |
|
|
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
|
|
Posted: Fri Feb 03, 2006 5:40 pm |
|
|
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
|
|
Posted: Fri Feb 03, 2006 6:13 pm |
|
|
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
|
|
Posted: Fri Feb 03, 2006 6:32 pm |
|
|
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
|
|
|
Guest
|
|
Posted: Fri Feb 03, 2006 7:14 pm |
|
|
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
|
|
Posted: Sat Feb 04, 2006 3:32 am |
|
|
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
|
|
Posted: Sat Feb 04, 2006 5:39 am |
|
|
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 |
|
|
|
|
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
|