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 support@ccsinfo.com

Converting raw string to int

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



Joined: 18 Apr 2006
Posts: 66

View user's profile Send private message Yahoo Messenger

Converting raw string to int
PostPosted: Tue Mar 24, 2020 8:11 pm     Reply with quote

I have an unusual application. I am reading frequency data from an ICOM receiver. The data comes out of the serial port at 9600. I am using an 18F25k80. I am reading in 11 bytes just fine into a string variable (sBuffer). Unfortunately, the radio vendor will send a frequency in LSB to MSB order. I extract the various digits just fine, but I need to mathematically multiply the decades to get the final frequency. The problem is that the bytes coming in are direct values. I.e. 10 is read back as 0x10 in a single byte as are the other digits.

I have tried to get them in a form I can multiply and add but with no luck.

char sBuffer[11]; // I want the 8th byte (0x10) to be an int 10
long nCurrentFreq;
char sAdr[1];

memcpy(sAdr,sBuffer+8,1);
nCurrentFreq=strtoul(sAdr,1,1);

// I need nCurrentFreq to me a long int that I can do math with.

Thanks for any help. I tried sprintf but could not get it to work either.
_________________
Ed J
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Mar 25, 2020 1:30 am     Reply with quote

- Post an example of the incoming string, with a space between each byte.
- Tell us which of the bytes in the string are the frequency.
- Tell us the frequency that the bytes represent.

In other words, give total information.
Ttelmah



Joined: 11 Mar 2010
Posts: 19195

View user's profile Send private message

PostPosted: Wed Mar 25, 2020 1:39 am     Reply with quote

The eighth byte is an integer that you can multiply already. However
remember you are probably going to have to build the result into an
int16 or int32 variable (the char locations will not be big enough to hold
the result), and you need to be using a similar longer type for the
multiplication.
As PCM_Programmer says, show us what you get, and what you
actually want to do.
foodwatch



Joined: 18 Apr 2006
Posts: 66

View user's profile Send private message Yahoo Messenger

PostPosted: Wed Mar 25, 2020 9:13 am     Reply with quote

Here is the raw data as I receive it. I have added a space between bytes for clarity but there is no space sent:

0xFE 0xFE 0x00 0x54 0x00 0x80 0x42 0x16 0x07 0x00 0x00 0x00 0xFD

The first 4 bytes are preamble and address, 0xFD is end of message byte
The message length is always the same.
The above data represents a frequency of 7164.2800
I don't need anything but 7164 ignoring everything to the right 0f 7164. As you can see, the protocol from the ICOM product is really strange.
The highest value for nFrequency is 54000 so a long int should do it.

I was planning to take only bytes 9 (0x07), 8 (0x16) and 7 (0x42) to assemble the final value of 7164 which

Thanks for the quick response to my first post and hope I am clarifying the problem I am having (been away from C for too long).
_________________
Ed J
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Mar 25, 2020 12:25 pm     Reply with quote

For anyone interested, here is an ICOM manual. Go to page 35 to see
the serial port commands and data format. The data is in BCD.
https://www.icomamerica.com/en/downloads/DownloadDocument.aspx?Document=122
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Mar 25, 2020 1:01 pm     Reply with quote

This will give you 7164:
Code:
#include <18F46K22.h>
#fuses INTRC_IO, NOWDT, BROWNOUT, PUT, NOPBADEN
#use delay(clock=4M)
#use rs232(baud=9600, UART1, ERRORS)

//======================================
void main()
{         
int8 sBuffer[] = {
0xFE,0xFE,0x00,0x54,0x00,0x80,0x42,0x16,0x07,0x00,0x00,0x00,0xFD};
int16 freq;

freq =  (sBuffer[8] & 0x0F) * 1000;
freq += (sBuffer[7] >> 4)   *  100;
freq += (sBuffer[7] & 0x0F) *   10;
freq += (sBuffer[6] >> 4);

printf("%lu\r\n", freq);

while(TRUE);

}
foodwatch



Joined: 18 Apr 2006
Posts: 66

View user's profile Send private message Yahoo Messenger

Raw Int
PostPosted: Wed Mar 25, 2020 2:56 pm     Reply with quote

Thanks for the sample code. The only problem is that the rawdata received by the uart has no spaces and no commas. Is there another way? Otherwise I can create variables for each of the bytes and define the array
using these bytes and do the math on the bytes. Any thoughts?
_________________
Ed J
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Mar 25, 2020 3:06 pm     Reply with quote

The commas are to separate the data bytes, per the C standard, when
initializing an array. There are no actual commas in the array.

How are you receiving the data from the ICOM receiver ? Through a serial
port. So, somehow you must be reading it into a buffer. It will be in the
buffer just as I've stored it in the array. (No commas, no spaces).

Post your receiving code for the serial bytes.
foodwatch



Joined: 18 Apr 2006
Posts: 66

View user's profile Send private message Yahoo Messenger

PostPosted: Wed Mar 25, 2020 5:58 pm     Reply with quote

Code:
char  cTemp;
int8    sBuffer[12];

//------------- rs232 interrupt routine--------------------------------------
#int_rda             //turn on serial interrupt
void serial_isr()    // serial interrrupt service routine
{
   disable_interrupts(int_timer1);
   cTemp =  Getc();                 //hold Getc() in cTemp
            if(cTemp==0xFD)                   //look for a # in buffer, then set nFlag
            {
               nFlag=1;          //- we have received a #
               nRead=0;          //- but dont empty sBuffer yet
               nBytes=0;
            }
            else                 //else if cTemp is NOT 0xFD
               {
               If (nFlag==1)    //- if previous byte rcvd was a 0xFD
                  {             //- and this one is not
                     sBuffer[nBytes] = cTEMP;   //load up buffer
                     nbytes++;                  //increase string cntr
                     if (nBytes>=11)         //if we got # and then 64 bytes
                        {
                 
                        nFlag =  0;    //- turn off # rcvd flag
                        nBytes = 0;    //- reset byte counter
                        }
                  }
                  else  // if nflag not = 1
                     {
                        memset(sBuffer,0,11);
                        nbytes=0;
                        cTemp = 0;
                        nread=0;
                     }        //end else
               }              //end if cTemp!        }
}  //-      end function

There are two data streams send by the ICOM radio. The last byte is always 0xFD so I wait for the first packet to end with an 0xFD and copy the 12 bytes that come after into sBuffer. I see that I am extracting the data into cTemp but I define it as a character instead of an int. This may be part of my problem. I use nFlag to show that the 0xFD has come and gone so the next data received is valid. Thanks again.
_________________
Ed J
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Mar 25, 2020 6:53 pm     Reply with quote

The code I posted should work. Try it.
Ttelmah



Joined: 11 Mar 2010
Posts: 19195

View user's profile Send private message

PostPosted: Thu Mar 26, 2020 3:06 am     Reply with quote

I'd make one change to it PCM:

freq += (sBuffer[7] >> 4) * 100L;

I think otherwise there is a risk of a numeric overflow on this one line.

Doesn't apply on the other lines (the 1000, forces int16 maths, and the
*10, is small enough that there should never be an overflow).

As PCM_Programmer says, this should work for your data. It is a demo
with his buffer filled to simulate what you have.
foodwatch



Joined: 18 Apr 2006
Posts: 66

View user's profile Send private message Yahoo Messenger

Update
PostPosted: Thu Mar 26, 2020 6:25 am     Reply with quote

Thanks to you both for the recommendations. I have it working with your code with the exception that any frequency over 10000 does not calculate correctly

0xFE 0xFE 0x00 0x54 0x00 0x20 0x49 0x14 0x18 0x00 0x00 0xFD

should display 18144. Instead I get 8144. It seems the error only exists when the frequency is at 10000 or greater. In reality the highest frequency I need to read is 54000.

I am trying to understand the bit manipulation you are doing in the calculations but I will have to study it more. I have been away from C for a number of years plus I'm not as young as I used to be :-) Thanks again
_________________
Ed J
foodwatch



Joined: 18 Apr 2006
Posts: 66

View user's profile Send private message Yahoo Messenger

Working
PostPosted: Thu Mar 26, 2020 6:43 am     Reply with quote

I added the following to the top of your code and now its working ok
Code:

nFreq = (buffer[8] >> 4 ) * 10000;

and changed the = to += in the top line of your code. Thanks for all the help... this one has been making me totally crazy for the past few days Very Happy
_________________
Ed J
temtronic



Joined: 01 Jul 2010
Posts: 9081
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Thu Mar 26, 2020 7:07 am     Reply with quote

Nice you got it working !!!What amazed me is that device has a REAL RS232 connector !! 25 pins...
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