如何发送十六进制字符串到串口?

时间:2019-01-05 09:01:50

标签: c linux serial-port

我正在开发一个串行通信程序,以在主机PC(Linux)和微控制器之间发送和接收数据。现在,我必须将十六进制数据发送到MCU。 因此,如何在不使用sprint / printf的情况下将缓冲区字符串数据转换为十六进制字符串,以便用户将诸如“ AA12CDFF1000001201”之类的字符串而不是“ \ xAA \ x12 \ xCD \ xFF \ x10 \ x00 \ x00 \ x00 \ x12 \ x01”发送到MCU。我也看到了Sending Hexadecimal to Serial Port,但是它没有帮助,因为它说我可以使用sprintf将字符串转换为十六进制,但是在这种情况下,我不想使用sprinf。 基本上我想要的是: 如果用户给定输入=“ AA12CDFF1000001201”,我必须将其转换为以下格式“ \ xAA \ x12 \ xCD \ xFF \ x10 \ x00 \ x00 \ x00 \ x12 \ x01”,然后将其写入串行端口。

#include <stdio.h>   /* Standard input/output definitions */
#include <string.h>  /* String function definitions */
#include <unistd.h>  /* UNIX standard function definitions */
#include <fcntl.h>   /* File control definitions */
#include <errno.h>   /* Error number definitions */
#include <termios.h> /* POSIX terminal control definitions */
void main()
{
int fd;
fd = open("/dev/ttyf1", O_RDWR | O_NOCTTY | O_NDELAY);
char buff[]="\xAA\x12\xCD\xFF\x10\x00\x00\x12\x01";
write(fd, buff, sizeof(buff));
close(fd);
}    

5 个答案:

答案 0 :(得分:1)

在与Hessam和Arkku进行了全面的讨论之后,新版本的代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

char* str2hexstr(char* inbuff) {

    char *outbuff;

    if (strlen(inbuff)%2) {
        outbuff=malloc((strlen(inbuff)*2+3)*sizeof(char));
        outbuff[strlen(inbuff)*2+2]='\0'; }
    else {
        outbuff=malloc(strlen(inbuff)*2+1*sizeof(char));
        outbuff[strlen(inbuff)*2]='\0'; }

    for (int strin=0,strout=0;strin<strlen(inbuff);) {
        outbuff[strout++]='\\';
        outbuff[strout++]='x';
        outbuff[strout++]=(!strin&&strlen(inbuff)%2)?'0':inbuff[strin++];
        outbuff[strout++]=inbuff[strin++];
    }
    return(outbuff);
}
int main()
{
    char inbuff1[]="123",inbuff2[]="1234";
    char *outbuff;

    outbuff=str2hexstr(inbuff1);
    printf("%s\n",outbuff);
    free(outbuff);
    outbuff=str2hexstr(inbuff2);
    printf("%s\n",outbuff);
    free(outbuff);
    return 0;
}

答案 1 :(得分:0)

从字符串转换为字节

#include <stdio.h>
#include <string.h>
#include <stdint.h>

/* Dummy input */
char input[] = "11121314151617181920";
uint8_t output[32];

/* Convert input char to int */
uint8_t
char2byte(char c) {
    if (c >= '0' && c <= '9') {
        return c - '0';
    } else if (c >= 'A' && c <= 'F') {
        return c - 'A' + 10;
    } else if (c >= 'a' && c <= 'f') {
        return c - 'a' + 10;
    }
    return 0;
}

int
main() {
    size_t len;

    /* String must be even */
    len = strlen(input);
    if (len & 1 == 0) {

    }
    /* Process all inputs, 2 chars for single byte */
    for (size_t i = 0; i < len / 2; ++i) {
        output[i] = char2byte(input[2 * i]) << 4;
        output[i] |= char2byte(input[2 * i + 1]);
    }

    /* Test, expected is 0x13 */
    printf("Test output[2] = %02X\r\n", (unsigned)output[2]);

    return 0;
}

如果运行代码:Test output[2] = 13

从字节转换为字符串

类似这样的事情。目标是将每个字节的每个半字节转换为char。这意味着输出长度是初始缓冲区大小的两倍。

#include <stdio.h>
#include <string.h>
#include <stdint.h>

/* Output array */
char output[128];

/* Dummy input data array */
char data[] = {0x12, 0x13, 0x14, 0x00, 0x5A};

/* Convert each nibble to char */
char num2char(uint8_t num) {
    if (num < 10) {
        return num + '0';
    } else if (num < 16) {
        return num - 10 + 'A';
    }
}

int
main() {
    size_t i;
    printf("Hello World\r\n");

    /* Process all bytes */
    for (i = 0; i < sizeof(data) / sizeof(data[0]); i++) {
        /* Generate it twice, for high and low nibble */
        output[2 * i] = num2char((data[i] >> 4) & 0x0F);
        output[2 * i + 1] = num2char((data[i]) & 0x0F);
    }
    /* Trailing zero for string */
    output[2 * i] = 0;

    printf("Output: %s\r\n", output);

    return 0;
}

运行代码时:

Output: 121314005A  

答案 2 :(得分:0)

看看这个,不是一个干净的代码,但是应该做的

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void hexify(const char *input, char *output)
{
    int i = 0;
    int o = 0;
    while(1)
    {
        if(input[i] == 0) break; 
        output[o++] = '\\';
        output[o++] = 'x';
        output[o++] = input[i++];
        if(input[i] == 0) break; 
        output[o++] = input[i++];
    }
    output[o] = 0;
}

 int main()
 {
     char test[]="112233AA"; //user input
     if((strlen(test) % 2) && strlen(test) != 1)
         printf("Input is not in correct format");
     else
     {
         char *out = malloc(2 * strlen(test) + 1);
         hexify(test, out);
         printf("%s", out);
         free(out);//dont forget this
     }
     return 0;
 }

答案 3 :(得分:0)

您想要这样的东西吗?

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main()
{
    char inbuff[]="AA12CDFF1000001201";
    char *outbuff;

    if (strlen(inbuff)%2) {
            printf("error : strlen is odd");
            exit(1);}
    outbuff=malloc((strlen(inbuff)*2+1)*sizeof(char));
    for (int strin=0,strout=0;strin<strlen(inbuff);) {
        outbuff[strout++]='\\';
        outbuff[strout++]='x';
        outbuff[strout++]=inbuff[strin++];
        outbuff[strout++]=inbuff[strin++];
    }
    outbuff[strlen(inbuff)*2]='\0';
    printf("%s\n",outbuff);
    return 0;
}

答案 4 :(得分:0)

  

如何将我的缓冲区字符串数据转换为十六进制字符串....因此用户发送...?

     

给定输入=“ AA12CDFF1000001201”,我必须将其转换为以下格式“ \ xAA \ x12 \ xCD \ xFF \ x10 \ x00 \ x00 \ x12 \ x01”,然后将其写入串行端口。

当不需要中间存储到缓冲区时,这非常简单。

一次将原始 string 的2个字符 1 转换为一个字节,每次迭代写入每个字节。

#include <ctype.h>

void write_hex_string(const char *hs) {
  while (isxdigit(hs[0]) && isxdigit(hs[1])) {
    char buf[3] = { hs[0], hs[1], '\0' };
    unsigned char value = (unsigned char) strtol(buf, 0, 16);
    write(fd, &value, sizeof value);
    hs += 2;
  }
}

样品使用

write_hex_string("AA12CDFF1000001201");

如果代码可以在过程中更改原始的 string ,那么生活也很容易。因为有一个方便的位置来存储转换。

void write_hex_string(char *hs) {
  char *pair  = hs;
  size_t length = 0;
  while (isxdigit(pair[0]) && isxdigit(pair[1])) {
    char buf[3] = { pair[0], pair[1], '\0' };
    hs[length++]  = (unsigned char) strtol(buf, 0, 16);
    pair += 2;
  }
  write(fd, hs, length);
}

1 ,只要两个字符都是十六进制数字:['0'-'9','A'-'F','a'-'f']。