2015-06-18 4 views
0

Мне нужно вычислить контрольную сумму CRC для CAN BUS.Вычислить CRC 15 для CAN BUS

Сценарий:

Мой вход выглядит всегда как следующие (где x либо 1 или 0, * Marks несколько раз x, | отмечает раздел и - является изменение способа ввода, lb является Label , tb является TextBox, cb является ComboBox):

  • lb: 0
  • tb: 11x
  • cb: х
  • cb: х
  • lb: 1
  • tb: 4x =>Convert.ToString(8-64/8, 2).PadLeft(4, '0');
  • tb: 8-64x, =>8-64 % 8 == 0
  • tb: 15x =>CRC of above
  • lb: 1
  • lb: 11
  • lb: 1111111
  • lb: 111

который возвращает этот макет:

0|11*x-x|x-1-4*x|64*x|15*x-1|11|1111111|111 

Пример:

00101010101000100100101010100101010(missing 15*x CRC sum)1111111111111 

Эта строка будет обработана следующим расширением строки, так что максимальные 5 равные цифры следуют друг за другом:

public static string Correct4CRC(this string s) 
{ 
    return s.Replace("00000", "000001").Replace("11111", "111110"); 
} 

После этого следующий метод возвращает делитель:

public static BigInteger CreateDivisor(string s) 
{ 
    var i = BigInteger.Parse(s); 
    var d = BigInteger.Pow(i, 15) + BigInteger.Pow(i, 14) + BigInteger.Pow(i, 10) + BigInteger.Pow(i, 8) + BigInteger.Pow(i, 7) + BigInteger.Pow(i, 4) + BigInteger.Pow(i, 3) + 1; 
    return d; 
} 

Единственная проблема, я «ве получил это часть с ^:

public static string CRC(this string s) 
{ 
    var dd = s.Correct4CRC(); 
    var dr = dd.CreateDivisor().ToString(); 
    int drl = dr.Length; 
    var d = dd.Substring(0, drl).CreateDivisor(); 
    var f = d^dr.CreateDivisor(); 
    var p = true; 
    while (p) 
    { 
     d = dd.Substring(0, drl).CreateDivisor(); 
     f = d^dr.CreateDivisor(); 
     p = d > dd.CreateDivisor(); 
    } 
    return f.ToString(); 
} 

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

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

+1

Как "CRC-16" может быть 15 бит? (15x) –

+0

@ Последний бит LastLare зарезервирован и всегда 1 – cramopy

+1

Посмотрев на https://en.wikipedia.org/wiki/CAN_bus#Data_frame, кажется, что сначала вы вычисляете CRC на битах до CRC, то вы добавляете CRC, затем выполняете битовую начинку (замену), затем добавляете два бита ACK и другие биты (конец кадра и IFS). – xanatos

ответ

1

Я думаю, что ваш битстаффинг неправильный (замена 00000 на 000001 и 11111 на 111110), потому что он не обрабатывает замены лавины ... 0000011110000, который становится 0000011111000001.

Здесь http://blog.qartis.com/can-bus/ есть, к примеру. Затем страница привязана к http://ghsi.de/CRC/index.php?Polynom=1100010110011001&Message=2AA80, которая генерирует некоторый код C для вычисления CRC-15.

// 0000011110000 becomes 0000011111000001 
public static string BitStuff(string bits) 
{ 
    StringBuilder sb = null; 

    char last = ' '; 
    int count = 0; 

    for (int i = 0; i < bits.Length; i++) 
    { 
     char ch = bits[i]; 

     if (ch == last) 
     { 
      count++; 

      if (count == 5) 
      { 
       if (sb == null) 
       { 
        // The maximum length is equal to the length of bits 
        // plus 1 for length 5, 2 for length 9, 3 for length 13... 
        // This because the maximum expanion is for 
        // 00000111100001111... or 11111000011110000... 
        sb = new StringBuilder(bits.Length + (bits.Length - 1)/4); 
        sb.Append(bits, 0, i); 
       } 

       sb.Append(ch); 
       last = ch == '0' ? '1' : '0'; 
       sb.Append(last); 
       count = 1; 

       continue; 
      } 
     } 
     else 
     { 
      last = ch; 
      count = 1; 
     } 

     if (sb != null) 
     { 
      sb.Append(ch); 
     } 
    } 

    return sb != null ? sb.ToString() : bits; 
} 

// Taken from http://ghsi.de/CRC/index.php?Polynom=1100010110011001&Message=2AA80 
public static string Crc15(string bits) 
{ 
    var res = new char[15]; // CRC Result 
    var crc = new bool[15]; 

    for (int i = 0; i < bits.Length; i++) 
    { 
     bool doInvert = (bits[i] == '1')^crc[14];   // XOR required? 

     crc[14] = crc[13]^doInvert; 
     crc[13] = crc[12]; 
     crc[12] = crc[11]; 
     crc[11] = crc[10]; 
     crc[10] = crc[9]^doInvert; 
     crc[9] = crc[8]; 
     crc[8] = crc[7]^doInvert; 
     crc[7] = crc[6]^doInvert; 
     crc[6] = crc[5]; 
     crc[5] = crc[4]; 
     crc[4] = crc[3]^doInvert; 
     crc[3] = crc[2]^doInvert; 
     crc[2] = crc[1]; 
     crc[1] = crc[0]; 
     crc[0] = doInvert; 
    } 

    // Convert binary to ASCII 
    for (int i = 0; i < 15; i++) 
    { 
     res[14 - i] = crc[i] ? '1' : '0'; 
    } 

    return new string(res); 
} 

, а затем:

string bits = "0101010101010000000"; // Example data 
string crc = Crc15(bits); 

bits = bits + crc; 
bits = BitStuff(bits); 

bits += '1'; // CRC delimiter 

bits += 'x'; // ACK slot TODO 

bits += '1'; // ACK delimiter 
bits += "1111111"; // EOF 

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

+0

спасибо человеку! : D работает как шарм ... – cramopy

+0

@cramopy Было бы лучше сделать это без распаковки байтов в битах, но я думаю, что это было очень очень очень сложно ... Вставка бит между другими битами сложна! Возможно, Crc немного оптимизирован ... как есть поддержка 'var crc = new bool [15]', но код можно изменить, чтобы не использовать его. – xanatos

+0

Он работает очень хорошо, потому что мне это нужно. Еще раз спасибо! – cramopy

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

  • Нет связанных вопросов^_^