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

sending negative numbers on I2C

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



Joined: 07 May 2004
Posts: 263

View user's profile Send private message

sending negative numbers on I2C
PostPosted: Sat May 21, 2011 10:05 am     Reply with quote

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

View user's profile Send private message

PostPosted: Sat May 21, 2011 1:20 pm     Reply with quote

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

View user's profile Send private message

PostPosted: Mon May 23, 2011 9:04 am     Reply with quote

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

View user's profile Send private message

PostPosted: Tue May 24, 2011 7:38 am     Reply with quote

The Make8 and Make32 did it. Much simpler than the way I was doing it.
Thanks
Ringo
_________________
Ringo Davis
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