开发者

Most efficient way of writing byte array for streaming

开发者 https://www.devze.com 2023-03-06 18:03 出处:网络
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 siz

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 +开发者_如何学Python= 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.


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.


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));
0

精彩评论

暂无评论...
验证码 换一张
取 消