LINUX.ORG.RU

Алгоритм обработки экранирующих символов при работе с последовательным портом.

 , , ,


1

2

Помогите пожалуйста с алгоритмом. Предложили на собеседовании дописать в следующем коде цикл
обработки экранирующих символов при приеме данных из последовательного порта.
Кроме того в конечном хранилище response должен находится принятый пакет, который начинается с байта PACKET_BYTE_START (неэкранированного).
То есть перед каждой обработкой в массиве buf[512] будет находится bytesReaded количество прочитанных из порта байт не обязательно с начала пакета естественно,
и из этого массива нужно будет удалить экранирующие байты PACKET_BYTE_ESC (если они не являются полезными данными).

#define PACKET_BYTE_START           0xFF
#define PACKET_BYTE_ESC             0xFE

uint8_t buf[512]; // массив содержащий прочитанные из порта байты
std::basic_string<uint8_t> response; // хранилище куда нужно поместить полезные байты
while (1) {
  // Чтение доступных байт из порта устройства
  uint16_t bytesReaded = portIO->read(buf, sizeof(buf),  read_timeout*1000);
  // Если в порт ничего не пришло, выходим из цикла
  if (bytesReaded <= 0) {
    return E_TIMEOUT;
  }

  // Обработка и удаление экранирующих символов (необходимо дописать цикл обработки)
  for (size_t i = 0; i < bytesReaded; i++) {
  // сохранить текущий прочитанный байт
  uint8_t byte = buf[i];
  // поместить байт в конечное хранилище
  response.push_back(byte);
  } // до тех пор, пока не обработали все принятые из порта байты
}

При таком раскладе в цикле for (size_t i = 0; i < bytesReaded; i++) просто тупо копируются байты из буфера в хранилище response без всякой обработки.
а мне нужен такой цикл

for (size_t i = 0; i < bytesReaded; i++)
{

}
чтобы в конечном хранилище response был пакет без экранирующих байтов.

Как пытался решать? Какие проблемы при этом возникли?

А то с такими запросами надо в Job.

Waterlaz ★★★★★
()

Предложили на собеседовании дописать в следующем коде цикл

С такими вопросами вам туда не надо. А то потом ракеты падают.

PPP328 ★★★★★
()
Ответ на: комментарий от PPP328

С такими вопросами вам туда не надо. А то потом ракеты падают.

Блин. Вот спасибо. Я-то голову сломал, что же делать. А мне оказывается туда не надо. Чтобы я делал без таких мудрых советов.

podovalov5
() автор топика

Мб поможет в интернете поискать на железячных сайтах протоколы к железкам например, содержающие экранированные последовательности и посмотреть их реализации, далее делать по аналогии.

tuk9
()
Ответ на: комментарий от podovalov5

Вы не можете выполнить задание с собеседования на работу. Значит вы не квалифицированны для этой работы. Задание примитивно, если вы не можете его выполнить в голове\на бумаге\в коде, значит вам на этой работе делать нечего.

PPP328 ★★★★★
()
Ответ на: комментарий от podovalov5

А мне оказывается туда не надо

Ну реально ведь не надо)

А по теме. Тебе надо сделать проверку на PACKET_BYTE_START и если тру, то проверить след. байт на PACKET_BYTE_ESC и если тру , то его не отправлять в массив и перейти к след. байту. Это при условии, что полное сообщение выглядит так: «PACKET_BYTE_START, PACKET_BYTE_ESC, полезные байты»

outsider ★★
()
Ответ на: комментарий от outsider

Там еще нужно обработать ESC ESC случаи:

bool flag = false;
bool start = false;

for (i = 0; i < size; i++)
{
    if (!start) && (a[i] != start) 
        continue;

    start = true;
    if ((a[i] == esc) && (!flag))
        flag = true;
    else
    {
        flag = false;
        push_back(a[i]);
    }
}

PPP328 ★★★★★
()
Ответ на: комментарий от PPP328

нее, сказано что только экранирующую послед. то есть последовательность старт еск, а дальше уже полезная инфа, даже след. еск

outsider ★★
()
Ответ на: комментарий от PPP328

хотя

и из этого массива нужно будет удалить экранирующие байты PACKET_BYTE_ESC (если они не являются полезными данными).

не понятно, что значит не являются полезными

outsider ★★
()
Последнее исправление: outsider (всего исправлений: 1)
Ответ на: комментарий от outsider

Это повсеместная практика. В условии не написано, но обычно там еще один байт есть - байт окончания передачи. Тогда будет типа FF 00 01 02 03 04 05 06 07 FE. При этом есть загвоздка - нельзя внутри посылки отправить FF и FE. Поэтому выделяют третий байт (например FD) и используют его как экранатор: FF 00 FD FF 01 02 03 04 FD FD 05 06 FD FE 07 FE.

PPP328 ★★★★★
()
Ответ на: комментарий от PPP328

обычно делают старт байт, контр. байт, полезная инфа, контр. байт или какая нить crc сумма полезной инфы, стоп байт и все сообщение определенной длины

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

outsider ★★
()
Ответ на: комментарий от outsider

Чексумма обычно идет в конце.

может и последовательность начала сообщения быть, особенно при помехах

Именно для этого и нужен экранатор.

обычно делают старт байт, контр. байт, полезная инфа, контр. байт

Так делают не всегда. И такой подход плох когда много информации переменной длины. Чаще делают именно через экранаторы. Как пример - проекторы Barco - старт байт FE, конец - FF, экранатор 80. Да, часто делают сообщения фиксированной длины, но обычно когда протокол одинаковый для RS232\LAN\USB. Тогда это удобно (google 0x06, 0x0E, 0x2B, 0x34). Там даже фиксированной длины строки (128 байт, пустые забиваются нулями). И что удобнее - переменной длины мессадж с длиной 1-128 или всегда 128?

PPP328 ★★★★★
()
Ответ на: комментарий от outsider

Чексума в каналах с помехами нужна всегда. А в RS232 лучше переменная длина, ибо скорости зачастую до 2400 не дотягивают. А чем меньше скорость тем дальше можно протянуть кабель.

PPP328 ★★★★★
()
Ответ на: комментарий от PPP328

Всё получилось. Алгоритм действительно нехитрый. Просто нужно было посидеть часок самому подумать, а не в ЛОР гадить. Всё уже загрузил на ракету. Спасибо всем за советы.

podovalov5
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.