2016-08-18 4 views
0

Мы разработали простой протокол фиксированной длины для встроенного устройства. Каждый пакет только два байта:Пакетное оснащение для очень коротких последовательных пакетов

bits | 15..12 | 11..4  | 3..0 | 
     | OpCode |  DATA  | CRC4 | 

Мы используем «ВРК-основой обрамление», то есть приемник собирает два байта, вычисляют CRC4 и если она соответствует кадру считается действительным. Как вы можете видеть, нет начального кадра или конца кадра.

Существует улов: рекомендуемая длина сообщения для CRC4 составляет 11 бит, и здесь она рассчитана на 12 бит. Насколько я понимаю, это означает, что свойства обнаружения ошибок CRC ухудшаются (но я не уверен, сколько).

(Кстати, если кто-нибудь нужен код для CRC4 (или любой другой) и не чувствует себя достаточно опытным, чтобы написать его сам, импульс имеет очень хороший импульс :: Crc функция, которая может вычислить любой КРР)

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

Мой вопрос: есть ли способ исправить кадрирование, не добавляя больше байтов? Мы потратили довольно много времени, сжимая все в двух байтах, и было бы грустно просто выбросить его так. У нас есть запасной бит в поле opcode.

  • основе времени обрамление будет не очень надежным, потому что наше радио-канал любит «выплюнуть» несколько пакетов сразу
  • Может быть, есть какой-то другой метод обнаружения ошибок, который будет работать лучше, чем CRC4?

Это мы должны добавить больше байтов, что было бы лучшим способом сделать это?

  • Мы можем использовать запуск из-кадров байт и байты-начинки (например, как ПОЧАТКИ) (+2 байт, но я не уверен, что делать с поврежденными сообщениями)
  • Мы можем использовать запуск из -frame nibble и расширять CRC до CRC8 (+1 байт)
  • Что-то еще?
+0

Как происходит обмен битами между процессором и устройством? – 4386427

+0

@ 4386427 процессор подключен к радиопередатчику UART; радиоприемник подключен к устройству UART. – Amomum

+0

Есть ли постоянный поток пакетов? – 4386427

ответ

1

Существует улов: рекомендуемая длина сообщения для CRC4 11 бит и здесь вычисляется для 12 бит.

Нет, здесь он рассчитан на 16 бит.

Насколько я понимаю, это означает, что свойства обнаружения ошибок CRC ухудшаются (но я не уверен, сколько).

Рекомендации по CRC, вероятно, относятся к тому, есть ли у вас 100% -ная вероятность найти однобитовую ошибку или нет. Все CRC борются с многобитными ошибками и не обязательно найдут их.

При работе с расчетами надежности CRC UART вам также необходимо взять стартовые и стоповые бит в учетную запись. Бит-ошибки могут также нанести удар, и в этом случае аппаратное обеспечение может помочь или не поможет найти ошибку.

второй байт от одного сообщения и первого байта из следующего сообщения иногда образуют правильное сообщение

Конечно. У вас нет механизма синхронизации, чего вы ожидаете? Это не имеет никакого отношения к CRC.

Мой вопрос: есть ли способ исправить кадрирование, не добавляя больше байтов?

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

Какой метод выбрать, зависит от характера данных и ваших спецификаций. Никто на SO не может рассказать вам, как выглядит ваша спецификация.

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

Неправильно. CRC - это в значительной степени единственный профессиональный алгоритм контрольной суммы. Полиномы выбираются на основе исключенного характера шума - они выбирают полином, который напоминает как можно меньше шума. Однако это в основном представляет академический интерес, поскольку ни один гуру CRC не может знать, как выглядит шум в вашем конкретном приложении.

Альтернативы представляют собой суммы, xor, четность, количество единиц 1 и т. Д. ... все они довольно плохие, вероятные.

Это мы должны добавить больше байтов, что было бы лучшим способом сделать это?

Никто не может ответить на этот вопрос, не зная характера данных.

+1

Просто хотел добавить комментарий к полиномиальной части: некоторые полиномы лучше справляются с пакетными ошибками, чем случайные ошибки и т. Д. Таким образом, есть некоторые шумовые характеристики, которые вы можете приспособить к своему полиномию crc. В этой публикации CMU говорится о выборе полинома во встроенном контексте: http://repository.cmu.edu/cgi/viewcontent.cgi?article=1672&context=isr –

+0

>> «Нет, здесь он рассчитан на 16 бит». Нет, это 12 бит данных и 4 бита CRC. Я использую boost :: crc_basic и вычисляю по частям. >> «У вас нет механизма синхронизации, чего вы ожидаете?» Насколько я знаю (но я не эксперт), основанная на crc синхронизация кадров - это механизм синхронизации, и он используется ..https: //en.wikipedia.org/wiki/CRC-based_framing >> «Никто не может ответить этот вопрос, не зная характера данных ». байт данных может быть любым произвольным байтом. – Amomum

+0

@Amomum На стороне приемника CRC обычно рассчитывается как по данным, так и по FCS. I.e вы XOR весь пакет против полинома и проверьте, равен ли результат 0 или нет. – Lundin

2

Обычный способ сделать то, что вы просите, это «охотиться за кадрированием» при запуске и требовать N последовательных хороших пакетов, прежде чем принимать какие-либо пакеты. Это может быть реализовано с использованием государственной машины с 3-мя состояниями: HUNT, LOF (потеря кадра), SYNC

Это может быть что-то вроде:

#define GOOD_PACKETS_REQUIRED_BEFORE_SYNC 8 
int state = HUNT; 
int good_count = 0; 

Packet GetPacket(void) 
{ 
    unsigned char fb = 0; 
    unsigned char sb = 0; 

    while (1) 
    { 
     if (state == HUNT) 
     { 
      fb = sb; 
      sb = GetNextByteFromUART(); 

      if (IsValidCRC(fb, sb)) 
      { 
       state = LOF; 
       good_count = 1; 
      } 
     } 
     else if (state == LOF) 
     { 
      fb = GetNextByteFromUART(); 
      sb = GetNextByteFromUART(); 

      if (IsValidCRC(fb, sb)) 
      { 
       good_count++; 
       if (good_count >= GOOD_PACKETS_REQUIRED_BEFORE_SYNC) 
       { 
        state = SYNC; 
       } 
      } 
      else 
      { 
       state = HUNT; 
       good_count = 0; 
      } 
     } 
     else if (state == SYNC) 
     { 
      fb = GetNextByteFromUART(); 
      sb = GetNextByteFromUART(); 

      if (IsValidCRC(fb, sb)) 
      { 
       return packet(fb, sb);; 
      } 

      // SYNC lost! Start a new hunt for correct framing 
      state = HUNT; 
      good_count = 0; 
     } 
    } 
} 

Вы можете найти несколько стандартных протоколов связи, которые используют это (или аналогичный), например ATM и E1 (https://en.wikipedia.org/wiki/E-carrier). Существуют разные варианты принципа. Например, вы можете перейти от SYNC к LOF при получении первого плохого пакета (декремент good_count), а затем перейти от LOF к HUNT во втором последовательном плохом пакете. Это сократило бы время, необходимое для переподготовки. Вышеприведенный просто показывает очень простой вариант.

Примечание: в коде реального мира вы, вероятно, не можете принять функцию блокировки, подобную приведенной выше. Вышеприведенный код предоставляется только для описания принципа.

Независимо от того, нужен ли вам CRC или может быть выполнено фиксированное фреймовое слово (например, 0xB), зависит от вашего носителя.

+0

'Пакет GetPacket()' неверен или вы забыли вернуть значение. Используйте правильные прототипы-деклараторы. На самом деле компилятор должен предупредить. – Olaf

+0

@Olaf - это не полная функция (это было бы ужасное осуществление ...) - это просто показать какой-то принцип. Однако, если все структуры и (отсутствующие) функции были реализованы, я не понимаю, почему прототип должен быть неправильным. – 4386427

+0

Для стартера, потому что он возвращает 'int'. Во-вторых, он использует декларатор старого стиля, который является функцией устаревания и сильно устарел. Вы можете прочитать стандарт. – Olaf

0

Если CRC в основном предназначен для паранойи (из комментариев), вы можете отказаться от проверки надежности и времени процессора для кадрирования.

Поскольку в коде операции есть свободный бит, всегда устанавливайте самый старший бит первого байта в ноль. Затем перед передачей, но после вычисления CRC, установите самый старший бит второго байта в один.

Кадр тогда состоит из двух последовательных байтов, где первый старший бит равен нулю, а второй - один. Если два байта не пройдут проверку CRC, установите самый старший бит второго байта на ноль и пересчитайте, чтобы увидеть, был ли пакет перевернут бит перед передачей.

Недостатком является то, что CRC будет рассчитан дважды примерно в половину времени. Кроме того, установка бит для кадрирования может привести к тому, что недопустимые данные будут соответствовать CRC.

Смежные вопросы