|
|
  |
Алгоритм CRC16 |
|
|
|
Apr 19 2010, 14:59
|

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

|
Цитата(vallav @ Apr 19 2010, 15:52)  ...Это то, что пропустил контроль побайтовой четности. А где в блоке байты и где в байтах ошибки - не важно. Конкретно - искажены два байта, по два бита в каждом, на одних и тех же позициях - это то, что прямая сумма пропускает. А CRC может пропустить не эти, а другие, удовлетворяющие исходному условию. Ну, что Вы так разошлись? Вашу бы энергию - да в мирных целях... Контроль чётности в Вашем примере - слабое утешение, раз помеха у Вас столь продолжительная, что действует в течении времени передачи двух байтов (помеха и на биты четности может повлиять). Поэтому суммирование может пропустить и блок, в котором информация искажена всего в двух битах. Конечно же, CRC - не панацея, и по её анализу тоже может принято неверное решение о целостности пакета, но на "малых" длинах пакетов, имхо, CRC всяко лучше простой суммы.
|
|
|
|
|
Apr 19 2010, 15:04
|
Частый гость
 
Группа: Участник
Сообщений: 197
Регистрация: 8-04-05
Пользователь №: 3 977

|
Цитата(defunct @ Apr 19 2010, 18:43)  Чтобы Вам не быть голословным, можете привести конкретный пример, - когда CRC16 пропускает искажение любых 4-х битов сообщения? А мы потом пообсуждаем. Дык нужно знать, какое имено CRC вы считаете непрорускающим четырехкратные ошибки. Чтобы потом Вы не заявляли, мол - полином неудачный...
|
|
|
|
|
Apr 19 2010, 17:48
|

embarrassed systems engineer
    
Группа: Свой
Сообщений: 1 083
Регистрация: 24-10-05
Из: Осокорки
Пользователь №: 10 038

|
Цитата(vallav @ Apr 19 2010, 15:52)  http://rsdn.ru/article/files/classes/SelfCheck/crcguide.pdfИ что именно Вы там обнаружили? Или Вы туда даже не заглядывали... Признаюсь, я много куда не заглядывал. Если понимать общие принципы то это часто можно себе позволить - никуда не заглядывать. Например, сейчас "не заглядывая" за полчаса была накалякана приаттаченная программка для проверки обнаружения двойных ошибок CRC-16-CCITT в 2048-битном блоке. После запуска на i7-860 пришлось ее пооптимизировать - перейти на табличный метод, а то думала слишком уж долго - и тоже никуда не заглядывая. Программка не шедевр, я бы даже сказал что немного чувствую себя идиотом - вроде как проверил 2x2=4  . Но таки практически убедился - любое число из одной/двух единиц (полиномы вида X^n + X^m и X^n) в пределах 2048-битного блока на порождающий полином CCITT вида 0x1021 таки не делится. Более того - запустил и на 4096-битном блоке (199 секунд перебирала), также все OK - не делится! Вот сама программка - не очень оптимальная, но написанная по-быстрому и честно "никуда не заглядывая ":), поэтому ногами сильно уж не пинайте  CODE #include <windows.h> #include <stdio.h> #define CRC_POLY 0x1021 #define CRC_WLEN 256 // number of 16bit words within block USHORT pack[CRC_WLEN]; USHORT ctab[256]; __inline USHORT crc_update_simple(USHORT crc, USHORT data) { ULONG i; crc = crc ^ (data << 8); for (i=0; i<8; i++) { if (crc & 0x8000) { crc = (crc << 1)^CRC_POLY; } else { crc <<= 1; } } crc = crc ^ (data & 0xFF00); for (i=0; i<8; i++) { if (crc & 0x8000) { crc = (crc << 1)^CRC_POLY; } else { crc <<= 1; } } return crc; } __inline USHORT crc_update_tab(USHORT crc, USHORT data) { crc = crc ^ (data << 8); crc = ctab[crc >> 8] ^ (crc << 8); crc = crc ^ (data & 0xFF00); crc = ctab[crc >> 8] ^ (crc << 8); return crc; } void crc_init(void) { ULONG i, j; for(i=0; i<256; i++) { USHORT t; t = (USHORT)(i << 8); for (j=0; j<8; j++) { if (t & 0x8000) { t = (t << 1)^CRC_POLY; } else { t <<= 1; } } ctab[i] = t; } } __inline USHORT crc_calc_simple(USHORT *buf, ULONG len) { USHORT crc; crc = 0; if (len) { do { crc = crc_update_simple(crc, *buf++); } while(--len); } return crc; } __inline USHORT crc_calc_tab(USHORT *buf, ULONG len) { USHORT crc; crc = 0; if (len) { do { crc = crc_update_tab(crc, *buf++); } while(--len); } return crc; } void main(void) { ULONG start; USHORT crc, *p1, *p2; ULONG i1, i2; crc_init(); printf("\r\nChecking %d-bit block", CRC_WLEN*16); start = GetTickCount(); memset(pack, 0, sizeof(pack)); for(p1 = pack; p1 < &pack[CRC_WLEN]  { printf("\r\n%d", p1-pack); for(i1=0; i1<16; i1++) { for(p2 = pack; p2 < &pack[CRC_WLEN]; p2++) { for(i2=0; i2<16; i2++) { *p1 = (1<<i1); *p2 |= (1<<i2); // // crc = crc_calc_simple(pack, CRC_WLEN); // crc = crc_calc_tab(pack, CRC_WLEN); if (crc == 0) { printf("\r\nCRC fail: %d, %d", (p1-pack)*16 + i1, (p2-pack)*16 + i2); } *p2 &= ~(1<<i2); } } } *p1++ = 0; } start = GetTickCount() - start; printf("\r\n%d ms elapsed\r\n", start); } Upd: если верить статье на вики, то CRC-16 CCITT обеспечивает обнаружение всех одиночных, двойных, тройных и нечетных (я так понял что нечетное число битов искажается) в блоке до 4095 БАЙТ (32 с лишним тысяч бит). Увы, счетверенные ошибки обнаруживатся не все. Upd2: Упомянутое Вами руководство Вильямса - хорошее, признаюсь - реально я когда-то давно (лет 10 назад, еще и русского перевода не было) изучал по нему программные реализации CRC.
|
|
|
|
|
Apr 20 2010, 04:56
|
Частый гость
 
Группа: Участник
Сообщений: 197
Регистрация: 8-04-05
Пользователь №: 3 977

|
Цитата(VslavX @ Apr 19 2010, 22:03)  Признаюсь, я много куда не заглядывал. То есть, других Вы посылаете читать по ссылкам, даже не заглядывая, куда именно посылаете? Цитата(VslavX @ Apr 19 2010, 22:03)  Upd: если верить статье на вики, то CRC-16 CCITT обеспечивает обнаружение всех одиночных, двойных, тройных и нечетных (я так понял что нечетное число битов искажается) в блоке до 4095 БАЙТ (32 с лишним тысяч бит). Увы, счетверенные ошибки обнаруживатся не все. Upd2: Упомянутое Вами руководство Вильямса - хорошее, признаюсь - реально я когда-то давно (лет 10 назад, еще и русского перевода не было) изучал по нему программные реализации CRC. Дык это понятно, что одиночные, двойные и все нечетные ошибки CRC ловит. Но это все поймает проверка байтов на четность. Сравнивать с прямой суммой CRC нужно на предмет обнаружения четверных ошибок по две в байте. То, что проверка байтов на четность пропускает. Я за 10 минут программы писать не умею, так что займет у меня это несколько дней. Имеется в виду китайский метод - перебором посчитать сколько четверных ошибок указанного типа пропустит CRC в блоке 256 байт. И сколько прямая сумма.
|
|
|
|
|
Apr 25 2010, 09:33
|
Частый гость
 
Группа: Участник
Сообщений: 197
Регистрация: 8-04-05
Пользователь №: 3 977

|
Посчитал. Надеюсь, если и ошибся, то не сильно. Получилось - в болке из 258 байт, четверных ошибок, пропущенных побайтным контролем на четность в случае контроля по CRC с полиномом x^16+x^15+x^2+x^0 будет 6292 штук. Прямая сумма хуже, она пропустит 43344 штуки. Программа, по которой считалось, приложена. Вместе они не пропустят ни одной четверной ошибки. Но если делать контрольное слово 32 бита, то лучше две разных прямых суммы - они тоже не пропустят ни одной четверной ошибки. Так что высказывания - прямая сумма отстой по сравнению с CRC - мало чем обоснованы.
serd.txt ( 833 байт )
Кол-во скачиваний: 150поменяйте расширение на .cpp
Сообщение отредактировал vallav - Apr 25 2010, 09:34
|
|
|
|
|
Apr 25 2010, 13:20
|
Частый гость
 
Группа: Участник
Сообщений: 197
Регистрация: 8-04-05
Пользователь №: 3 977

|
Цитата(ASN @ Apr 25 2010, 15:46)  vallav Прямая сумма хуже CRC16 в Вашем случае более чем в 6 раз. Что и требовалось доказать. Если сумма 32-х битная (или две по 16), то это уже CRC32. Реализация контроля по CRC32 табличным методом на 8-ми битной ЭВМ проще. Что и требовалось доказать. Ну да, прямая сумма пропустит такие ошибки в 6 раз вероятнее. Но такие ошибки ( четверные по две в байте ) сами по себе для приведенного примера довольно редкие. Вероятность где то ~ 10^-9 ( одна на миллиард пакетов ). Намного вероятнее пачка ошибок от короткой мощной импульсной помехи. А в этом случае прямая сумма вроде лучше ( если пачка короче 17 бит, прямая сумма ловит все ). CRC из за перепутывания бит часть пропустит. А вот откуда сведения, что на 8-ми битной ЭВМ реализация 32 битной СRC проще? Код существенно длиннее, время выполнения несколько больше. И Вы уверены, что есть 32 битные CRC не пропусакающие ни одной такой ошибки? Две разные прямые суммы - точно не пропустят. Я не про то, что CRC никуда не годится, я про то, что прямая сумма вполне годится а может быть в некоторых случаях лучше CRC.
|
|
|
|
|
  |
3 чел. читают эту тему (гостей: 3, скрытых пользователей: 0)
Пользователей: 0
|
|
|