|
crc 8, Нужна помощь |
|
|
|
Jan 28 2011, 16:11
|
Участник

Группа: Участник
Сообщений: 27
Регистрация: 24-11-10
Пользователь №: 61 153

|
Все добрый день! необходимо написать программу, простенькую, для расчета контрольной суммы по алгоритму crc8.Собственно говоря, я в С++ только только начал разбираться  , но вот появилась такая задача и можно сказать зашился. Хочу, что бы просто в командной строке вводишь данные и сразу выдает ответ. Данные hex. Алгоритм программы таков public class CRC8 { private static int getCrc(int oneByte, int crc){ int i = oneByte ^ crc; crc = 0; if((i & 0x01)>0) crc ^= 0x5e; if((i & 0x02)>0) crc ^= 0xbc; if((i & 0x04)>0) crc ^= 0x61; if((i & 0x08)>0) crc ^= 0xc2; if((i & 0x10)>0) crc ^= 0x9d; if((i & 0x20)>0) crc ^= 0x23; if((i & 0x40)>0) crc ^= 0x46; if((i & 0x80)>0) crc ^= 0x8c; return crc; } byte[] bytes = {(byte)0x31,(byte)0xFF,(byte)0x06}; System.out.printf("crc=%X\n",CRC8.getCrc4Array(bytes)); Сразу скажу, что возможно он отличается от привычных всем, ибо этот алгоритм разработан производителями переферийнного устройства и, подсчитывая crc в ручную, у меня не совпадало значение моего crc со значением производителя  . Я писал им support  , но они отказываются мне помогать.
|
|
|
|
|
Jan 28 2011, 19:23
|

Гуру
     
Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244

|
QUOTE (nokepp @ Jan 28 2011, 19:11)  Сразу скажу, что возможно он отличается от привычных всем, ибо этот алгоритм разработан производителями переферийнного устройства и, подсчитывая crc в ручную О! Это совершенно секретный  , как уже заметил Сергей полином X^8+X^5+X^4+X^0 имении Dallas. Считается оптимальным для коротких последовательностей. Считается, как и любой CRC массой способов. Хоть по таблице: CODE const BYTE crc8_8540_tbl[]= { 0, 94, 188, 226, 97, 63, 221, 131, 194, 156, 126, 32, 163, 253, 31, 65, 157, 195, 33, 127, 252, 162, 64, 30, 95, 1, 227, 189, 62, 96, 130, 220, 35, 125, 159, 193, 66, 28, 254, 160, 225, 191, 93, 3, 128, 222, 60, 98, 190, 224, 2, 92, 223, 129, 99, 61, 124, 34, 192, 158, 29, 67, 161, 255, 70, 24, 250, 164, 39, 121, 155, 197, 132, 218, 56, 102, 229, 187, 89, 7, 219, 133, 103, 57, 186, 228, 6, 88, 25, 71, 165, 251, 120, 38, 196, 154, 101, 59, 217, 135, 4, 90, 184, 230, 167, 249, 27, 69, 198, 152, 122, 36, 248, 166, 68, 26, 153, 199, 37, 123, 58, 100, 134, 216, 91, 5, 231, 185, 140, 210, 48, 110, 237, 179, 81, 15, 78, 16, 242, 172, 47, 113, 147, 205, 17, 79, 173, 243, 112, 46, 204, 146, 211, 141, 111, 49, 178, 236, 14, 80, 175, 241, 19, 77, 206, 144, 114, 44, 109, 51, 209, 143, 12, 82, 176, 238, 50, 108, 142, 208, 83, 13, 239, 177, 240, 174, 76, 18, 145, 207, 45, 115, 202, 148, 118, 40, 171, 245, 23, 73, 8, 86, 180, 234, 105, 55, 213, 139, 87, 9, 235, 181, 54, 104, 138, 212, 149, 203, 41, 119, 244, 170, 72, 22, 233, 183, 85, 11, 136, 214, 52, 106, 43, 117, 151, 201, 74, 20, 246, 168, 116, 42, 200, 150, 21, 75, 169, 247, 182, 232, 10, 84, 215, 137, 107, 53 }; хоть другими отличными от Вашего софтовыми способами: CODE #define CRC8INIT 0x00 #define CRC8POLY 0x18 // X^8+X^5+X^4+X^0 // 0x18 = ( 0x130 >> 1 ) & 0x7F bint crc8_8540( BYTE *data_in, bint bytes ) { BYTE crc = CRC8INIT; bint bit_cnt; register BYTE data; register BYTE feedback_bit;
while( bytes-- ) { data = *data_in++;
for( bit_cnt=8; bit_cnt; bit_cnt-- ) { feedback_bit = (data^crc) & 0x01; crc >>= 1; data >>= 1; if( feedback_bit ) crc ^= ((CRC8POLY >> 1)|0x80); } } return( crc ); } хоть в железе: CODE //--------------------------------------------------------------------------- // Verilog module containing a synthesizable Dallas CRC8 function // * Polynomial: (8 5 4 0) // * Data width: 8 // * CRC width : 8 // * Mirror //--------------------------------------------------------------------------- module CRC8_8540;
function [7:0] nextCRC;
input [7:0] Data; input [7:0] CRC;
reg [7:0] D; reg [7:0] C; reg [7:0] xCRC;
begin
D = Data; C = CRC;
// Mirror DATA and final CRC xCRC[7] = D[1]^D[3]^D[4]^D[7]^C[7]^C[4]^C[3]^C[1]; xCRC[6] = D[0]^D[2]^D[3]^D[6]^C[6]^C[3]^C[2]^C[0]; xCRC[5] = D[1]^D[2]^D[5]^C[5]^C[2]^C[1]; xCRC[4] = D[0]^D[1]^D[4]^C[4]^C[1]^C[0]; xCRC[3] = D[0]^D[1]^D[4]^D[7]^C[7]^C[4]^C[1]^C[0]; xCRC[2] = D[0]^D[1]^D[4]^D[6]^D[7]^C[7]^C[6]^C[4]^C[1]^C[0]; xCRC[1] = D[0]^D[3]^D[5]^D[6]^C[6]^C[5]^C[3]^C[0]; xCRC[0] = D[2]^D[4]^D[5]^C[5]^C[4]^C[2];
nextCRC = xCRC;
end
endfunction
endmodule Судя по режущим глаз if((i & 0x01)>0) напахать Вы могли в Вашей первой программе где угодно, а не в отцитированных Вами кусочках.
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
Jan 31 2011, 10:25
|
Участник

Группа: Участник
Сообщений: 27
Регистрация: 24-11-10
Пользователь №: 61 153

|
В общем вот что у меня получилось:
#include <conio.h> #include <stdlib.h> #include <stdio.h> #include <iostream>
unsigned char crc8(unsigned char data, unsigned int crc) { unsigned char i=data^crc; crc=0; if(i & 0x01) crc^=0x5e; if(i & 0x02) crc^=0xbc; if(i & 0x04) crc^=0x61; if(i & 0x08) crc^=0xc2; if(i & 0x10) crc^=0x9d; if(i & 0x20) crc^=0x23; if(i & 0x40) crc^=0x46; if(i & 0x80) crc^=0x8c; return crc; }
void main (void) { unsigned char a,c=0x00,l=1; a=crc8(c,l); printf("a=0x%x",a); getch(); }
В данном примере считает для 0x01.(т.е. l=0x01). Но проблема в том, что считает для значений только до 9. ВСе что выше(10,11,...), выдает уже неверные значения.Мне нужно расширить значение до максимума. Ну например "31FF09". Пока не врублюсь как это сделать.. И еще интересует как сделать чтобы значение можно было вводить в окно консоля...пробовал через using namespace std;но короче он ругается на unsigned char;(прошу прощения за непроффесиональный слэнг)
|
|
|
|
|
Jan 31 2011, 15:48
|
Участник

Группа: Участник
Сообщений: 27
Регистрация: 24-11-10
Пользователь №: 61 153

|
Цитата(DpInRock @ Jan 31 2011, 17:36)  Я бы на вашем месте попытался бы разобраться что такое CRC8 вообще. Ибо вы не имеете об этом ни малейшего представления. Т.е. пишите программу, которая слышала звон. Вот рассмотрите данные вам примеры у поинтересуйтесь, чего это оне все имеют некий счетчик байт... И все работают в каком-то цикле... Зачем? Вот в википедии можно подчерпнуть как знания, так и исходные коды на всех языках мира. Сомневаюсь, что на всех языках мира. Я увидел только на СИ...В принципе, как я считаю, алгоритм исчесления я понял. Всю информацию предстваляем как огромное число в бинарном ввиде и делим столбиком, как в школе на используемый полином,ну т.е. не на полином, а на тоже бинарное число, интерпретированное как полином..Остаток от деления и есть искомое crc8. Честно вам скажу, я это делал на бумаге, с небольшими числами. Но когда вижу, такой алгоритм в СИ, почему -то не могу разобраться, что к чему. Я только начал изучать языки и понимаю, что взялся за слишком серьезную задачу для своего уровня программирования. Поэтому прошу помочь мне для ее решения. Ведь чувствую, что близок к завершению
|
|
|
|
|
Jan 31 2011, 16:18
|

Гуру
     
Группа: Свой
Сообщений: 2 399
Регистрация: 10-05-06
Из: г. Новочеркасск
Пользователь №: 16 954

|
Цитата(nokepp @ Jan 31 2011, 18:48)  ... и делим столбиком... на полином...Остаток от деления и есть искомое crc8. Честно вам скажу, я это делал на бумаге, с небольшими числами. Но когда вижу, такой алгоритм в СИ, почему -то не могу разобраться, что к чему. Вы, наверное, сравниваете "честный" остаток с полученным CRC и удивляетесь, что не совпадают значения? Почитайте что-нибудь по теории вычисления CRC... При вычислении CRC используется двоичная арифметика без учета переносов - тогда сложение/вычитание заменяется операцией "исключающее ИЛИ".
|
|
|
|
|
Jan 31 2011, 20:10
|
Местный
  
Группа: Свой
Сообщений: 443
Регистрация: 22-07-06
Из: Украина, г. Харьков
Пользователь №: 19 006

|
Цитата(nokepp @ Jan 31 2011, 12:25)  ... unsigned char crc8(unsigned char data, unsigned int crc) { ... }
void main (void) { unsigned char a,c=0x00,l=1; a=crc8(c,l); printf("a=0x%x",a); getch(); } Насколько я вижу, при вызове функции перепутаны местами данные и crc. Понятнее было бы переменную для crc назвать crc (Капитан очевидность  ). Я бы написал так: Код unsigned char crc; unsigned char data = 1; // ну это чтоб от вас не отличаться сильно
crc = crc8(data, crc); printf("crc=0x%x",crc); Цитата Ну например "31FF09". Пока не врублюсь как это сделать. Приведенное вами значение это 3 байта. Ваша же функция считает crcдля одного байта. Когда нужно посчитать crc для пакета в несколько байт делают так: Допустим нужные нам данные, скажем 8 байт, сложены в unsigned char buf[8]. тогда Код unsigned char crc = 0; // Начальное значение. В общем случае может быть и не 0, надо смотреть спецификацию. for(i=0;i<8;i++) crc = crc8(buf[i], crc); printf("crc пакета =0x%x",crc); P.S. ну и зачем при обьявлении функции crc сделан unsigned int тоже непонятно. unsigned char надо.
|
|
|
|
|
Feb 1 2011, 09:21
|

Универсальный солдатик
     
Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362

|
Мне попадался полином x^8 + x^2 + x + 1 (CRC-8-Dallas/Maxim) Для него я написал программу, но потом не использовал, так что в работоспособности не поручусь на 100%. Код /* *********************************************************************** * Расчет циклического избыточного кода CRC для массива сообщения * Используется полином x^8 + x^2 + x + 1 (CRC-8-Dallas/Maxim) * Задается указатель на начало рассчитываемых байтов в массиве, * количество байтов, участвующих в расчете (ровно) * начальный код CRC (если считается не с начала массива), * Для ускорения расчета используется таблица ***********************************************************************/ char calcCRC(char *Ptr, char Num, char CRC) { const char CrcTable[256] = { 0x00, 0x07, 0x0e, 0x09, 0x1c, 0x1b, 0x12, 0x15, // 00 0x38, 0x3f, 0x36, 0x31, 0x24, 0x23, 0x2a, 0x2d, // 08 0x70, 0x77, 0x7E, 0x79, 0x6C, 0x6B, 0x62, 0x65, // 10 0x48, 0x4F, 0x46, 0x41, 0x54, 0x53, 0x5A, 0x5D, // 18 0xE0, 0xE7, 0xEE, 0xE9, 0xFC, 0xFB, 0xF2, 0xF5, // 20 0xD8, 0xDF, 0xD6, 0xD1, 0xC4, 0xC3, 0xCA, 0xCD, // 28 0x90, 0x97, 0x9E, 0x99, 0x8C, 0x8B, 0x82, 0x85, // 30 0xA8, 0xAF, 0xA6, 0xA1, 0xB4, 0xB3, 0xBA, 0xBD, // 38 0xC7, 0xC0, 0xC9, 0xCE, 0xDB, 0xDC, 0xD5, 0xD2, // 40 0xFF, 0xF8, 0xF1, 0xF6, 0xE3, 0xE4, 0xED, 0xEA, // 48 0xB7, 0xB0, 0xB9, 0xBE, 0xAB, 0xAC, 0xA5, 0xA2, // 50 0x8F, 0x88, 0x81, 0x86, 0x93, 0x94, 0x9D, 0x9A, // 58 0x27, 0x20, 0x29, 0x2E, 0x3B, 0x3C, 0x35, 0x32, // 60 0x1F, 0x18, 0x11, 0x16, 0x03, 0x04, 0x0D, 0x0A, // 68 0x57, 0x50, 0x59, 0x5E, 0x4B, 0x4C, 0x45, 0x42, // 70 0x6F, 0x68, 0x61, 0x66, 0x73, 0x74, 0x7D, 0x7A, // 78 0x89, 0x8E, 0x87, 0x80, 0x95, 0x92, 0x9B, 0x9C, // 80 0xB1, 0xB6, 0xBF, 0xB8, 0xAD, 0xAA, 0xA3, 0xA4, // 88 0xF9, 0xFE, 0xF7, 0xF0, 0xE5, 0xE2, 0xEB, 0xEC, // 90 0xC1, 0xC6, 0xCF, 0xC8, 0xDD, 0xDA, 0xD3, 0xD4, // 98 0x69, 0x6E, 0x67, 0x60, 0x75, 0x72, 0x7B, 0x7C, // a0 0x51, 0x56, 0x5F, 0x58, 0x4D, 0x4A, 0x43, 0x44, // a8 0x19, 0x1E, 0x17, 0x10, 0x05, 0x02, 0x0B, 0x0C, // b0 0x21, 0x26, 0x2F, 0x28, 0x3D, 0x3A, 0x33, 0x34, // b8 0x4E, 0x49, 0x40, 0x47, 0x52, 0x55, 0x5C, 0x5B, // c0 0x76, 0x71, 0x78, 0x7F, 0x6A, 0x6D, 0x64, 0x63, // c8 0x3E, 0x39, 0x30, 0x37, 0x22, 0x25, 0x2C, 0x2B, // d0 0x06, 0x01, 0x08, 0x0F, 0x1A, 0x1D, 0x14, 0x13, // d8 0xAE, 0xA9, 0xA0, 0xA7, 0xB2, 0xB5, 0xBC, 0xBB, // e0 0x96, 0x91, 0x98, 0x9F, 0x8A, 0x8D, 0x84, 0x83, // e8 0xDE, 0xD9, 0xD0, 0xD7, 0xC2, 0xC5, 0xCC, 0xCB, // f0 0xE6, 0xE1, 0xE8, 0xEF, 0xFA, 0xFD, 0xF4, 0xF3 // f8 }; do CRC = CrcTable[CRC ^ *Ptr++]; while (--Num); return CRC; }
|
|
|
|
|
Feb 1 2011, 17:23
|
Участник

Группа: Участник
Сообщений: 22
Регистрация: 1-02-11
Из: Днепропетровск
Пользователь №: 62 622

|
Цитата(nokepp @ Jan 31 2011, 17:48)  Сомневаюсь, что на всех языках мира. Я увидел только на СИ...В принципе, как я считаю, алгоритм исчесления я понял. Всю информацию предстваляем как огромное число в бинарном ввиде и делим столбиком, как в школе на используемый полином,ну т.е. не на полином, а на тоже бинарное число, интерпретированное как полином..Остаток от деления и есть искомое crc8. Честно вам скажу, я это делал на бумаге, с небольшими числами. Но когда вижу, такой алгоритм в СИ, почему -то не могу разобраться, что к чему. Я только начал изучать языки и понимаю, что взялся за слишком серьезную задачу для своего уровня программирования. Поэтому прошу помочь мне для ее решения. Ведь чувствую, что близок к завершению Вы не представляете, насколько усложнили себе понимание подсчета CRC ! Посмотрите, как это организуется аппаратно, в виде сдвигового регистра с обратными связями - будете смеяться, насколько все просто ! А для "долбания" указанного вами алгоритма предлагаю взять "нормальные" - из app/notes - и проверить их на ваших тестовых последовательностях - в них могли быть элементарно ошибки, а вы будете долбить головой стену ! ps - имеет значение порядок следования байтов, порядок "сдвига" битов, расположение тетрад в байте ! сделайте сперва работающую правильно модель, а затем бодайтесь с этим конкретным алгоритмом.
|
|
|
|
|
Feb 7 2011, 15:53
|
Участник

Группа: Участник
Сообщений: 27
Регистрация: 24-11-10
Пользователь №: 61 153

|
Цитата(Artem_Petrik @ Jan 31 2011, 23:10)  Приведенное вами значение это 3 байта. Ваша же функция считает crcдля одного байта. Когда нужно посчитать crc для пакета в несколько байт делают так: Допустим нужные нам данные, скажем 8 байт, сложены в unsigned char buf[8]. тогда Код unsigned char crc = 0; // Начальное значение. В общем случае может быть и не 0, надо смотреть спецификацию. for(i=0;i<8;i++) crc = crc8(buf[i], crc); printf("crc пакета =0x%x",crc); P.S. ну и зачем при обьявлении функции crc сделан unsigned int тоже непонятно. unsigned char надо. Что-то у меня с данными размеров выше одного байта ничего не получается. Еще компилятор такой дурацкий. Как я понял buf[i] это массив ... i-кол-во байт данных. значит включается счетчик от одного до 8 байт и с каждым прибавлением 1 ,выполняется присваивание. Но не ясно, где же блит данные=( и еще не ясно, как же задействовать команду cin для ввода пакета данных. или для таких задач необходимо задействовать что-то другое?
|
|
|
|
|
Feb 7 2011, 16:03
|
Участник

Группа: Участник
Сообщений: 27
Регистрация: 24-11-10
Пользователь №: 61 153

|
Цитата(Палыч @ Feb 7 2011, 19:01)  Вроде, ясно написано ах!!!не угледел..но все равно например переменной buf[i] я присваиваю значение в 3 байта...и выскакивают какие-то ошибки. ТОчнее мой компилятор, считает по последнему рабочему коду(
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|