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