linux writing string value as hex to serial

2019-09-09 17:43发布

问题:

here's my problem
i have a string with hex value such as

std::string str ="8C000002008E"  

and i want to write this as hex to serial out by using the

write()

I have a sony Display which i want to control with.
Passing a

unsigned char test[6] = {0x8c, 0x00, 0x00, 0x02, 0x00, 08E};

to the write method works. But i dont know how to convert the string to such a char array especially that the size of the char array has to be calculated on runtime.

Thanks for your help.

Here is my full code

#include <stdio.h>
#include <iostream>
#include <cstring>
#include <fcntl.h>
#include <termios.h>

#include <sstream>

using namespace std;
#define TERM_DEVICE "/dev/ttyUSB0"
#define TERM_SPEED "B9600"


int main() {

std::string teststr = "8C000002008E";

int fd, old_flags;

ssize_t length;

char buffer[16];

struct termios term_attr;

fd_set input_fdset;

if ((fd = open(TERM_DEVICE, O_RDWR)) == -1)
   {
    perror("terminal: Can't open device " TERM_DEVICE);
    return(1);
   }
            /* RS232 konfigurieren */
  if (tcgetattr(fd, &term_attr) != 0)
   {
    perror("terminal: tcgetattr() failed");
    return(1);
   }

  cfsetispeed(&term_attr, B9600);
  cfsetospeed(&term_attr, B9600);

  term_attr.c_cflag &= ~PARENB;

  term_attr.c_cflag &= CS8;
  term_attr.c_cflag &= CSIZE;
  term_attr.c_cflag &= CSTOPB;
  term_attr.c_iflag = 0;
  term_attr.c_oflag = OPOST | ONLCR;
  term_attr.c_lflag = 0;
  if (tcsetattr(fd, TCSAFLUSH, &term_attr) != 0)
    perror("terminal: tcsetattr() failed");

  if (tcgetattr(STDIN_FILENO, &term_attr) != 0)
   {
    perror("terminal: tcgetattr() failed");
    return(1);
   }

  old_flags = term_attr.c_lflag;
  term_attr.c_lflag &= ~(ICANON | ECHO);
  if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &term_attr) != 0)
    perror("terminal: tcsetattr() failed");

  while (1)
   {
    FD_ZERO(&input_fdset);
    FD_SET(STDIN_FILENO, &input_fdset);
    FD_SET(fd, &input_fdset);

    if (select(fd+1, &input_fdset, NULL, NULL, NULL) == -1)
      perror("terminal: select() failed");


    unsigned char test[6] = {0x8c, 0x00, 0x00, 0x02, 0x00, 0x8E};

    if (FD_ISSET(STDIN_FILENO, &input_fdset)){
          if ((length = read(STDIN_FILENO, buffer, 16)) == -1)
            perror("terminal: read() failed");
          else
            if (buffer[0] == '\33')
                break;
        else{
              write(fd, test , sizeof(test));
        }
     }


    if (FD_ISSET(fd, &input_fdset))
     {
      if ((length = read(fd, buffer, 16)) == -1)
        perror("terminal: read() failed");
      else
          cout << std::hex << buffer<< endl;

     }
   }

  term_attr.c_lflag = old_flags;
  if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &term_attr) != 0)
    perror("terminal: tcsetattr() failed");

  printf("Aborted.\n");
  close(fd);

return 0;

}

回答1:

If the problem is only one of converting the string to a char array, you can try the following:

#include <iostream>
#include <sstream>

int main(int argc, char **argv)
{
  const std::string str ="8C000002008E";

  // count the number of character pairs (i.e. bytes) in the string
  // and dynamically allocate an array of the required size
  const int numBytes = str.size() / 2;
  unsigned char* bytes = new unsigned char[numBytes];

  for (int i = 0; i < numBytes; ++i)
  {
    // grab two characters from the string...
    std::string twoChars = str.substr(2 * i, 2);

    // ...and convert them to an integer using a stringstream
    int byte;
    std::stringstream ss(twoChars);
    ss >> std::hex >> byte;

    // store the result in our char array
    bytes[i] = byte;
  }

  //
  // do something with the byte array here
  //

  // deallocate array before exiting
  delete[] bytes;
}

Please note that this assumes that the initial string always contains an even number of characters. Some extra code would be needed for handling input strings of an odd size.



回答2:

Probably fast solution I can't offer to you, but you may try this:

std::string str ="8C000002008E"  
std::vector<unsigned char> vect;
vect.resize(str.length() / 2);
for (size_t i = 0; i < str.length(); ++i)
{
    vect[i] = str[2*i] - ('0' - 7 * (str[2*i] >= '9'));    //it is possible to optimize this
    vect[i] <<= 4;
    vect[i] = str[2*i+1] - ('0' - 7 * (str[2*i+1] >= '9'));  //it is possible to optimize this
}

Didn't tried that, but should work, however, code is really not optimized, I have left this part for yourself.

Also this assumes that the initial string always contains an even number of characters.