Nybbles

General discussion on mikroBasic PRO for ARM.
Post Reply
Author
Message
ART_ME
Posts: 22
Joined: 19 Dec 2016 09:48

Nybbles

#1 Post by ART_ME » 11 Feb 2017 05:55

Hi,
MikroBasic have a beautiful built-in routines: Lo, Hi, Higher and Highest, which make it easy to divide words into bytes in order to transfer them via UART. But there are communication protocols in which the transfer takes place by sending ASCII characters. For example, a byte 00111011 ("3B") is transmitted as two bytes: 00010011 ("3") and 1000010 ( "B").
For this operation, I need to divide byte into two nybbles (4 bis each), but I not founded such routines here.
Please message me where such routines, and if is not exist, then how to properly make nybbles by other manner in MikroBasic?

serge87
Posts: 45
Joined: 12 Sep 2012 17:55

Re: Nybbles

#2 Post by serge87 » 13 Feb 2017 09:07

Hello,
You have in the Conversions Library some routines for converting to ASCII characters.
Try ByteToHex routine, it will take a byte as input and at output it will take a string of 2 in which it will put the ASCII characters.
Extract from the help file:

Code: Select all

dim procedure ByteToHex(dim input as byte, dim byref output as string[2])
Converts input number to a string containing the number's hexadecimal representation. The output string is right justified and remaining positions on the left (if any) are filled with zeros.

Best regards.
Just tell me....

ART_ME
Posts: 22
Joined: 19 Dec 2016 09:48

Re: Nybbles

#3 Post by ART_ME » 14 Feb 2017 17:49

serge87,
Thank you very much!

Can I do reverse conversion by StrToInt?

PS. MicroE, when will we see MANUAL.PDF?

serge87
Posts: 45
Joined: 12 Sep 2012 17:55

Re: Nybbles

#4 Post by serge87 » 15 Feb 2017 11:09

ART_ME wrote:Can I do reverse conversion by StrToInt?
No.
The ByteToHex routine transforms (in your case) the value 3B in to characters "3" and "B".
The StrToInt routine expects the decimal representation of the number (in your case "59", characters "5" and "9").
Just tell me....

ART_ME
Posts: 22
Joined: 19 Dec 2016 09:48

Re: Nybbles

#5 Post by ART_ME » 15 Feb 2017 17:34

Oh...
If I have to send via UART byte 0011 1011, I use ByteToHex, and send two bytes - 00110011 ("3") and 01000010 ( "B").
But when I take two bytes - 00110011 ("3") and 01000010 ( "B"), how can I converte them in byte 0011 1011?
Last edited by ART_ME on 16 Feb 2017 10:20, edited 2 times in total.

serge87
Posts: 45
Joined: 12 Sep 2012 17:55

Re: Nybbles

#6 Post by serge87 » 15 Feb 2017 23:14

Code: Select all

dim value as byte  'this is the final variable
dim receive as char[2] ' this is the variable in which you load the ASCII from UART
value = 0
if ((receive[0] < 0x39) AND (receive[0] > 0x47)) then  
   value = receive[0] - 48                                 
else
     if ((receive[0] < 71) AND (receive[0] > 64)) then
        value = receive[0] - 65
        value = value << 4
     end if
end if
if ((receive[1] < 0x39) AND (receive[1] > 0x47)) then
   value = value OR (receive[1] - 48)
else
     if ((receive[1] < 71) AND (receive[1] > 64)) then
        value = value OR (receive[1] - 65)
     end if
end if
I hope it works, I haven't tested the code.
Regards.
Just tell me....

ART_ME
Posts: 22
Joined: 19 Dec 2016 09:48

Re: Nybbles

#7 Post by ART_ME » 16 Feb 2017 10:26

I'm sorry,

I not understand receive[0] < 0x39 AND (receive[0] > 0x47
May be receive[0] < 0x39 OR (receive[0] > 0x47 ?
Or receive[0] > 0x39 AND (receive[0] < 0x47 ?
Last edited by ART_ME on 16 Feb 2017 11:32, edited 1 time in total.

serge87
Posts: 45
Joined: 12 Sep 2012 17:55

Re: Nybbles

#8 Post by serge87 » 16 Feb 2017 10:59

Yeah, my mistake, sorry.
I haven't tested it
Here's the fixed piece of code:

Code: Select all

dim value as byte  'this is the final variable
dim receive as char[2] ' this is the variable in which you load the ASCII from UART
value = 0
if ((receive[0] < 58) AND (receive[0] > 47)) then  
   value = receive[0] - 48                                 
else
     if ((receive[0] < 71) AND (receive[0] > 64)) then
        value = receive[0] - 65
        value = value << 4
     end if
end if
if ((receive[1] < 58) AND (receive[1] > 47)) then
   value = value OR (receive[1] - 48)
else
     if ((receive[1] < 71) AND (receive[1] > 64)) then
        value = value OR (receive[1] - 65)
     end if
end if
Just tell me....

ART_ME
Posts: 22
Joined: 19 Dec 2016 09:48

Re: Nybbles

#9 Post by ART_ME » 16 Feb 2017 15:06

serge87,

May be instead

Code: Select all

value = value OR (receive[1] - 65)

Code: Select all

value = value + (receive[1] - 65)
?
Besides, 66 ("B") - 65 ("A") = 0000 0001 while we need 0000 1011

There other way:

Code: Select all

if receive[0] = 48 then value = %0
if receive[0] = 49 then value = %1
if receive[0] = 50 then value = %2
.....
if receive[0] = 70 then value = %F
:wink:

But all this does not matter to convert to ASCII and back have special operators:
Chr and Ord.

I had a problem with access to nybbles, and you decided it accidentally:
<< and >>

Thank you!!!

serge87
Posts: 45
Joined: 12 Sep 2012 17:55

Re: Nybbles

#10 Post by serge87 » 16 Feb 2017 18:18

As I understood the problem, you need to transmit ASCII characters to the UART port.
A value to ASCII conversion is done based on the ASCII table.
If we take the example you given (3B) and convert it to ASCII with the StrToHex function we produce a string of 2 characters which contains the following values:
00110011 - character "3"
01000010 - character "B".
In order to convert the ASCII representation back to a value we need to take in 2 characters and spit out 1 byte.
Now let's see what the code posted by me does:
First we work on the first character in the string, in our case "3".

Code: Select all

if ((receive[0] < 58) AND (receive[0] > 47)) then 
This piece verifies if the character is between "0" and "9" and if it is then it will do the following"

Code: Select all

value = receive[0] - 48
If the character is not in that interval it check to see if the character is between "A" and "F", because there are other characters between "9" and "A" in the ASCII table we need to do this in 2 steps.

Code: Select all

 if ((receive[0] < 71) AND (receive[0] > 64)) then
If it is in this region then we will do the following:

Code: Select all

value = receive[0] - 55
After all of this we have in the variable "value" a value between 0 and 15.
Now we need to put it in the upper nibble of the variable, so we do this.

Code: Select all

value = value << 4
(I found another mistake, damn, I'm hurrying to much)
The above code shifts the variable left by 4 locations.
The mistake is that this shift must be done after the if structure.
Back to our example. in the case of character "3" coming in we have the following:
00110011 - which in decimal is 51, so 51 - 48 = 3 = 00000011, then we shift the bits 4 locations to the left and we have: 00110000.
After the first IF block the value = 00110000.
Now in the second IF block we do the same comparisons and divisions as in first but we have to take in to account that variable "value" has something in it.
If we take the example again in this case with character "B" we have the following:
(Damn another mistake, have to stop writing in a hurry)
00110000 - which in decimal is 66, so 66 - 55 = 11 = 00001011.
In order to put it in the variable without deleting the value in it we have to do the following:

Code: Select all

value = value OR (receive[1] - 55)
which does the following:
00110000 OR
00001011
------------
00111011 , which is 3B.

Code: Select all

dim value as byte  'this is the final variable
dim receive as char[2] ' this is the variable in which you load the ASCII from UART
value = 0
if ((receive[0] < 58) AND (receive[0] > 47)) then 
   value = receive[0] - 48                                 
else
     if ((receive[0] < 71) AND (receive[0] > 64)) then
        value = receive[0] - 55
     end if
end if
value = value << 4
if ((receive[1] < 58) AND (receive[1] > 47)) then
   value = value OR (receive[1] - 48)
else
     if ((receive[1] < 71) AND (receive[1] > 64)) then
        value = value OR (receive[1] - 55)
     end if
end if
ART_ME wrote:But all this does not matter to convert to ASCII and back have special operators:
Chr and Ord.
The above routines do not convert to ASCII and back, they just return the ASCII value of the character:
Chr(67) will return the letter "C"
Ord("C") will return the value 67 not 13.

P.S. Sorry for the mistakes, I have a tendency to do things in a hurry.
Just tell me....

ART_ME
Posts: 22
Joined: 19 Dec 2016 09:48

Re: Nybbles

#11 Post by ART_ME » 16 Feb 2017 18:46

serge87 wrote: 00110000
OR
00001011
------------
00111011 , which is 3B.
00110000 = %30
00001011 = %0B
-------------------
%30 + %0B = %3B, which is 00111011

Also:
00110000 = 48
00001011 = 11
-----------------
48 + 11 = 59, which is 00111011

Where mistake?
Last edited by ART_ME on 16 Feb 2017 19:14, edited 1 time in total.

ART_ME
Posts: 22
Joined: 19 Dec 2016 09:48

Re: Nybbles

#12 Post by ART_ME » 16 Feb 2017 18:57

serge87 wrote:

Code: Select all

value = receive[0] - 55
OK, your listing is good.

Why MikroE not use it to create HexToByte routine? :!:

User avatar
lana.arsic
mikroElektronika team
Posts: 1715
Joined: 15 Jan 2016 12:50

Re: Nybbles

#13 Post by lana.arsic » 21 Feb 2017 10:52

Hi,

I have forwarded your request to our developers to take in consideration.

Kind regards,
Lana

ART_ME
Posts: 22
Joined: 19 Dec 2016 09:48

Re: Nybbles

#14 Post by ART_ME » 21 Feb 2017 12:51

lana.arsic wrote:Hi,
I have forwarded your request to our developers to take in consideration.
Kind regards,
Lana
Yes!
One good turn deserves another.

Post Reply

Return to “mikroBasic PRO for ARM General”