реклама на сайте
подробности

 
 
6 страниц V   1 2 3 > »   
Reply to this topicStart new topic
> Алгоритм CRC16
athlon64
сообщение Apr 10 2010, 07:39
Сообщение #1


Частый гость
**

Группа: Свой
Сообщений: 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. Голову сломал на этом затыке. Буду благодарен за любые мысли по проблеме


--------------------
Руслан
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Apr 10 2010, 08:09
Сообщение #2


фанат дивана
******

Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684



Видимо то устройство, что работало, было 16-битное? smile.gif
Попробуйте заменить unsigned int на unsigned short.


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
demiurg_spb
сообщение Apr 10 2010, 08:13
Сообщение #3


неотягощённый злом
******

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



Код
//==============================================================
static uint16_t crc_xmodem_update(uint16_t crc, uint8_t data)
{
    crc = crc ^ ((uint16_t)data << 8);

    for (int i=0; i<8; ++i)
    {
        if (crc & 0x8000) crc = (crc << 1) ^ 0x1021;
        else              crc <<= 1;
    }

    return (crc);
}
//==============================================================
uint16_t crc_xmodem(uint8_t *p, uint16_t len)
{
    uint16_t crc = 0;

    while (len--)
    {
        crc = crc_xmodem_update(crc, *p++);
    }

    return (crc);
}
//==============================================================
static uint16_t crc16_update(uint16_t crc, uint8_t data)
{
    crc ^= data;

    for (int i=0; i<8; ++i)
    {
        if (crc & 1)  crc = (crc >> 1) ^ 0xA001;
        else          crc = (crc >> 1);
    }

    return (crc);
}
//==============================================================
uint16_t crc16(uint8_t *p, uint16_t len)
{
    uint16_t crc = 0xffff;

    while (len--)
    {
        crc = crc16_update(crc, *p++);
    }

    return (crc);
}
Привыкайте писать исходники структурировано и прозрачно....


--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
Go to the top of the page
 
+Quote Post
baralgin
сообщение Apr 10 2010, 08:25
Сообщение #4


Частый гость
**

Группа: Участник
Сообщений: 92
Регистрация: 23-12-08
Из: Кишинёв
Пользователь №: 42 680



Если перед расчётом CRC проинициализировать 0x6DA5 (вместо 0), то получится как-раз "A1 01" . Просто брутфорс smile.gif . Исходник один в один скопировали?
Go to the top of the page
 
+Quote Post
zltigo
сообщение Apr 10 2010, 08:59
Сообщение #5


Гуру
******

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



Цитата(AHTOXA @ Apr 10 2010, 10:24) *
Видимо то устройство, что работало, было 16-битное? smile.gif

Не видимо, а именно так. Только не устройство, а int был 16 бит. Ну а у писателей с писательством было туго, вот и напхали интов, где ни поподя sad.gif.
Цитата(demiurg_spb @ Apr 10 2010, 10:28) *
Привыкайте...

Бездумная декомпозиция исходников не поможет. Ну и в Ваших образцах стиля есть еще и проблема обратная использованию int, где попало - неиспользование int, вот и заставляете, например, 32 битовик работать с 16бит переменными без всякой на то надобности sad.gif.
Код
    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
Go to the top of the page
 
+Quote Post
athlon64
сообщение Apr 10 2010, 09:01
Сообщение #6


Частый гость
**

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



Цитата(AHTOXA @ Apr 10 2010, 14:24) *
Видимо то устройство, что работало, было 16-битное? smile.gif
Попробуйте заменить unsigned int на unsigned short.

Устройство было на меге2561 smile.gif

Цитата(baralgin @ Apr 10 2010, 14:40) *
Если перед расчётом CRC проинициализировать 0x6DA5 (вместо 0), то получится как-раз "A1 01" . Просто брутфорс smile.gif . Исходник один в один скопировали?

да, брал исходник как есть

Всё разобрался, рядом с этой функцией лежала такая же с постфиксом New в имени smile.gif, в которой алгоритм гораздо проще, опробовал - считает правильно:
Код
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 прошлым разработчикам пришлось упростить контроль целостности пакета, а я эту функцию проморгал smile.gif
Всем отписавшимся огромное спасибо smile.gif


--------------------
Руслан
Go to the top of the page
 
+Quote Post
demiurg_spb
сообщение Apr 10 2010, 09:37
Сообщение #7


неотягощённый злом
******

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



zltigo, нет предела совершенству, можно и так:
Код
uint16_t crc16(uint8_t *p, size_t len)

А тут
Код
for (int i=0; i<8; ++i)
никто маяться не будет, т.к. индекс не используется в теле цикла и оптимизатор всё подчиститsmile.gif


--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
Go to the top of the page
 
+Quote Post
ASN
сообщение Apr 10 2010, 12:07
Сообщение #8


Местный
***

Группа: Свой
Сообщений: 459
Регистрация: 15-07-04
Из: g.Penza
Пользователь №: 326



athlon64
Видимо, это стандартный CRC16 для обмена по стыку IRDA. В Linux есть исходники расчёта CRC на С.Считается табличным методом.
Замена на сложение принципиально ухудшает обнаруживающую ошибки способность.
Go to the top of the page
 
+Quote Post
zltigo
сообщение Apr 10 2010, 12:17
Сообщение #9


Гуру
******

Группа: Свой
Сообщений: 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)

Слишком правильно smile.gif. Если Вы обладаете некими дополнительными знаниями о размерностях массивов, то можно дать подсказку и облегчить жизнь 8 и 16 битовикам.
Цитата
и оптимизатор всё подчиститsmile.gif

Или да, или нет. А дабы всегда было да - int_fast8_t


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
defunct
сообщение Apr 10 2010, 23:07
Сообщение #10


кекс
******

Группа: Свой
Сообщений: 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);
Go to the top of the page
 
+Quote Post
demiurg_spb
сообщение Apr 13 2010, 06:47
Сообщение #11


неотягощённый злом
******

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



Цитата(defunct @ Apr 11 2010, 03:22) *
И это Вы назваете "прозрачно"?
Да. Называю. Приведите Вашу альтернативу. И укажите, что конкретно Вам не понравилось.

Цитата(defunct @ Apr 11 2010, 03:22) *
Еще б вот такое назвали...
Но ведь это Ваш пример а не мой...


--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
Go to the top of the page
 
+Quote Post
vallav
сообщение Apr 13 2010, 15:40
Сообщение #12


Частый гость
**

Группа: Участник
Сообщений: 197
Регистрация: 8-04-05
Пользователь №: 3 977



Цитата(ASN @ Apr 10 2010, 16:22) *
athlon64
Видимо, это стандартный CRC16 для обмена по стыку IRDA. В Linux есть исходники расчёта CRC на С.Считается табличным методом.
Замена на сложение принципиально ухудшает обнаруживающую ошибки способность.


Всегда интересовало - почему "Замена на сложение принципиально ухудшает обнаруживающую ошибки способность"?
Одиночные ошибки - одинаково. Обнаруживаются всегда.
Двойные - от статистики зависит. Если они часто в одном разряде, CRC лучше, если они независимы, сложение лучше.
Go to the top of the page
 
+Quote Post
ASN
сообщение Apr 13 2010, 16:28
Сообщение #13


Местный
***

Группа: Свой
Сообщений: 459
Регистрация: 15-07-04
Из: g.Penza
Пользователь №: 326



vallav
Теорию не помню.
По опыту. Работаем в очень сложной помеховой обстановке. Сложение ошибок не обнаруживало, CRC - обнаруживало.
Go to the top of the page
 
+Quote Post
vallav
сообщение Apr 13 2010, 17:01
Сообщение #14


Частый гость
**

Группа: Участник
Сообщений: 197
Регистрация: 8-04-05
Пользователь №: 3 977



Цитата(ASN @ Apr 13 2010, 20:43) *
vallav
Теорию не помню.
По опыту. Работаем в очень сложной помеховой обстановке. Сложение ошибок не обнаруживало, CRC - обнаруживало.


Не очень понятно. Может - сложение иногда многкратных ошибок не обнаруживало ( пропускало пакет с ошибками ).
CRC пропускало пакет с ошибками в несколько раз реже.
Такое может быть, если многократные ошибки сильно и специфически коррелированы.

А вот чтобы - сложение всех ошибок не обнаруживало а CRC все ошибки обнаруживало - такое вряд ли.
Go to the top of the page
 
+Quote Post
demiurg_spb
сообщение Apr 13 2010, 19:08
Сообщение #15


неотягощённый злом
******

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



Цитата(vallav @ Apr 13 2010, 21:16) *
Не очень понятно...

crcguide.pdf


--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
Go to the top of the page
 
+Quote Post

6 страниц V   1 2 3 > » 
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 6th July 2025 - 14:40
Рейтинг@Mail.ru


Страница сгенерированна за 0.01502 секунд с 7
ELECTRONIX ©2004-2016