Наиболее эффективный способ записи байтового массива для потоковой передачи

Мне нужно создать байтовый массив, который необходим для потоковой передачи на другое устройство через 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::string а также std::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

Конфигурация и значение настройки известны заранее, это указано в документации устройства. Этот вопрос связан с тем, что я задал здесь

Спасибо за усилия до сих пор.

2 ответа

Решение

Кольцевой буфер является типичным решением для подобных проблем.

Я понятия не имею, на каком устройстве вы находитесь, но я просто предположу, что вы пишете для какого-то встроенного устройства. Давайте предположим, что есть какие-то прерывания, перемещающие данные из кольцевого буфера в UART. Это прерывание вызовет getc, другой код позвонит putc а также 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);
    }
};

Как правило, вы не хотите, чтобы буфер динамически увеличивался для чего-то подобного. В приведенном выше коде есть много возможностей для улучшения, а также есть библиотеки, доступные для такого рода вещей.

Эта конкретная реализация также никогда не позволяет полностью заполнить буфер, но в результате код становится проще. Возможно, я бы не стал использовать этот код в производстве, но, надеюсь, это шаг в правильном направлении.

Если 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));
Другие вопросы по тегам