-1

I'm making a program for a microcontroller (mbed LPC1768) and having a few problems to decode serial input to uint8_t.

I get a char ackBuffer[20]; filled with input from an external device. What we get is for example: F040A34B6785121\r

What I want to do is to get an uint8_t array where each number is symbolized by the hex value of 2 characters. The F is to show the message from the external device is started and the carriage return is the end of each message.

So what I want in the uint8_t array is:

0x04
0x0A
0x34
...

To make it even harder it can be the ackBuffer is a smaller size, so for example only F04004A\r (if this can be easy fixed then it's very nice, but I can work around this problem myself.

Thank you!

Jannes
  • 29
  • 9
  • How would you convert the string `"04"` into the integer `0x04`? – Oliver Charlesworth Dec 20 '13 at 18:28
  • @OliCharlesworth An old way of doing that would be `scanf("%2.2x", &val)`. – Zac Howland Dec 20 '13 at 18:32
  • ackBuffer[0] = '0'; ackBuffer[16] = 0;/*null terminate*/ Then follow http://stackoverflow.com/questions/1070497/c-convert-hex-string-to-signed-integer – IdeaHat Dec 20 '13 at 18:35
  • @MadScienceDreams: That's how you would do it on a PC where runtime costs less than development time. Not on a microcontroller, where processing power is severely limited. – Ben Voigt Dec 20 '13 at 18:42
  • @Zac: `sscanf` is definitely not a good performance target. `strtol` would be the best library-provided function, but it is still more general than necessary. – Ben Voigt Dec 20 '13 at 18:47
  • @BenVoigt True ... I didn't say it was efficient, just that it was old ;) It was the common method used for hardware communication via serial bus at a company I worked at 12+ years ago. – Zac Howland Dec 20 '13 at 18:52
  • Performance is not that much of an issue. The microcontroller runs at 100Mhz and that's fast enough. – Jannes Dec 21 '13 at 15:27

1 Answers1

0

So I'm assuming that an ackMessage must start with 'F' and end with '\r'. And I'm even assuming that, since you work on a micro controller, anything that does more than required (eg. library functions) should be avoided. Given that you just have to iterate over the buffer:

uint8_t charToHex(unsigned 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;
  assert(false);
}

#define BUFFER_SIZE (20)

int main(void)
{
  char ackBuffer[BUFFER_SIZE] = "F12345890AB\r";
  uint8_t result[(BUFFER_SIZE-2)/2]; // at most 9 bytes since it's 20 - 2 / 2

  char* ptr = ackBuffer;

  assert(*ptr == 'F');
  ++ptr;

  int count = 0;
  while(*ptr != '\r')
  {
    uint8_t value = charToHex(*ptr) << 4 | charToHex(*(ptr+1));
    result[count++] = value;
    ptr += 2;
  }

  int i;
  for (i = 0; i < count; ++i)
    printf("%x\n", result[i]);

  return 0;
}

Mind that you must have a charToHex consistent with the used encoding and probably you could need some more sanity checks around the code.

Jack
  • 131,802
  • 30
  • 241
  • 343
  • @OliCharlesworth: I was bored :( – Jack Dec 20 '13 at 18:39
  • Thanks mate for the fast answer! Will try to do this. – Jannes Dec 20 '13 at 18:40
  • @BenVoigt: yes, it was a typo (that was correct in the code indeed). Thank you, just fixed it. – Jack Dec 20 '13 at 18:44
  • Yes, it ends with a '\r' (carriage return, 13 in ASCII) and not an r. Tried it before with sscanf, but didn't really work out. Also tried some difficult things but also didn't work how I wanted. – Jannes Dec 20 '13 at 18:46