写入流式字节数组的最有效方法

发布于 2024-11-08 11:26:44 字数 1098 浏览 0 评论 0原文

我需要创建一个字节数组,需要通过 UART 流式传输到另一个设备。我可以事先填写一些固定参数,但字符串等变量是动态调整大小的。到目前为止,我一直在做:

unsigned char buffer[255];
unsigned char wr_head = 0;
buffer[wr_head++] = 0x01; // and so on
memcpy(&buffer[wr_head], &some_chararray, sizeof(some_chararray));
wr_head += some_chararray;

我尝试过其他方法,例如 std::stringstd::vector 但我觉得有很多可管理的方法为流写入字节数组的方式。建议?

编辑:请就性能提出建议,因为是线程化的。

edit2:很抱歉第一次缺乏细节。该设备确实是嵌入式设备。尽管有些人提出了一些解决方案,但这并不是我真正想要的。也许我当前实现的一个片段会消除一些混乱:

unsigned char buffer[255];
unsigned char wr_head = 0;

buffer[wr_head++] = 0x01; // Set message type
buffer[wr_head++] = 0x30; // message length
memcpy(&buffer[wr_head], &some_chararray, sizeof(some_chararray));
wr_head += some_chararray;
buffer[wr_head++] = CalChecksum;
UartSend(&buffer, wr_head); // Send array to stream out from UART

配置和设置值是预先知道的,由设备文档提供。这个问题与我在此处中提出的问题有关,

感谢您的努力迄今为止。

I need to create a byte array that is needed to be stream to another device through UART. There are some fixed parameters that I can fill in before hand but variables such as string is dynamically sized. Right up till now, I've been doing:

unsigned char buffer[255];
unsigned char wr_head = 0;
buffer[wr_head++] = 0x01; // and so on
memcpy(&buffer[wr_head], &some_chararray, sizeof(some_chararray));
wr_head += some_chararray;

I've experimented with other methods like std::string and std::vector but I felt that there is much manageable way of writing byte array for streams. Suggestions?

edit: Please advice on performance as well because is threaded.

edit2: Sorry for lacking of details the first time around. The device is indeed an embedded device. Though some suggested some solution, its not really what I want. Maybe a snippet of my current implementation will clear some confusion:

unsigned char buffer[255];
unsigned char wr_head = 0;

buffer[wr_head++] = 0x01; // Set message type
buffer[wr_head++] = 0x30; // message length
memcpy(&buffer[wr_head], &some_chararray, sizeof(some_chararray));
wr_head += some_chararray;
buffer[wr_head++] = CalChecksum;
UartSend(&buffer, wr_head); // Send array to stream out from UART

The configuration and setting value is known before hand, provided by the device documentation. This question is related to what I've asked in here

Thanks for the effort so far.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

养猫人 2024-11-15 11:26:44

环形缓冲区是此类问题的典型解决方案。

我不知道您使用的是哪种设备,但我只是假设您正在为某种嵌入式设备编写代码。假设有一些中断将数据从环形缓冲区移动到 UART。该中断将调用getc,其他代码将调用putcputs

class RingBuffer {
private:
    static unsigned BUFSZ = 256;
    volatile unsigned char buf[BUFSZ];
    volatile unsigned char read, write;

public:
    RingBuffer() : read(0), write(0) { }

    // Blocks until space is available
    void putc(unsigned int c) {
        while (((write - read) & (BUFSZ - 1)) == 1)
            sleep();
        buf[write++ & (BUFSZ - 1)] = c;
    }

    // Returns -1 if empty
    int getc() {
        if (read == write)
            return -1;
        return buf[read++ & (BUFSZ - 1)];
    }

    // There are faster ways to write this.
    void puts(char *str) {
        for (; *str; ++str)
            putc(*str);
    }
};

通常,您不希望缓冲区因类似情况而动态增长。上面的代码有很多改进的空间,并且也有可用于此类事情的库。

这种特定的实现也永远不会让您完全填充缓冲区,但因此代码更简单。我可能不会将此代码投入生产,但希望这是朝着正确方向迈出的一步。

A ring buffer is a typical solution for problems like these.

I have no idea what kind of device you're on, but I'll just suppose that you're writing for some kind of embedded device. Let's assume that there's some interrupt moving data from the ring buffer to the UART. This interrupt will call getc, other code will call putc and puts.

class RingBuffer {
private:
    static unsigned BUFSZ = 256;
    volatile unsigned char buf[BUFSZ];
    volatile unsigned char read, write;

public:
    RingBuffer() : read(0), write(0) { }

    // Blocks until space is available
    void putc(unsigned int c) {
        while (((write - read) & (BUFSZ - 1)) == 1)
            sleep();
        buf[write++ & (BUFSZ - 1)] = c;
    }

    // Returns -1 if empty
    int getc() {
        if (read == write)
            return -1;
        return buf[read++ & (BUFSZ - 1)];
    }

    // There are faster ways to write this.
    void puts(char *str) {
        for (; *str; ++str)
            putc(*str);
    }
};

Typically, you don't want to make the buffer dynamically grow for something like this. There's lots of room for improvement in the above code, and there are also libraries available for this kind of thing.

This particular implementation also never lets you fill the buffer completely, but the code is simpler as a result. I probably wouldn't put this code in production, but hopefully it's a step in the right direction.

撩动你心 2024-11-15 11:26:44

如果 UartSend 是一个阻塞函数,那么你可以这样做:

void UartSend(byte b) { UartSend(&b, 1); } // sends one byte

UartSend(0x01); // Set message type
UartSend(0x30); // message length
UartSend(some_chararray,sizeof(some_chararray));

If UartSend is a blocking function then you can do just this:

void UartSend(byte b) { UartSend(&b, 1); } // sends one byte

UartSend(0x01); // Set message type
UartSend(0x30); // message length
UartSend(some_chararray,sizeof(some_chararray));
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文