首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >如何在C中转换从串口传入的十六进制值?

如何在C中转换从串口传入的十六进制值?
EN

Stack Overflow用户
提问于 2018-10-26 00:10:55
回答 1查看 742关注 0票数 0

概述:我想使用Visual Studio (C语言)通过串行COM端口从传感器读取24字节数据包的小端十六进制值。每当有新数据发送到端口时,我都需要更新串行读取,并将数据的一些字节解释为浮点值。当串行数据可用时,我如何开始从COM端口读取数据,组织字节,并将它们转换为浮点数/有用的信息?

详细信息:传入的数据包是已知的24字节长度,并以已知字符("{“和"}")开始/结束,因此这有助于了解要捕获的字节数以及如何分解它们。字节7-10包含小端十六进制格式的气体1浓度数据,字节11-14包含小端十六进制格式的气体2浓度数据。示例数据包如下所示:

Example 24-byte HEX packet 1

类似数据包的另一个示例(由传感器的数据表提供)如下所示:

Example 24-byte HEX packet 2

我为整个操作绘制的伪代码概述如下:

代码语言:javascript
复制
If serial data is available{

    //read serial packet into char array
    Char serialString[24]  = read serial until newline character () 

    startBracketHexChar = serialString[0] //”{“ part of packet
    Gas1HexChar= serialString[6-9]      //gas measurement 1 data from packet
    Gas2HexChar = serialString[10-13]   //gas measurement 2 data from packet
    tempHexChar = serialString[14-17]   //temp measurement from packet
    endBracketHexChar = serialString[23]        //”}” part of bracket

    //if packet is as expected…
    if (startBracketHexChar == ‘{‘ && endBrackHexChar == ‘}’){  

        Gas1Float = char.to.float(Gas1HexChar)  //convert char to float type
        Gas2Float = char.to.float(Gas2HexChar)  //convert char to float type
        tempFloat = char.to.float(tempHexChar)  //convert char to float type
        gas1textBox.Text = Gas1Float;           //display gas 1 reading 
        gas2textBox.Text = Gas2Float;           //display gas 2 reading 
        temptextBox.Text = tempFloat;           //display temp reading
    }
    else {
        ErrortextBox.Text = “Packet error”; //unexpected packet error
    }
}

我认为我在伪代码中关于读取Gas1HexChar数组的假设是非常错误的(也许它需要一个字符一个字符地读取并拼接在一起,而不是在一个数组块中?)和转换它(在调用一个字符字符串一个十六进制值,然后将该十六进制值转换为浮点数?)-这是我的知识和经验非常有限的地方,实现建议将非常感谢。

EN

回答 1

Stack Overflow用户

发布于 2018-10-26 02:26:10

好的,不用担心,这并不是很难。

我重新编写了您的伪代码,以便将其编译为C代码片段。我相信你问题的主要部分是关于如何引入和组装一个多字节的值。在下面的代码块中,这是decode函数。

在处理像您这样的二进制数据包时,比起仅仅使用char,使用unsigned char要好得多。这使得转换更容易/更正确。

您说数据包以换行符终止,但这并未显示在图中。而且,由于我们处理的是二进制数据,正如您在顶部注释中确认的那样,数据包的数据部分中的任何有效字节都可能是0x0A (即换行符),因此在看到换行符之前,我们不能逐个读取字符。

如果在最后确实有换行符,我们可能需要读取25个字节,并只检查最后一个字符。

我不做windows :-),所以我不知道访问COM端口的细节,但我已经编写了你可以填充的函数。

无论如何,代码如下,请原谅不必要的样式清理

代码语言:javascript
复制
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>

typedef struct {
    char Text[100];
} TextBox_t;

FILE *stream;

TextBox_t gas1textBox;
TextBox_t gas2textBox;
TextBox_t temptextBox;
TextBox_t ErrortextBox;

// serial_data_is_available -- check for data ready
int
serial_data_is_available(void)
{

    return 1;
}

// serial_get -- get single byte from device
unsigned char
serial_get(void)
{

    return rand();
}

// serial_buf -- assemble packet buffer
int
serial_buf(unsigned char *buf,int buflen)
{
    int idx;

    for (idx = 0;  idx < buflen;  ++idx)
        buf[idx] = serial_get();

    return idx;
}

// decode -- get a binary value
uint32_t
decode(unsigned char *buf,int beg,int end)
{
    uint32_t acc = 0;

    for (int idx = end;  idx >= beg;  --idx) {
        acc <<= 8;
        acc |= buf[idx];
    }

    return acc;
}

// floatget -- get a float value
float
floatget(unsigned char *buf,int beg,int end)
{
    union {
        float fval;
        uint32_t val;
    } join;

    join.val = decode(buf,beg,end);

    return join.fval;
}

// process_packet -- process a single packet
void
process_packet(void)
{
    // for raw binary data, unsigned is better
    unsigned char buf[24];

    // read serial packet into char array
    serial_buf(buf,sizeof(buf));

    // "{" part of packet
    char start = buf[0];

    // "}" part of bracket
    char end = buf[23];

    //if packet is as expected…
    if ((start == '{') && (end == '}')){
        // gas measurement 1 data from packet
        float Gas1Float = floatget(buf,6,9);

        // gas measurement 2 data from packet
        float Gas2Float = floatget(buf,10,13);

        // temp measurement from packet
        float tempFloat = floatget(buf,14,17);

        sprintf(gas1textBox.Text,"%f",Gas1Float);
        sprintf(gas2textBox.Text,"%f",Gas2Float);
        sprintf(temptextBox.Text,"%f",tempFloat);
    }
    else {
        strcpy(ErrortextBox.Text,"Packet error"); //unexpected packet error
    }
}

void
loop(void)
{

    while (1) {
        if (serial_data_is_available())
            process_packet();
    }
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/52993785

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档