|
|
  |
Алгоритм CRC16 |
|
|
|
Apr 10 2010, 07:39
|

Частый гость
 
Группа: Свой
Сообщений: 156
Регистрация: 10-03-10
Из: Уфа
Пользователь №: 55 882

|
Устройство на sam7x должно обмениваться по uart пакетами длинной 76 байт + 2 байта CRC16 с программой на компьютере. Исходника программы компа нет, но есть исходник (в icc) предыдущей версии рабочего устройства (правильно рассчитываеющего CRC и успешно обменивающегося с программой), из которого был взят фрагмент рассчёта CRC. По какой то причине CRC рассчитывается неверно. Фрагмент для IAR: Код // пакет лежит в uart1_buffer // len - длина пакета, по которому считается CRC (76 байт) void CRC16(unsigned int len) { unsigned char i; unsigned int k; unsigned int CRC;
CRC=k=0; while(k<len){ CRC=CRC^((unsigned int)uart1_buffer[k++]<<8); i=8; do{ if(CRC & 0x8000) CRC=(CRC<<1)^0x1021; else CRC=CRC<<1; } while(--i); } // дописываем в конец буфера CRC16 uart1_buffer[76]=CRC & 0xff; uart1_buffer[77]=(CRC>>8) & 0xff; } Для пакета Код 0A 90 00 00 00 00 00 00 00 00 4F 33 40 40 05 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 CRC16 должна быть равна A1 01, а рассчитывается 0B D1, перепробовал ещё кучу стандартных алгоритмов, все рассчитывают новые CRC, но ни одна не посчитала A1 01. Голову сломал на этом затыке. Буду благодарен за любые мысли по проблеме
--------------------
Руслан
|
|
|
|
|
Apr 10 2010, 08:59
|

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

|
Цитата(AHTOXA @ Apr 10 2010, 10:24)  Видимо то устройство, что работало, было 16-битное?  Не видимо, а именно так. Только не устройство, а int был 16 бит. Ну а у писателей с писательством было туго, вот и напхали интов, где ни поподя  . Цитата(demiurg_spb @ Apr 10 2010, 10:28)  Привыкайте... Бездумная декомпозиция исходников не поможет. Ну и в Ваших образцах стиля есть еще и проблема обратная использованию int, где попало - неиспользование int, вот и заставляете, например, 32 битовик работать с 16бит переменными без всякой на то надобности  . Код for (int i=0; i<8; ++i) Тут восьмибитовик будет маяться с 16 битами у i. Код uint16_t crc16(uint8_t *p, uint16_t len) А тут 32битовик с теми-же 16 битами у len.
Сообщение отредактировал zltigo - Apr 10 2010, 09:24
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
Apr 10 2010, 09:01
|

Частый гость
 
Группа: Свой
Сообщений: 156
Регистрация: 10-03-10
Из: Уфа
Пользователь №: 55 882

|
Цитата(AHTOXA @ Apr 10 2010, 14:24)  Видимо то устройство, что работало, было 16-битное?  Попробуйте заменить unsigned int на unsigned short. Устройство было на меге2561  Цитата(baralgin @ Apr 10 2010, 14:40)  Если перед расчётом CRC проинициализировать 0x6DA5 (вместо 0), то получится как-раз "A1 01" . Просто брутфорс  . Исходник один в один скопировали? да, брал исходник как есть Всё разобрался, рядом с этой функцией лежала такая же с постфиксом New в имени  , в которой алгоритм гораздо проще, опробовал - считает правильно: Код void SumCRCNew(unsigned int len) { unsigned char i; unsigned int CRC;
CRC=0; for(i=0;i<76;i++) CRC+=uart1_buffer[i]; uart1_buffer[76]=CRC & 0xff; uart1_buffer[77]=(CRC>>8) & 0xff; } Видимо для обмена по uart прошлым разработчикам пришлось упростить контроль целостности пакета, а я эту функцию проморгал  Всем отписавшимся огромное спасибо
--------------------
Руслан
|
|
|
|
|
Apr 10 2010, 09:37
|

неотягощённый злом
     
Группа: Свой
Сообщений: 2 746
Регистрация: 31-01-08
Из: Санкт-Петербург
Пользователь №: 34 643

|
zltigo, нет предела совершенству, можно и так: Код uint16_t crc16(uint8_t *p, size_t len) А тут Код for (int i=0; i<8; ++i) никто маяться не будет, т.к. индекс не используется в теле цикла и оптимизатор всё подчистит
--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
|
|
|
|
|
Apr 10 2010, 12:17
|

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

|
Цитата(demiurg_spb @ Apr 10 2010, 11:52)  zltigo, нет предела совершенству, можно и так: Код uint16_t crc16(uint8_t *p, size_t len) Слишком правильно  . Если Вы обладаете некими дополнительными знаниями о размерностях массивов, то можно дать подсказку и облегчить жизнь 8 и 16 битовикам. Цитата и оптимизатор всё подчистит  Или да, или нет. А дабы всегда было да - int_fast8_t
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
Apr 10 2010, 23:07
|

кекс
     
Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326

|
Цитата(demiurg_spb @ Apr 10 2010, 11:28)  Код if (crc & 0x8000) crc = (crc << 1) ^ 0x1021; else crc <<= 1; Привыкайте писать исходники структурировано и прозрачно.... И это Вы назваете "прозрачно"? Еще б вот такое назвали "прозрачно": Код if (crc & 1) crc = (crc >> 1) ^ 0xA001; else crc = (crc >> 1);
|
|
|
|
|
Apr 13 2010, 06:47
|

неотягощённый злом
     
Группа: Свой
Сообщений: 2 746
Регистрация: 31-01-08
Из: Санкт-Петербург
Пользователь №: 34 643

|
Цитата(defunct @ Apr 11 2010, 03:22)  И это Вы назваете "прозрачно"? Да. Называю. Приведите Вашу альтернативу. И укажите, что конкретно Вам не понравилось. Цитата(defunct @ Apr 11 2010, 03:22)  Еще б вот такое назвали... Но ведь это Ваш пример а не мой...
--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
|
|
|
|
|
Apr 13 2010, 15:40
|
Частый гость
 
Группа: Участник
Сообщений: 197
Регистрация: 8-04-05
Пользователь №: 3 977

|
Цитата(ASN @ Apr 10 2010, 16:22)  athlon64 Видимо, это стандартный CRC16 для обмена по стыку IRDA. В Linux есть исходники расчёта CRC на С.Считается табличным методом. Замена на сложение принципиально ухудшает обнаруживающую ошибки способность. Всегда интересовало - почему "Замена на сложение принципиально ухудшает обнаруживающую ошибки способность"? Одиночные ошибки - одинаково. Обнаруживаются всегда. Двойные - от статистики зависит. Если они часто в одном разряде, CRC лучше, если они независимы, сложение лучше.
|
|
|
|
|
Apr 13 2010, 17:01
|
Частый гость
 
Группа: Участник
Сообщений: 197
Регистрация: 8-04-05
Пользователь №: 3 977

|
Цитата(ASN @ Apr 13 2010, 20:43)  vallav Теорию не помню. По опыту. Работаем в очень сложной помеховой обстановке. Сложение ошибок не обнаруживало, CRC - обнаруживало. Не очень понятно. Может - сложение иногда многкратных ошибок не обнаруживало ( пропускало пакет с ошибками ). CRC пропускало пакет с ошибками в несколько раз реже. Такое может быть, если многократные ошибки сильно и специфически коррелированы. А вот чтобы - сложение всех ошибок не обнаруживало а CRC все ошибки обнаруживало - такое вряд ли.
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|