How to connect two half bytes

hello, half bytes are coming into the buffer, how do I select two half bytes and connect them to get the code in ASCii C1? Command to the port 8F C1 FF FF 5D

#define K_line_RX 0 
#define K_line_TX 1 
void setup(){
  pinMode(K_line_RX, INPUT); 
pinMode(K_line_TX, OUTPUT);
Serial.begin(14400);
}
char buff[30];
void loop(){
   if (Serial.available() > 0){
    delay(10);
    Serial.readBytes(buff,14);
     Serial.println(buff[3]);
     memset(buff, 0, sizeof(buff));
   }
delay(10);
}

Which is received first, low nibble or high nibble? Look at how the transmitter sends.

Fix your code formatting.

#define K_line_RX 0
#define K_line_TX 1
void setup() {
  pinMode(K_line_RX, INPUT);
  pinMode(K_line_TX, OUTPUT);
  Serial.begin(14400);
}
char buff[30];
void loop() {
  if (Serial.available() > 0) {
    delay(10);
    Serial.readBytes(buff, 14);
    Serial.println(buff[3]);
    memset(buff, 0, sizeof(buff));
  }
  delay(10);
}

I take two characters from the buffer and want to connect them and send them back to the port buff[3] C + buff[4] 1 = It should work С1 I do not know how to do this.

Serial ONLY works with 8-bit characters, each a full byte long.

If you receive "C1" as text and want to convert it to a number, you can look at strtoul; the page also links to an example on strtol(3) - Linux manual page.

void setup() {
  Serial.begin(115200);
  Serial.println((0xC << 4) + 0x1, HEX);
}

void loop() {}

Thanks, I'll keep working.

Your question has nothing to do with IDE 2.x or any other version of the IDE. I have moved it to the Programming section of the forum. Before you post in future, please read the sticky post at the top of the forum section to understand what questions would be appropriate there.

I think it's spelled nybble :slight_smile:

Useless facts:
In Swedish it is nibble. I guess they took the word, Swedishized it because they couldn't stand borrow a word straight flat, and so it ended up being another English word. Or they only heard the word and thought it was nibble. :upside_down_face:

so reading your description,I assume that

  • you are actually getting ASCII symbols and the text "8F C1 FF FF 5D" into your buffer (including spaces).

  • and what you want to is take buff[3] which is the character 'C' and buff[4] which is character '1' and build a byte value 0xC1

if you are 100% sure the transmission is correct and you'll always get the correct data then you can do

byte highNibble = (buff[3] >= '0' && buff[3] <= '9') ? (buff[3] - '0') : (buff[3] - 'A' + 10);
byte lowNibble  = (buff[4] >= '0' && buff[4] <= '9') ? (buff[4] - '0') : (buff[4] - 'A' + 10);
byte result = (highNibble << 4) | lowNibble;

➜ the first two lines convert an ASCII character representing hexadecimal digit into a single byte by decoding each character to its numeric value (relying on the fact that in ASCII code the numbers and letters are consecutive so subtracting '0' or 'A' and adding 10 gives you the value )

then it's just shifting the high nibble by 4 bits to the left and combining it with the low nibble using a bitwise OR to get the right HEX value and storing the result.

not clear what you're trying to do.

each element of buff [] is an 8-bit character. see ASCII. ASCII codes are only 7-bits, 0-127, 0-0x7F. 0xC1 is not a valid ASCII code.

perhaps this would you understand what you're working with

output:

    0x8f    0xc1    0xff    0xff    0x5d
 0x8 0xF 0xC 0x1 0xF 0xF 0xF 0xF 0x5 0xD

unsigned char buf [] = { 0x8F, 0xC1, 0xFF, 0xFF, 0x5D };
const int     BufSz  = sizeof(buf);

char s [90];

// -----------------------------------------------------------------------------
void
setup (void)
{
    Serial.begin (9600);

    for (int n = 0; n < BufSz; n++)  {
        sprintf (s, "    0x%02x", buf [n]);
        Serial.print (s);
    }
    Serial.println ();

    for (int n = 0; n < BufSz; n++)  {
        sprintf (s, " 0x%X", buf [n] >> 4);
        Serial.print (s);

        sprintf (s, " 0x%X", buf [n] & 0xF);
        Serial.print (s);
    }
    Serial.println ();
}

void loop () { }

your code is very good, I checked it, it works, thank you, this symbol is C1. in fact, it gives permission for the further operation of the entire program, then the same data will come to the port, but with the last two bytes variable, but I will apply your code for the last operations, thank you again

this is another approach


const char buf [] = "ackC1born";
const int     BufSz  = sizeof(buf);

unsigned val;
char     s [90];

// -----------------------------------------------------------------------------
void
setup (void)
{
    Serial.begin (9600);

    sscanf (&buf [3], "%2x", & val);
    Serial.println (val, HEX);
}

void loop () {
    if(Serial.available ())  {
        char buf [90];
        Serial.readBytesUntil ('\n', buf, sizeof(buf)-1);

        sscanf (&buf [3], "%2x", & val);
        Serial.println (val, HEX);
    }
}

no, this method doesn't suit me because it works with an array, but I need it to work with a buffer.,

A buffer IS an array.

see The C Programming Language, pg 22 discussing arrays

What is surprising is that your protocol does not seem to have any header / start marker or end marker

It’s surprising as you can’t be sure you did not miss any byte in the communication and that you are perfectly in sync with the sender …

That’s very error prone …

I took one procedure and worked it out without involving the main code, then I will insert this part into the main loop, I had to figure out how to solve the problem.

Thanks, I downloaded this document, I'll read it.

vanilla C language

unsigned char b, nibble;

nibble = b & 15; // right nibble, 4 bits

nibble = b >> 4; // left nibble
```NibbleArray