【问题标题】:arduino read hex from serial rs232 inarduino 从串行 rs232 中读取十六进制
【发布时间】:2020-08-10 15:46:31
【问题描述】:

我从 rs232 Tx RX 读取串行数据时遇到问题

我的代码是

uint8_t cc;
char  rtx[MAX_LEN] = { 0 };
int   ii, lenn = 0;

    Serial.print("recv (HEX): ");
    Serial.println();
    while (mySerial.available())
    {
      cc = mySerial.read();
  
      if (cc < 0x10) Serial.print("0");
      Serial.print(cc, HEX);
      rtx[lenn] = cc; lenn++;
      Serial.print("");
    }
    
Serial.println();

在这里我可以看到我的输出没有问题

输出例如

recv (HEX): 
030039094C80703470326421A5713DFE01EA6B79AE8D9DBD94F523F95340217C739BCB3B75DE1D1EF09CF03D2F916AB390E92136074A41BBA4E95ACB

我想从外面打印 rtx 的问题

例如我用过这个代码

char  buffer[MAX_LEN] = { 0 };
sprintf(buffer, "%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X",rtx[0],rtx[1],rtx[2],rtx[3],rtx[4],rtx[5],rtx[6],rtx[7],rtx[8],rtx[9],rtx[10],rtx[11],rtx[12],rtx[13],rtx[14],rtx[15],rtx[16],rtx[17],rtx[18],rtx[19],rtx[20]);
Serial.println(buffer); 

它只给出有限的错误数据

我明白了

0300FF39094FFFC807034FFF70326421A571

问题是在 out 中添加 FFF,我无法获取所有 rtx[21],rtx[22],rtx[23],rtx[23],rtx[24]......

【问题讨论】:

  • 如果您有一个负数,您使用 sprintf 的代码会在输出中添加额外的 FF。您的缓冲区rtx 包含char,默认情况下可以签名或未签名。在您的系统中,它似乎已签名。因此,当您将其传递给可变参数函数时,它会使用符号扩展名转换为 int。您可以通过使用unsigned char 或指定除int int sprintf 之外的其他类型来避免这种情况。如果编译器支持inttypes.h,则可以使用"%02hhX""%02"PRIx8

标签: c arduino serial-port


【解决方案1】:

你的缓冲区需要两倍大加上一个尾随零字节:

uint8_t buffer[MAX_LEN*2 + 1] = { 0 };
sprintf(buffer, "%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X",rtx[0],rtx[1],rtx[2],rtx[3],rtx[4],rtx[5],rtx[6],rtx[7],rtx[8],rtx[9],rtx[10],rtx[11],rtx[12],rtx[13],rtx[14],rtx[15],rtx[16],rtx[17],rtx[18],rtx[19],rtx[20]);
Serial.println(buffer); 

值以字节存储,但要将它们转换为十六进制字符串,每个值需要 2 个字节/字符。

参数个数与格式字符串不匹配(21个参数,格式字符串20个)。

读取时,您必须检查 MAX_LEN 以避免缓冲区溢出。


下面是一些读取和显示缓冲区的示例代码:

#define MAX_LEN 100

uint8_t rtx[MAX_LEN] = { 0 };

ReadData();
PrintBuffer(20);


int ReadData()
{
    int lenn = 0;

    Serial.println("recv (HEX): ");

    while (mySerial.available()) {

        if (lenn >= MAX_LEN) {
            Serial.println();
            Serial.println("Buffer overflow");
            return(-1);
        }

        uint8_t cc = mySerial.read();
        PrintHexByte(cc);
        rtx[lenn++] = cc;
    }

    Serial.println();
    return(0);
}

void PrintBuffer(int len)
{
    if (len < 0 || len > MAX_LEN)
        len = MAX_LEN;

    for (int i = 0; i < len; ++i) {
        PrintHexByte(rtx[i]);
    }

    Serial.println();
}

void PrintHexByte(uint8_t cc)
{
    if (cc < 0x10)
        Serial.print("0");

    Serial.print(cc, HEX);
}

【讨论】:

  • 感谢您的回复告诉我是否可以像这样获取所有字节 String buffer[] = { rtx[0],rtx[1],rtx[2],rtx[3],rtx[ 4],rtx[5],rtx[6],rtx[7],rtx[8],rtx[9],rtx[10],rtx[11],rtx[12],rtx[13],rtx[ 14],rtx[15],rtx[16],rtx[17],rtx[18],rtx[19],rtx[20] };
  • 您已经在rtx[] 缓冲区中有这些字节。要以十六进制显示缓冲区,您可以使用循环并以十六进制格式打印每个字节,就像您在接收循环中所做的那样。
  • 仍不工作良好,我在同时将其输出给030039094C8170347032642191777F013D840DD174E665BF4F88ACC5A6FC021BBA8DD778E3C184CF80351572D36C895ED6881D2B5B244108F6239C89和sprintf的Serial.println(缓冲液);它给 030039094CFF81703470326421FF91777F013DFF840DFFD1
  • 感谢 Danny_ds 它工作得很好,但是在子字符串中使用你的代码有问题我已经测试过使用 String stringOne = PrintBuffer[16];字符串 test_01 = stringOne.substring(0, 2);不工作
猜你喜欢
  • 2019-03-09
  • 1970-01-01
  • 2016-03-21
  • 1970-01-01
  • 1970-01-01
  • 2018-02-02
  • 2015-12-25
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多