View previous topic :: View next topic |
Author |
Message |
vtrx
Joined: 11 Oct 2017 Posts: 142
|
Load Int16 with hex value |
Posted: Fri Nov 05, 2021 6:38 pm |
|
|
I am here again.
I need to load an int16 with a value received from UART.
example;
The value 1358 is sent by the UART as 054E (Buf[0]=05,Buf[1]=4E), so I need to load the variable x(int16) with the value 1358(054E).
what would be the most effective means?
make16 works directly(x = make16(Buf[0],Buf[1]); ) ? |
|
|
jeremiah
Joined: 20 Jul 2010 Posts: 1353
|
|
Posted: Fri Nov 05, 2021 7:16 pm |
|
|
make16() for sure |
|
|
vtrx
Joined: 11 Oct 2017 Posts: 142
|
|
Posted: Fri Nov 05, 2021 7:24 pm |
|
|
jeremiah wrote: | make16() for sure |
Is it not necessary to convert?
Can i directly use the 05 and 4E values? |
|
|
jeremiah
Joined: 20 Jul 2010 Posts: 1353
|
|
Posted: Fri Nov 05, 2021 7:31 pm |
|
|
vtrx wrote: | jeremiah wrote: | make16() for sure |
Is it not necessary to convert?
Can i directly use the 05 and 4E values? |
I may not understand: convert to what? your using integer types for your array and integer types for your resultant value. Integer types have implicit conversions. You generally only need to explicitly convert when trying to force math results because math doesn't automatically promote. |
|
|
vtrx
Joined: 11 Oct 2017 Posts: 142
|
|
Posted: Sat Nov 06, 2021 4:23 am |
|
|
I was thinking...
The PC sends 054E as ascii '0','5','4','E' because it uses serial communication and the PC routine only sends Ascii.
I don't need to manipulate this?
In fact, the application that sends data over the serial is for Android.
I'm saying this because I'm trying to port the routine I use with USB and Android has to be serial.
The USB routine is pretty easy because it works with bytes directly, I send Buf[0] with 0x05 and Buf[1] with 0x4E, only that, this way I send what I need which is the size of the data to receive.
I'm not able to send this way using serial. |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9241 Location: Greensville,Ontario
|
|
Posted: Sat Nov 06, 2021 4:58 am |
|
|
this...
Quote: | The PC sends 054E as ascii '0','5','4','E' because it uses serial communication and the PC routine only sends Ascii.
is a LOT different than your original question ! |
It sounds like your PC program is sending data as 4 ASCII bytes even though a PC UART can send a byte of data several ways (binary, octal, hex, integer, etc.) to represent the data.
If you're really getting 2 bytes as 05, 4e then the make16() method will work and is the fastest.
If you're getting 4 ASCII bytes, then yes, you'll need to 'convert' the 4 ASCII bytes into 4 bytes and place into the correct locations in the unsigned int16 word. Pretty sure you just take the ASCII byte, subtract 30 decimal, and store the result. But, it's early here, coffee's not made and the cat wants his breakfast.... |
|
|
jeremiah
Joined: 20 Jul 2010 Posts: 1353
|
|
Posted: Sat Nov 06, 2021 10:38 am |
|
|
vtrx wrote: | I was thinking...
The PC sends 054E as ascii '0','5','4','E' because it uses serial communication and the PC routine only sends Ascii.
I don't need to manipulate this?
In fact, the application that sends data over the serial is for Android.
I'm saying this because I'm trying to port the routine I use with USB and Android has to be serial.
The USB routine is pretty easy because it works with bytes directly, I send Buf[0] with 0x05 and Buf[1] with 0x4E, only that, this way I send what I need which is the size of the data to receive.
I'm not able to send this way using serial. |
Okie dokie, in your initial post you said it sent:
Quote: |
Buf[0]=05,Buf[1]=4E
|
which is raw integers, not ASCII. If it were ASCII, your buffer would look like:
Quote: |
Buff[0] = 0x30
Buff[1] = 0x35
Buff[2] = 0x34
Buff[3] = 0x45
|
If it looks like that you need to convert either by appending a null character to the buffer (you need space on your buffer for this) and using the atoi() function (google can help here) or making your own function that does the conversion. You have to ensure to handle checking if the ASCII value is in range of a number, capital letter, or lowercase letter and handle each case:
Code: |
unsigned int8 from_ascii(char value){
if(value >= '0' && value <= '9'){
return value - '0';
}else if(value >= 'a' && value <= 'f'){
return value - 'a'+10;
}else if(value >= 'A' && value <= 'F'){
return value - 'A'+10;
}else{
return -1; //need some sort of error value
}
}
|
Then you just can call that and make sure the value isn't -1 before using the result. NOTE that I just wrote that on the fly without checking it would compile. It's just notional for an example. I'm sure there are other examples out there on google on how to convert ASCII to hex numbers |
|
|
vtrx
Joined: 11 Oct 2017 Posts: 142
|
|
Posted: Sat Nov 06, 2021 7:51 pm |
|
|
I changed the code.
Code: |
char digit[6];
...
digit[0]=Rs_buf[1];//0
digit[1]=Rs_buf[2];//0
digit[2]=Rs_buf[3];//3
digit[3]=Rs_buf[4];//2
digit[4]=Rs_buf[5];//3
digit[5]=Rs_buf[6];//2
...
messagelength = atoi(digit);//messagelength int16
|
The Android program separates an int16(Word) into 2 bytes that are sent over the serial in decimal(ascii) format.
Ex: 1000 = 0,0,3,2,3,2
ATOI formats it right this way? |
|
|
jeremiah
Joined: 20 Jul 2010 Posts: 1353
|
|
Posted: Sat Nov 06, 2021 9:01 pm |
|
|
you need to append a null character at the end:
Code: |
char digit[7]; // <======== See here at size
...
digit[0]=Rs_buf[1];//0
digit[1]=Rs_buf[2];//0
digit[2]=Rs_buf[3];//3
digit[3]=Rs_buf[4];//2
digit[4]=Rs_buf[5];//3
digit[5]=Rs_buf[6];//2
digit[6]= '\0'; // <============ See here
...
messagelength = atoi(digit);//messagelength int16
|
|
|
|
mdemuth
Joined: 16 Apr 2007 Posts: 71 Location: Stuttgart, Germany
|
|
Posted: Tue Nov 09, 2021 9:13 am |
|
|
I think you are looking for something returns an int16 which is built from 4 received characters.
You can use:
Code: |
int8 ASCI_TO_HEX(int8 high_nibble, int8 low_nibble)
{
int8 value=0;
int8 value_ln=0;
int8 value_hn=0;
if ((low_nibble >= 0x30) && (low_nibble <= 0x39)) value_ln= low_nibble - 0x30; // 0..9
if ((low_nibble >= 0x41) && (low_nibble <= 0x46)) value_ln= low_nibble - 55; // A..F
if ((high_nibble >= 0x30) && (high_nibble <= 0x39)) value_hn= high_nibble - 0x30; // 0..9
if ((high_nibble >= 0x41) && (high_nibble <= 0x46)) value_hn= high_nibble - 55; // A..F
value = value_hn*16;
value=value+value_ln;
return(value);
}
|
Then use the function above:
Code: |
int16 ValueReceived = make16 (ASCI_TO_HEX(Rs_buf[1], Rs_buf[2]), ASCI_TO_HEX(Rs_buf[3], Rs_buf[4]))
|
In order to have a save communication you add control characters such as: STX, ETX, CR or any other character then 0..9, A..F |
|
|
vtrx
Joined: 11 Oct 2017 Posts: 142
|
|
Posted: Thu Nov 11, 2021 5:12 pm |
|
|
The 'solution' I'm using is:
I formatted the 16-bit value into six ASCII characters to keep the same space, for example:
1000-> 001000 and i used ATOI.
Code: | ///Android->send 1000(ASCII).
digit[0]=Rs_buf[1];//0
digit[1]=Rs_buf[2];//0
digit[2]=Rs_buf[3];//1
digit[3]=Rs_buf[4];//0
digit[4]=Rs_buf[5];//0
digit[5]=Rs_buf[6];//0
digit[6]='\0';
messagelength = atoi(digit); |
|
|
|
mdemuth
Joined: 16 Apr 2007 Posts: 71 Location: Stuttgart, Germany
|
|
Posted: Fri Nov 12, 2021 12:35 am |
|
|
OK, then you are printing format is decimal not hex e.g. 65536 instead of FFFF
It works (almost) just as well. The important thing is to have a clear separation between control characters and content characters. |
|
|
vtrx
Joined: 11 Oct 2017 Posts: 142
|
|
Posted: Sat Nov 13, 2021 5:40 pm |
|
|
I came back to correct a mistake.
For the value that i needed(16 bits) i need to use atoL |
|
|
|