Почему вычисленная контрольная сумма не совпадает с BCC, отправленным через последовательный порт? - PullRequest
1 голос
/ 09 октября 2009

У меня есть небольшое приложение, написанное на C #, которое прослушивает SerialPort для получения информации. Информация приходит как: STX + data + ETX + BCC. Затем мы вычисляем BCC пакета передачи и сравниваем. Функция:

private bool ConsistencyCheck(byte[] buffer)
{
    byte expected = buffer[buffer.Length - 1];
    byte actual = 0x00;

    for (int i = 1; i < buffer.Length - 1; i++)
    {
        actual ^= buffer[i];
    }

    if ((expected & 0xFF) != (actual & 0xFF))
    {
        if (AppTools.Logger.IsDebugEnabled)
        {
            AppTools.Logger.Warn(String.Format("ConsistencyCheck failed: Expected: #{0} Got: #{1}", expected, actual));
        }
    }

    return (expected & 0xFF) == (actual & 0xFF);
}

И, похоже, работает более или менее. Он точно не включает STX или BCC и точно включает ETX в свои расчеты. Кажется, это работает очень большой процент времени, однако у нас есть как минимум две машины, на которых мы работаем, обе из которых являются 64-разрядными Windows 2008, в которых вычисление BCC НИКОГДА не складывается. Выгрузка из последнего журнала, который у меня был в одном байте 20, была отправлена, и я вычислил 16, а тот, в котором было отправлено 11, и я вычислил 27.

Я абсолютно озадачен тем, что здесь происходит. Может быть, мне не хватает 64-битной или Windows 2008 "ошибки"? Любая помощь или даже дикие идеи будут оценены.

EDIT:

Вот код, который читает данные в:

private void port_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
    // Retrieve number of bytes in the buffer
    int bytes = serialPort.BytesToRead;

    // Create a byte array to hold the awaiting data
    byte[] received = new byte[bytes];

    //read the data and store it
    serialPort.Read(received, 0, bytes);

    DataReceived(received);
}

И функция DataReceived() берет эту строку и добавляет ее к глобальному объекту StringBuilder. Затем он остается строителем строк, пока не будет передан этим различным функциям, и в этот момент для него вызывается .ToString().

EDIT2: изменен код для отображения моих измененных подпрограмм, которые работают с байтами / байтовыми массивами, а не со строками.

РЕДАКТИРОВАТЬ3: Я до сих пор не понял этого, и я получил больше тестовых данных, которые имеют совершенно противоречивые результаты (сумма, которую я вычеркиваю из контрольной суммы отправки, меняется каждый раз без шаблона). Такое ощущение, что я просто неправильно вычисляю контрольную сумму, но я не знаю как.

Ответы [ 3 ]

2 голосов
/ 09 октября 2009

Буфер определяется как строка. Хотя я подозреваю, что данные, которые вы передаете, являются байтами. Я бы порекомендовал использовать байтовые массивы (даже если вы отправляете ascii / utf / любую кодировку). Затем, после того как контрольная сумма верна, преобразуйте данные в строку

1 голос
/ 20 апреля 2011

вычисление BCC не является стандартным, но «определяется пользователем». мы программируем интерфейсы для наших клиентов и много раз находили разные алгоритмы, в том числе sum, xor, masking, разделяя stx, etx или оба, или разделяя все известные байты. например, структура пакета представляет собой «stx, машинный код, код команды, данные, ..., данные, etx, bcc», а исчисление bcc (определяется пользователем!) как «двоичная сумма всех байтов от кода команды до последние данные включительно, и все замаскировано с 0xCD ". То есть мы должны сначала добавить все неизвестные байты (нет смысла добавлять stx, etx или машинный код, если эти байты не совпадают, кадр все равно отбрасывается! Их значение проверяется при получении, чтобы убедитесь, что кадр начинается, заканчивается правильно, и он адресован принимающей машине, и в этом случае мы должны скопировать только байты, которые могут измениться в кадре, это уменьшит время, так как во многих случаях мы работаем с 4 или 8-битные медленные микроконтроллеры, и осторожно, это суммирование байтов, а не их ксерокса, это был просто пример, другой клиент хочет чего-то другого), и, во-вторых, после того, как у нас есть сумма (которая может быть 16 бит, если не обрезается во время добавления), мы маскируем его (побитовое И) ключом (в этом примере 0xCD). Такие вещи часто используются для всех видов закрытых систем, таких как банкоматы, например (для подключения последовательной клавиатуры к банкомату) в целях защиты и т. Д., Помимо шифрования и других вещей. Итак, вам действительно нужно проверить (читай «крэк»), как ваши две машины вычисляют свои (нестандартные) BCC.

0 голосов
/ 10 октября 2009

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

port.DiscardNull = false;

Кроме того, проверьте тип байта, поступающего на последовательный порт, и принимайте только данные:

private void port_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
    if (e.EventType == SerialData.Chars)
    {
        // Your existing code
    }
}
...