|
|
View previous topic :: View next topic |
Author |
Message |
Ringo42
Joined: 07 May 2004 Posts: 263
|
sending negative numbers on I2C |
Posted: Sat May 21, 2011 10:05 am |
|
|
I'm using CCS PCH C Compiler, Version 4.093.
I'm trying to send 32bit numbers over I2C. Positive numbers work fine, but negative numbers get messed up. I'm sure it is a Signed/Unsigned issue but I'm not sure how to fix it. The master code looks like this.
Code: |
dist1d = (dist1 / 16777216);
dist1=dist1-(dist1d*16777216);
dist1c =(dist1/65536);
dist1=dist1-(dist1c*65536);
dist1b=dist1/256;
dist1=dist1-(dist1b*256);
dist1a=dist1;
printf ("a=%ld b=%ld c=%ld d=%ld\r\n",dist1a,dist1b,dist1c,dist1d);
tempdist= (dist1a + (dist1b*256) +(dist1c*65536) +(dist1d*16777216) );
printf ("dist1 rebuilt = %ld\r\n",tempdist);
if(address<14)
{
Address=(ID2+38);
i2c_start(); // restart condition
i2c_write(ADDRESS);
i2c_write(43);//digo
i2c_write(1);
i2c_write(dist1a);
i2c_write(dist1b);
i2c_write(dist1c);
i2c_write(dist1d);
i2c_write(vel1);
......
i2c_stop();
|
if dist1 = -1000 I get a=-232 b=-3 c=0 d=0 and the rebuilt number is -1000.
That looks ok.
On the receiving end I started with sample code from the forum that looks like this.
Code: |
#INT_SSP HIGH
void ssp_interupt ()
{
int i;
BYTE incoming, state;
state = i2c_isr_state();
// printf("i2c\r\n");
if(state < 0x80) //Master is sending data
{
signed int32 dist1a,dist1b,dist1c,dist1d,dist2a,dist2b,dist2c,dist2d;
incoming = i2c_read();
buffer[bytecounter]=incoming;
bytecounter++;
if(bytecounter ==14 )//First received byte is address
{
if(buffer[1]==43) // DIGO
{
// printf("digo\r\n");
//// // Format: /digo address, 43, ID, DistL,Dist2,Dist3,DistH,Vel,ID,DistL,Dist2,Dist3,DistH,Vel 14
ID1=buffer[2];
dist1a =buffer[3];
dist1b=buffer[4];
dist1c =buffer[5];
dist1d=buffer[6];
vel1=buffer[7];
.....
printf("%d %d id=%d a=%d b=%d c=%d d=%d vel=%d\r\n",buffer[0],buffer[1],buffer[2],buffer[3],buffer[4],buffer[5],buffer[6],buffer[7]);
dist1= (dist1a + (dist1b*256) +(dist1c*65536) +(dist1d*16777216) );
dist2= (dist2a + (dist2b*256) +(dist2c*65536) +(dist2d*16777216) );
printf ("dist1 rebuilt = %ld dist2 rebuilt = %ld\r\n",dist1,dist2);
bytecounter=0;
sprintf(SERIAL_BUFFER,"digo %d:%ld:%d %d:%ld:%d\0",ID1,dist1,vel1,ID2,dist2,vel2);
printf("command is %s\r\n",SERIAL_BUFFER);
setDistance();
}
}
|
Here I get
>40 43 id=1 a=24 b=-3 c=0 d=0 vel=10
dist1 rebuilt = 64792 dist2 rebuilt = 64792
Incoming buffer is defined as bytes, but my dist numbers are signed int32's.
That is probably the issue, but I'm not sure how to fix it.
Any thoughts on a simple answer?
Thanks
Ringo _________________ Ringo Davis |
|
|
FvM
Joined: 27 Aug 2008 Posts: 2337 Location: Germany
|
|
Posted: Sat May 21, 2011 1:20 pm |
|
|
I must confess, that I'm not motivated to analyze, why your code doesn't work as intended. Of course it's possible to use arithmetic expressions or - more straightforward - shift operations to split longint into bytes and assemble byte to longint, and get a correct result. But basically you don't want to perform arithmetic, you're just moving bytes.
There are two ways to translate between 32 bit entities and bytes directly:
- use unions
- use the CCS proprietary functions make8() and make32()
With make8() and make32() you can directly write what you intend:
Code: | i2c_write(make8(dist1,0));
i2c_write(make8(dist1,1));
i2c_write(make8(dist1,2));
i2c_write(make8(dist1,3)); | Or on read
Code: | dist1 = make32(dist1d,dist1c,dist1b,dist1a); |
|
|
|
rnielsen
Joined: 23 Sep 2003 Posts: 852 Location: Utah
|
|
Posted: Mon May 23, 2011 9:04 am |
|
|
First, don't have ANY printf() statements inside the interrupt. That, alone, will kill things.
I2C can only transmit 8 bits at a time so your 'dist1a', 'dist1b'.... only need to be declared as 8bit variables. Like FvM stated, use make8() in your master code to split up the variable dist1. Then, use make32() in your slave to put everything back together. Simple and much easier for others to read what you're doing.
If you do want to print what the slave received then do it in main(). Just set a flag, in your ISR, and evaluate that flag in main to print.
Ronald
-If at first you don't succeed, try doing it the way your wife told you to. |
|
|
Ringo42
Joined: 07 May 2004 Posts: 263
|
|
Posted: Tue May 24, 2011 7:38 am |
|
|
The Make8 and Make32 did it. Much simpler than the way I was doing it.
Thanks
Ringo _________________ Ringo Davis |
|
|
|
|
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
|