|
CRC16(ModBus) на С для ATmega128, помогите разобраться |
|
|
|
Sep 17 2008, 07:38
|

Участник

Группа: Участник
Сообщений: 35
Регистрация: 30-10-07
Из: Москва
Пользователь №: 31 896

|
Всем доброе время суток! Прошу помочь мне разобраться в С коде.Сам только недавно начал осваивать. нужно реализовать CRC16 для ModBus. Я знаю,что есть куча готовых реализаций.Простым(последовательным) и табличным способом. Но хочу реализовать сам. У меня проблема в том,что для вычисления CRC нужно смотреть на состояние младшого бита. Если "1" - то выполнять XOR,если нет,то крутить дальше. Вот мой код: int crc16 (unsigned char a) // a - 8-bit data for calculation CRC { unsigned int reg, tmp; int i; reg = 0xFFFF; // step1: initial loading of 16-bit register reg ^= (unsigned int)a; // step2: a XOR reg for(i = 0;i<8;i++) //step3: 8-iteration to calculate CRC { reg >>= 1; tmp = reg; tmp <<= 15; if(tmp == 0x8000) reg ^= 0xA001; // checking: if LSB = "1" reg=reg^0xA001 } return reg; } проверку я выолняю поразрядным сдвигом 16-битного reg влево, и, если там "1",то xor. ниже преведена другая реализация CRC16 и она работет корректно!!!!int crc16 (unsigned char a) { unsigned int reg; unsigned char i, tmp; reg = 0xFFFF; reg ^= (unsigned int)a; for(i = 0;i<8;i++) { tmp = (unsigned char)(reg&0x0001); reg >>= 1; if(tmp) reg ^= 0xA001; } return reg; } Поясните,что не так в первой реализачии.
|
|
|
|
|
 |
Ответов
|
Sep 19 2008, 20:27
|

Нечётный пользователь.
     
Группа: Свой
Сообщений: 2 033
Регистрация: 26-05-05
Из: Бровари, Україна
Пользователь №: 5 417

|
Цитата(Rst7 @ Sep 19 2008, 19:06)  Ну и пара огрехов других, например, надо сдвигать yl влево на один бит. Это ладно, я не это имел ввиду, когда писал Цитата(ReAl @ Sep 19 2008, 18:16)  И что, именно этот веник действительно метёт? Даже если исправить эти мелкие огрехи, в переводе на С тот ассемблерный кусок выглядит приблизительно так: Код extern uint16_t crctable[32]; uint16_t crc;
void crc_update(uint8_t data) { crc ^= crctable[ data & 0x0F ]; crc ^= crctable[ 16 + (data >>4) ]; } Что-то не пахнет тут CRC. Мне кажется, что это ничем не лучше простой XORки всех байтов сообщения. Независимо от таблицы реакция на последовательность 0xA5 0xC3 будет та же, что и на 0xC3 0xA5 или на 0xC5 0xA3. А после того, как заставить этот код считать таки CRC, да табличку положить во флеш и получить +4 такта на переходе от LD к LPM - выйдет дольше, чем обсуждавшиеся методы.
--------------------
Ну, я пошёл… Если что – звоните…
|
|
|
|
|
Sep 21 2008, 22:30
|

Ambidexter
    
Группа: Свой
Сообщений: 1 589
Регистрация: 22-06-06
Из: Oxford, UK
Пользователь №: 18 282

|
Цитата(ReAl @ Sep 19 2008, 19:27)  Что-то не пахнет тут CRC. Мне кажется, что это ничем не лучше простой XORки всех байтов сообщения. Независимо от таблицы реакция на последовательность 0xA5 0xC3 будет та же, что и на 0xC3 0xA5 или на 0xC5 0xA3 А вот интересно, какая по-вашему будет crc для последовательностей 1) 0xA5, 0xC3 2) 0xC3, 0xA5 3) 0xC5, 0xA3 ? Таблица для справки Код LOCAL_D int crcbuf[256]= { 0x0000,0x1021,0x2042,0x3063,0x4084,0x50A5,0x60C6,0x70E7, 0x8108,0x9129,0xA14A,0xB16B,0xC18C,0xD1AD,0xE1CE,0xF1EF, 0x1231,0x0210,0x3273,0x2252,0x52B5,0x4294,0x72F7,0x62D6, 0x9339,0x8318,0xB37B,0xA35A,0xD3BD,0xC39C,0xF3FF,0xE3DE, 0x2462,0x3443,0x0420,0x1401,0x64E6,0x74C7,0x44A4,0x5485, 0xA56A,0xB54B,0x8528,0x9509,0xE5EE,0xF5CF,0xC5AC,0xD58D, 0x3653,0x2672,0x1611,0x0630,0x76D7,0x66F6,0x5695,0x46B4, 0xB75B,0xA77A,0x9719,0x8738,0xF7DF,0xE7FE,0xD79D,0xC7BC, 0x48C4,0x58E5,0x6886,0x78A7,0x0840,0x1861,0x2802,0x3823, 0xC9CC,0xD9ED,0xE98E,0xF9AF,0x8948,0x9969,0xA90A,0xB92B, 0x5AF5,0x4AD4,0x7AB7,0x6A96,0x1A71,0x0A50,0x3A33,0x2A12, 0xDBFD,0xCBDC,0xFBBF,0xEB9E,0x9B79,0x8B58,0xBB3B,0xAB1A, 0x6CA6,0x7C87,0x4CE4,0x5CC5,0x2C22,0x3C03,0x0C60,0x1C41, 0xEDAE,0xFD8F,0xCDEC,0xDDCD,0xAD2A,0xBD0B,0x8D68,0x9D49, 0x7E97,0x6EB6,0x5ED5,0x4EF4,0x3E13,0x2E32,0x1E51,0x0E70, 0xFF9F,0xEFBE,0xDFDD,0xCFFC,0xBF1B,0xAF3A,0x9F59,0x8F78, 0x9188,0x81A9,0xB1CA,0xA1EB,0xD10C,0xC12D,0xF14E,0xE16F, 0x1080,0x00A1,0x30C2,0x20E3,0x5004,0x4025,0x7046,0x6067, 0x83B9,0x9398,0xA3FB,0xB3DA,0xC33D,0xD31C,0xE37F,0xF35E, 0x02B1,0x1290,0x22F3,0x32D2,0x4235,0x5214,0x6277,0x7256, 0xB5EA,0xA5CB,0x95A8,0x8589,0xF56E,0xE54F,0xD52C,0xC50D, 0x34E2,0x24C3,0x14A0,0x0481,0x7466,0x6447,0x5424,0x4405, 0xA7DB,0xB7FA,0x8799,0x97B8,0xE75F,0xF77E,0xC71D,0xD73C, 0x26D3,0x36F2,0x0691,0x16B0,0x6657,0x7676,0x4615,0x5634, 0xD94C,0xC96D,0xF90E,0xE92F,0x99C8,0x89E9,0xB98A,0xA9AB, 0x5844,0x4865,0x7806,0x6827,0x18C0,0x08E1,0x3882,0x28A3, 0xCB7D,0xDB5C,0xEB3F,0xFB1E,0x8BF9,0x9BD8,0xABBB,0xBB9A, 0x4A75,0x5A54,0x6A37,0x7A16,0x0AF1,0x1AD0,0x2AB3,0x3A92, 0xFD2E,0xED0F,0xDD6C,0xCD4D,0xBDAA,0xAD8B,0x9DE8,0x8DC9, 0x7C26,0x6C07,0x5C64,0x4C45,0x3CA2,0x2C83,0x1CE0,0x0CC1, 0xEF1F,0xFF3E,0xCF5D,0xDF7C,0xAF9B,0xBFBA,0x8FD9,0x9FF8, 0x6E17,0x7E36,0x4E55,0x5E74,0x2E93,0x3EB2,0x0ED1,0x1EF0 };
--------------------
Делай сразу хорошо, плохо само получится
|
|
|
|
|
Sep 22 2008, 11:09
|

Нечётный пользователь.
     
Группа: Свой
Сообщений: 2 033
Регистрация: 26-05-05
Из: Бровари, Україна
Пользователь №: 5 417

|
Вы так упорствуете в своих заблуждениях... Цитата(=GM= @ Sep 22 2008, 01:30)  А вот интересно, какая по-вашему будет crc для последовательностей 1) 0xA5, 0xC3 2) 0xC3, 0xA5 3) 0xC5, 0xA3 ? Ну я не факир-вычислитель, сразу так не скажу, но что она будет разной - уверен. Какой именно будет - сейчас сбацаем тест. Цитата(=GM= @ Sep 22 2008, 01:30)  Таблица для справки Код LOCAL_D int crcbuf[256]= { 0x0000,0x1021,0x2042,0x3063,0x4084,0x50A5,0x60C6,0x70E7, ...}; Таблица не для того полинома и направления сдвига, который обсуждается в теме, ну да ладно... Для основной темы это только частичный оффтопик, но тема веников наконец-то будет раскрыта. CODE #include <stdint.h> #include <stdio.h>
uint16_t crctable[256]= { 0x0000,0x1021,0x2042,0x3063,0x4084,0x50A5,0x60C6,0x70E7, 0x8108,0x9129,0xA14A,0xB16B,0xC18C,0xD1AD,0xE1CE,0xF1EF, 0x1231,0x0210,0x3273,0x2252,0x52B5,0x4294,0x72F7,0x62D6, 0x9339,0x8318,0xB37B,0xA35A,0xD3BD,0xC39C,0xF3FF,0xE3DE, 0x2462,0x3443,0x0420,0x1401,0x64E6,0x74C7,0x44A4,0x5485, 0xA56A,0xB54B,0x8528,0x9509,0xE5EE,0xF5CF,0xC5AC,0xD58D, 0x3653,0x2672,0x1611,0x0630,0x76D7,0x66F6,0x5695,0x46B4, 0xB75B,0xA77A,0x9719,0x8738,0xF7DF,0xE7FE,0xD79D,0xC7BC, 0x48C4,0x58E5,0x6886,0x78A7,0x0840,0x1861,0x2802,0x3823, 0xC9CC,0xD9ED,0xE98E,0xF9AF,0x8948,0x9969,0xA90A,0xB92B, 0x5AF5,0x4AD4,0x7AB7,0x6A96,0x1A71,0x0A50,0x3A33,0x2A12, 0xDBFD,0xCBDC,0xFBBF,0xEB9E,0x9B79,0x8B58,0xBB3B,0xAB1A, 0x6CA6,0x7C87,0x4CE4,0x5CC5,0x2C22,0x3C03,0x0C60,0x1C41, 0xEDAE,0xFD8F,0xCDEC,0xDDCD,0xAD2A,0xBD0B,0x8D68,0x9D49, 0x7E97,0x6EB6,0x5ED5,0x4EF4,0x3E13,0x2E32,0x1E51,0x0E70, 0xFF9F,0xEFBE,0xDFDD,0xCFFC,0xBF1B,0xAF3A,0x9F59,0x8F78, 0x9188,0x81A9,0xB1CA,0xA1EB,0xD10C,0xC12D,0xF14E,0xE16F, 0x1080,0x00A1,0x30C2,0x20E3,0x5004,0x4025,0x7046,0x6067, 0x83B9,0x9398,0xA3FB,0xB3DA,0xC33D,0xD31C,0xE37F,0xF35E, 0x02B1,0x1290,0x22F3,0x32D2,0x4235,0x5214,0x6277,0x7256, 0xB5EA,0xA5CB,0x95A8,0x8589,0xF56E,0xE54F,0xD52C,0xC50D, 0x34E2,0x24C3,0x14A0,0x0481,0x7466,0x6447,0x5424,0x4405, 0xA7DB,0xB7FA,0x8799,0x97B8,0xE75F,0xF77E,0xC71D,0xD73C, 0x26D3,0x36F2,0x0691,0x16B0,0x6657,0x7676,0x4615,0x5634, 0xD94C,0xC96D,0xF90E,0xE92F,0x99C8,0x89E9,0xB98A,0xA9AB, 0x5844,0x4865,0x7806,0x6827,0x18C0,0x08E1,0x3882,0x28A3, 0xCB7D,0xDB5C,0xEB3F,0xFB1E,0x8BF9,0x9BD8,0xABBB,0xBB9A, 0x4A75,0x5A54,0x6A37,0x7A16,0x0AF1,0x1AD0,0x2AB3,0x3A92, 0xFD2E,0xED0F,0xDD6C,0xCD4D,0xBDAA,0xAD8B,0x9DE8,0x8DC9, 0x7C26,0x6C07,0x5C64,0x4C45,0x3CA2,0x2C83,0x1CE0,0x0CC1, 0xEF1F,0xFF3E,0xCF5D,0xDF7C,0xAF9B,0xBFBA,0x8FD9,0x9FF8, 0x6E17,0x7E36,0x4E55,0x5E74,0x2E93,0x3EB2,0x0ED1,0x1EF0 };
uint16_t gm_crc_update(uint16_t crc, uint8_t data) { return crc ^ crctable[ data ]; }
uint16_t canonical_crc_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 fast_table_crc_update(uint16_t crc, uint8_t data) { uint8_t index = (crc >> 8) ^ data; crc = (crc << 8) ^ crctable[index]; return crc; }
uint16_t fast_non_table_crc_update(uint16_t crc, uint8_t data) { uint8_t carry = (crc >> 8) ^ data; carry = carry ^ (carry >> 4); crc = (((crc ^ (carry << 4)) << 8) | carry) ^ (carry << 5); return crc; }
//-------------------------------------------------------------------------
uint16_t calc_crc( uint16_t (*crc_update)(uint16_t, uint8_t), const uint8_t *buf, int len) { uint16_t crc = 0; while(len--) crc = crc_update(crc, *buf++); return crc; }
void show_crc( uint16_t (*crc_update)(uint16_t, uint8_t), const uint8_t *buf, int len) { printf("crc = %04X for buf = ", calc_crc( crc_update, buf, len) ); for(int i = 0; i < len; ++i) printf(" %2X", buf[i]); putchar('\n'); }
const uint8_t buf1[] = { 0xA5, 0xC3 }; const uint8_t buf2[] = { 0xC3, 0xA5 }; const uint8_t buf3[] = { 0xC5, 0xA3 };
int main() { printf("\n=== GM super-fast table algorithm ==========\n"); show_crc( gm_crc_update, buf1, sizeof(buf1) ); show_crc( gm_crc_update, buf2, sizeof(buf2) ); show_crc( gm_crc_update, buf3, sizeof(buf3) ); printf("\n=== Canonical bitwise algorithm ============\n"); show_crc( canonical_crc_update, buf1, sizeof(buf1) ); show_crc( canonical_crc_update, buf2, sizeof(buf2) ); show_crc( canonical_crc_update, buf3, sizeof(buf3) ); printf("\n=== Correct table bytewise algorithm =======\n"); show_crc( fast_table_crc_update, buf1, sizeof(buf1) ); show_crc( fast_table_crc_update, buf2, sizeof(buf2) ); show_crc( fast_table_crc_update, buf3, sizeof(buf3) );
printf("\n=== Fast non-table bytewise algorithm =======\n"); show_crc( fast_non_table_crc_update, buf1, sizeof(buf1) ); show_crc( fast_non_table_crc_update, buf2, sizeof(buf2) ); show_crc( fast_non_table_crc_update, buf3, sizeof(buf3) ); } Код === GM super-fast table algorithm ========== crc = 0C60 for buf = A5 C3 crc = 0C60 for buf = C3 A5 crc = 0C60 for buf = C5 A3
=== Canonical bitwise algorithm ============ crc = 0BA4 for buf = A5 C3 crc = A648 for buf = C3 A5 crc = 6C28 for buf = C5 A3
=== Correct table bytewise algorithm ======= crc = 0BA4 for buf = A5 C3 crc = A648 for buf = C3 A5 crc = 6C28 for buf = C5 A3
=== Fast non-table bytewise algorithm ======= crc = 0BA4 for buf = A5 C3 crc = A648 for buf = C3 A5 crc = 6C28 for buf = C5 A3 Dixi
--------------------
Ну, я пошёл… Если что – звоните…
|
|
|
|
|
Sep 23 2008, 11:51
|

Ambidexter
    
Группа: Свой
Сообщений: 1 589
Регистрация: 22-06-06
Из: Oxford, UK
Пользователь №: 18 282

|
Ну, я не упорствую, но вот это ваше "return crc^crctable[data]" как-то слишком прямолинейно, даже для меня. Это ж просто выборка из таблицы для вычисления цкс, а можно сделать выборку, используя тетрады данных, тогда размер таблицы уменьшится с 512 байт до 64 байт, надеюсь, вам это понятно. Собственно вот код, который так и делает. Как видите, веник метёт, и неплохо(:-). Код crcloop: ld data,z+ eor data,crch mov crch,crcl mov yl,data andi yl,0x0F ld crcl,y ldd tmp,y+16 eor crch,tmp eor yl,data swap yl ldd tmp,y+32 eor crcl,tmp ldd tmp,y+48 eor crch,tmp dec datcnt brne crcloop Для ваших тестовых строк даёт те же цкс Код .db 0xA5,0xC3 ;CRC=0x0BA4 .db 0xC5,0xA3 ;CRC=0x6С28 .db 0xC3,0xA5 ;CRC=0xA648 (Замечу в скобках, обычно цкс начинают считать с 0xFFFF, а не с 0х0000 как у вас)
--------------------
Делай сразу хорошо, плохо само получится
|
|
|
|
|
Sep 29 2008, 19:50
|

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

|
Цитата(=GM= @ Sep 23 2008, 14:51)  Для ваших тестовых строк даёт те же цкс Код .db 0xA5,0xC3 ;CRC=0x0BA4 .db 0xC5,0xA3 ;CRC=0x6С28 .db 0xC3,0xA5 ;CRC=0xA648 (Замечу в скобках, обычно цкс начинают считать с 0xFFFF, а не с 0х0000 как у вас) У вас ошибка CRC. Модбас работать не будет. Д.б. сл. значения .db 0xA5,0xC3 ;CRC=0xB13A .db 0xC5,0xA3 ;CRC=0x9912 .db 0xC3,0xA5 ;CRC=0x3B91
|
|
|
|
|
Sep 30 2008, 15:35
|

Ambidexter
    
Группа: Свой
Сообщений: 1 589
Регистрация: 22-06-06
Из: Oxford, UK
Пользователь №: 18 282

|
Цитата(defunct @ Sep 30 2008, 12:13)  Я не табличкой считал, а старым дедовским способом, описанным в спецификации на modbus (гарантированно правильным). ReAl от Вас хотел только неравенства всех трех значений, а нужно чтоб кроме неравенства еще и считалось _то_ что надо ReAl считал тремя способами, между прочим, и старым дедовским тоже. И вообще-то, ReAl хотел добиться правды, он её добился, все получили более-менее быстрый алгоритм с таблицей в ВОСЕМЬ раз меньше стандартной таблицы. А я считал по своему алгоритму, и результаты всех четырёх расчётов совпали, вам что, этого мало? Я ж вам сказал, возьмите правильную, нужную таблицу для модбаса, и дело в шляпе. Алгоритм универсальный. А укороченные таблицы вычленяются из штатных.
--------------------
Делай сразу хорошо, плохо само получится
|
|
|
|
|
Sep 30 2008, 16:04
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
Цитата(=GM= @ Sep 30 2008, 18:35)  Я ж вам сказал, возьмите правильную, нужную таблицу для модбаса, и дело в шляпе. Но ведь это вы "вбросили" сюда неправильную неподходящую таблицу, почему исправлять это недоразумение должны ReAl и defunct? Начали - доводите до конца. И озвучьте характеристики вашего кода (размер/такты), чтобы можно было сравнить.
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Sep 30 2008, 21:49
|

Ambidexter
    
Группа: Свой
Сообщений: 1 589
Регистрация: 22-06-06
Из: Oxford, UK
Пользователь №: 18 282

|
Цитата(Сергей Борщ @ Sep 30 2008, 15:04)  Но ведь это вы "вбросили" сюда неправильную неподходящую таблицу, почему исправлять это недоразумение должны ReAl и defunct? Начали - доводите до конца. И озвучьте характеристики вашего кода (размер/такты), чтобы можно было сравнить. Во, Сергей Борщ объявился, а мы уж и не ждали (:-)! Это ведь вы заварили всю кашу, как, да что, да опубликуйте код... ReAl ничего не исправлял и не должен, с какой стати? Он посчитал цкс по моей таблице, она совпала с моим расчётом, он и согласился со мной. Теперь о таблице. Если есть таблица для любого полинома, то можно легко получить укороченную таблицу, что я и пытался показать своим первым кодом (по крайней мере, для меня было трудно написать с ходу), но тут все накинулись, не так, не работает, да и озу, ой как жалко, целых 64 байта... Короче, дайте таблицу для модбаса, я её подрихтую. Как я уже говорил, таблица занимает 64 байта озу, программа считает цкс для одного байта в цикле за 22 МЦ, хотя можно уменьшить до 21. Цитата(defunct @ Sep 30 2008, 15:46)  Проблема в том, что не получилось у меня создать таблицу для модбаса (256x16) чтобы работала по вашему алгоритму: crc ^= crctable2[ data ] defunct, это не алгоритм, мой алгоритм приведен в посте #28. А то, что вы привели, мне бы надо переписать как-то так CRCLUT=crctable2[ data ], выше я уже говорил про это. Вот вам код для расчёта по таблице, случайно оказался дома на одном из двд, 100% рабочий, вырвал из моей старой программы 2001 года, работала с очень неудобным таг-ридером, который проектировал один кетаец в юса, отсюда такая таблица Код lcrc=hcrc=0x00FF; for(i=0;i<nbyte;i++) { indx=(datain[i]^hcrc)&0x00FF; crc=crcbuf[indx]; hcrc=((crc>>8)^lcrc)&0xFF; lcrc=crc&0x00FF; } hcrc=hcrc^0x00FF; lcrc=lcrc^0x00FF;
--------------------
Делай сразу хорошо, плохо само получится
|
|
|
|
|
Oct 3 2008, 09:23
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
Цитата(=GM= @ Oct 1 2008, 00:49)  Во, Сергей Борщ объявился, а мы уж и не ждали (:-)! Это ведь вы заварили всю кашу, как, да что, да опубликуйте код... Я и не пропадал. Внимательно смотрю, как вы выкручиваетесь. Не надо перекладывать с одной головы на здоровую. Кашу заварили вы: Цитата(=GM= @ Sep 19 2008, 14:20)  А что если сделать две таблицы на биты <7-4> и <3-0>? Прикинул программулю, получается 20 тактов на байт, размер 47 слов вместе с таблицами. Я лишь попросил вас привести подтверждение этих цифр в виде кода. Алгоритм, который вы, снова не удосужившисть проверить, привели, оказался абсолютно нерабочим, что вам с цифрами в руках доказал ReAl. Вы довели его до ума, но от исходных "20 тактов на байт, размер 47 слов вместе с таблицами" не осталось и следа. И вдруг выясняется, что ваш алгоритм считает совсем другую CRC. И снова виноват кто-то другой: Цитата(=GM= @ Sep 30 2008, 12:26)  А вы это ReAl'у скажите, у меня с ним совпало. Хотя: Цитата(ReAl @ Sep 22 2008, 14:09)  Таблица не для того полинома и направления сдвига, который обсуждается в теме, ну да ладно... Для основной темы это только частичный оффтопик, но тема веников наконец-то будет раскрыта. "Казалось бы, при чем здесь Лужков"? Цитата(=GM= @ Oct 1 2008, 00:49)  ReAl ничего не исправлял и не должен, с какой стати? Он посчитал цкс по моей таблице, она совпала с моим расчётом, он и согласился со мной. Совесть имейте: Цитата(ReAl @ Sep 19 2008, 23:27)  Что-то не пахнет тут CRC. Мне кажется, что это ничем не лучше простой XORки всех байтов сообщения. Независимо от таблицы реакция на последовательность 0xA5 0xC3 будет та же, что и на 0xC3 0xA5 или на 0xC5 0xA3. Итог после всех ваших исправлений "прикинутой программули": уменьшить таблицы можно, но "47 слов вместе с таблицами и 20 тактов", которые были главными козырями, нету и близко. Хотя виноваты, конечно, все, кроме =GM=. Цитата(=GM= @ Oct 3 2008, 11:30)  Проверил ещё раз, получаются другие результаты, но пригляделся - они такие же, только у вас переставлены младший и старший байты. Честно-честно? Проверили? И что, это работало? Цитата Код uchCRCHi = uchCRCLo ^ auchCRCHi[uIndex}; Цитата(=GM= @ Oct 3 2008, 11:30)  И таблица, и программа взяты из описания протокола модбас Ну а где же ваши чудо-таблицы? Что же вы проверяли - описание модбас?
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Oct 3 2008, 12:43
|

Ambidexter
    
Группа: Свой
Сообщений: 1 589
Регистрация: 22-06-06
Из: Oxford, UK
Пользователь №: 18 282

|
Вот укороченная таблица для модбаса Код ;a short crc table for modbus protocol .db 0x00,0xC0,0xC1,0x01,0xC3,0x03,0x02,0xC2 .db 0xC6,0x06,0x07,0xC7,0x05,0xC5,0xC4,0x04 .db 0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41 .db 0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40 .db 0x00,0xCC,0xD8,0x14,0xF0,0x3C,0x28,0xE4 .db 0xA0,0x6C,0x78,0xB4,0x50,0x9C,0x88,0x44 .db 0x00,0x01,0x01,0x00,0x01,0x00,0x00,0x01 .db 0x01,0x00,0x00,0x01,0x00,0x01,0x01,0x00 Вот тестовые строки и цкс для каждой строки, как результат работы моей программы с укороченной таблицей. А у Юры явно перепутаны старший и младший байты Код .db 0xA5,0xC3;CRC=0x3AB1 .db 0xC5,0xA3;CRC=0x1299 .db 0xC3,0xA5;CRC=0x913B Как видите, таблица занимает 32 слова в озу, сама программа занимает 16 слов во флеше, в итоге получается 48. Один байт из буфера обсчитывается за 22 такта с учетом организации цикла. Можно сделать за 21 такт, не стал приводить, поскольку сложнее для понимания. Кому надо, легко сделает. Можно также развернуть цикл, будет примерно 96флеш+32озу=128 слов, время выполнения будет 19 тактов на байт. Ещё раз, алгоритм универсальный, работает для ЛЮБОГО полинома, поскольку берёт данные из укороченной таблицы соответствующего полинома. На остальное не отвечаю по понятной причине.
--------------------
Делай сразу хорошо, плохо само получится
|
|
|
|
|
Jan 9 2009, 00:07
|

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

|
Цитата(=GM= @ Oct 3 2008, 14:43)  Вот тестовые строки и цкс для каждой строки, как результат работы моей программы с укороченной таблицей. А у Юры явно перепутаны старший и младший байты =GM=, наткнулся на табличную реализацию - точно такую же как Вы привели  У меня все-таки ничего не перепутано, похоже, что пример который Вы нашли сделан для big-endian проца. Для little-endian результат должен быть такой как у меня. Ну и чтоб с приведеными табличками можно было работать на AVR привожу код (для AVR'а надо пользовать little-endian функцию): Код #if (BIG_ENDIAN) // big endian CPU U16 crc16(U16 crc, U8 data) { U8 index; U8 crc_High = crc >> 8; U8 crc_Low = crc & 0xFF;
index = crc_High ^ data; crc_High = crc_Low ^ mb_table_level1[ index ]; crc_Low = mb_table_level2[ index ];
return (crc_High << 8) | crc_Low; } #else // little endian CPU U16 CRC16_Update(U16 crc, U8 data) { U8 index; U8 crc_High = crc >> 8; U8 crc_Low = crc & 0xFF;
index = crc_Low ^ data; crc_Low = crc_High ^ mb_table_level1[ index ]; crc_High = mb_table_level2[ index ];
return (crc_High << 8) | crc_Low; } #endif mb_table_level1 ---> auchCRCHi из поста #42 mb_table_level2 ---> auchCRCLo из поста #42
|
|
|
|
|
Jan 9 2009, 11:38
|

Ambidexter
    
Группа: Свой
Сообщений: 1 589
Регистрация: 22-06-06
Из: Oxford, UK
Пользователь №: 18 282

|
Цитата(defunct @ Jan 9 2009, 00:07)  =GM=, наткнулся на табличную реализацию - точно такую же как Вы привели  У меня все-таки ничего не перепутано, похоже, что пример который Вы нашли сделан для big-endian проца Вполне может быть, они такие путаники. Вот выжимка из описания модбаса как вычисляется кцс CODE Алгоритм генерации CRC: 1. 16-ти битовый регистр загружается числом FF hex (все 1), и используется далее как регистр CRC. 2. Первый байт сообщения складывается по ИСКЛЮЧАЮЩЕМУ ИЛИ с содержимым регистра CRC. Результат помещается в регистр CRC. 3. Регистр CRC сдвигается вправо(в направлении младшего бита) на 1 бит, старший бит заполняется 0. 4. (Если младший бит 0): Повторяется шаг 3 (сдвиг) (Если младший бит 1): Делается операция ИСКЛЮЧАЮЩЕЕ ИЛИ регистра CRC и полиномиального числа A001 hex. 5. Шаги 3 и 4 повторяются восемь раз. 6. Повторяются шаги со 2 по 5 для следующего сообщения. Это повторяется до тех пор пока все байты сообщения не будут обработаны. 7. Финальное содержание регистра CRC и есть контрольная сумма. РАЗМЕЩЕНИЕ CRC В СООБЩЕНИИ При передаче 16 бит контрольной суммы CRC в сообщении, сначала передается младший байт, затем старший. Например, если CRC равна 1241 hex :
| Адрес | Функция | Счетчик | Данные | CRC Ст | CRC Мл | 41 12
ПРИМЕР Пример функции на языке C реализующей генерацию CRC приведен ниже. Все возможные величины CRC загружены в два массива. Один массив содержит все 256 возможных комбинаций CRC для старшего байта поля CRC, другой массив содержит данные для младшего байта. Идексация CRC в этом случая обеспечивает быстрое выполнение вычислений новой величины CRC для каждого нового байта из буфера сообщения. Функция принимает два аргумента: unsigned char *puchMsg; /* Указатель на буфер */ unsigned short usDataLen; /* Количество байтов в буфере */ Функция возвращает CRC как тип unsigned short. static unsigned char auchCRCHi [ ] = { 0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01,0xC0,0x80,0x41,0x00, 0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,0x00,0xC1, 0x81,0x40,0x01,0xC0,0x80,0x41,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81, 0x40,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40, 0x01,0xC0,0x80,0x41,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,0x01, 0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,0x00,0xC1,0x81,0x40,0x01,0xC0, 0x80,0x41,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01,0xC0,0x80, 0x22,0x00,0xC1,0x81,0x40,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41, 0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x00, 0xC1,0x81,0x40,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01,0xC0, 0x80,0x41,0x00,0xC1,0x81,0x40,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80, 0x41,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01,0xC0,0x80,0x41, 0x00,0xC1,0x81,0x40,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01, 0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x00,0xC1, 0x81,0x40,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81, 0x40,0x01,0xC0,0x80,0x41,0x00,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40, 0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,0x00,0xC1,0x81,0x40,0x01, 0xC0,0x80,0x41,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,0x00,0xC1, 0x81,0x40,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80, 0x41,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40 } static char auchCRCLo [ ] = { 0x00,0xC0,0xC1,0x01,0xC3,0x03,0x02,0xC2,0xC6,0x06,0x07,0xC7,0x05, 0xC5,0xC4,0x04,0xCC,0x0C,0x0D,0xCD,0x0F,0xCF,0xCE,0x0E,0x0A,0xCA, 0xCB,0x0B,0xC9,0x09,0x08,0xC8,0xD8,0x18,0x19,0xD9,0x1B,0xDB,0xDA, 0x1A,0x1E,0xDE,0xDF,0x1F,0xDD,0x1D,0x1C,0xDC,0x14,0xD4,0xD5,0x15, 0xD7,0x17,0x16,0xD6,0xD2,0x12,0x13,0xD3,0x11,0xD1,0xD0,0x10,0xF0, 0x30,0x31,0xF1,0x33,0xF3,0xF2,0x32,0x36,0xF6,0xF7,0x37,0xF5,0x35, 0x34,0xF4,0x3C,0xFC,0xFD,0x3D,0xFF,0x3F,0x3E,0xFE,0xFA,0x3A,0x3B, 0xFB,0x39,0xF9,0xF8,0x38,0x28,0xE8,0xE9,0x29,0xEB,0x2B,0x2A,0xEA, 0xEE,0x2E,0x2F,0xEF,0x2D,0xED,0xEC,0x2C,0xE4,0x24,0x25,0xE5,0x27, 0xE7,0xE6,0x26,0x22,0xE2,0xE3,0x23,0xE1,0x21,0x20,0xE0,0xA0,0x60, 0x61,0xA1,0x63,0xA3,0xA2,0x62,0x66,0xA6,0xA7,0x67,0xA5,0x65,0x64, 0xA4,0x6C,0xAC,0xAD,0x6D,0xAF,0x6F,0x6E,0xAE,0xAA,0x6A,0x6B,0xAB, 0x69,0xA9,0xA8,0x68,0x78,0xB8,0xB9,0x79,0xBB,0x7B,0x7A,0xBA,0xBE, 0x7E,0x7F,0xBF,0x7D,0xBD,0xBC,0x7C,0xB4,0x74,0x75,0xB5,0x77,0xB7, 0xB6,0x76,0x72,0xB2,0xB3,0x73,0xB1,0x71,0x70,0xB0,0x50,0x90,0x91, 0x51,0x93,0x53,0x52,0x92,0x96,0x56,0x57,0x97,0x55,0x95,0x94,0x54, 0x9C,0x5C,0x5D,0x9D,0x5F,0x9F,0x9E,0x5E,0x5A,0x9A,0x9B,0x5B,0x99, 0x59,0x58,0x98,0x88,0x48,0x49,0x89,0x4B,0x8B,0x8A,0x4A,0x4E,0x8E, 0x8F,0x4F,0x8D,0x4D,0x4C,0x8C,0x44,0x84,0x85,0x45,0x87,0x47,0x46, 0x86,0x82,0x42,0x43,0x83,0x41,0x81,0x80,0x40 } unsigned short CRC16(puchMsg, usDataLen) unsigned char *puchMsg; unsigned short usDataLen; { unsigned char uchCRCHi = 0xFF; unsigned char uchCRCLo = 0xFF; while (usDataLen--) { uIndex = uchCRCHi *puchMsg++; uchCRCHi = uchCRCLo auchCRCHi [ uIndex ]; uchCRCLo = auchCRCLo [ uIndex ]; } return (uchCRCHi << 8 | uchCRCLo); }
Обратите внимание, в примере CRC=0х1241, прямо указано сначала передается младший байт, затем старший, а потом в табличке почему-то стоит CRC Ст над младшим байтом. Почему стоит Ст, а не Мл? Ну не п&#o$a$ы, а?
--------------------
Делай сразу хорошо, плохо само получится
|
|
|
|
Сообщений в этой теме
sf9 CRC16(ModBus) на С для ATmega128 Sep 17 2008, 07:38 Sat360 В первой реализации регистр сдвигается ДО анализа ... Sep 17 2008, 07:46 Сергей Борщ В работающей программе сначала запоминается младши... Sep 17 2008, 07:55 sf9 СПАСИБО ОГРОМНОЕ!!!
Я понял,просто ... Sep 17 2008, 08:30 Rst7 А меня вот последнее время поперло по-другому CRC1... Sep 17 2008, 08:52 ReAl Цитата(Rst7 @ Sep 17 2008, 11:52) А меня ... Sep 17 2008, 10:29  singlskv Цитата(ReAl @ Sep 17 2008, 14:29) У avr-g... Sep 17 2008, 17:43 sf9 Кстати,в компиляторах и САПРах для МСs как можно п... Sep 17 2008, 09:15 Rst7 Никак. Только ручками. Ну или в симуляторе выполни... Sep 17 2008, 09:29 sf9 Цитата(Rst7 @ Sep 17 2008, 13:29) Никак. ... Sep 17 2008, 09:43 Rst7 ЦитатаЕсть ли настройки в компиляторах или САПРах ... Sep 17 2008, 09:50 sf9 Спасибо большое!
Побрёл я наращивать головные ... Sep 17 2008, 10:04 sf9 По поводу crc16.h абсолютно согласен,вчера проверя... Sep 18 2008, 09:52 Rst7 Цитата+1 Оптимальнее чем в avr-gcc для crc16 и не ... Sep 18 2008, 11:42 singlskv Цитата(Rst7 @ Sep 18 2008, 15:42) Не кажи... Sep 18 2008, 20:25  =GM= А что если сделать две таблицы на биты <7-4... Sep 19 2008, 11:20   Сергей Борщ Цитата(=GM= @ Sep 19 2008, 14:20) А что е... Sep 19 2008, 11:47    =GM= Идея простая, как веник. Ну вот как-то так, таблиц... Sep 19 2008, 12:07     ReAl Цитата(=GM= @ Sep 19 2008, 15:07) Идея пр... Sep 19 2008, 15:16  =GM= Цитата(ReAl @ Sep 19 2008, 19:27) в перев... Sep 19 2008, 23:17   ReAl Цитата(=GM= @ Sep 20 2008, 02:17) Я бы ещ... Sep 20 2008, 07:16    =GM= Цитата(ReAl @ Sep 20 2008, 06:16) Кажется... Sep 20 2008, 17:36     ReAl Цитата(=GM= @ Sep 20 2008, 20:36) Речь я ... Sep 20 2008, 20:51     singlskv Цитата(=GM= @ Sep 23 2008, 15:51) (Замечу... Sep 23 2008, 18:48     ReAl Цитата(=GM= @ Sep 23 2008, 14:51) Ну, я н... Sep 23 2008, 21:33      =GM= Цитата(ReAl @ Sep 23 2008, 20:33) Вы сами... Sep 23 2008, 23:18         defunct Цитата(=GM= @ Sep 30 2008, 18:35) Я ж вам... Sep 30 2008, 16:46      =GM= Цитата(defunct @ Sep 29 2008, 18:50) Mодб... Oct 2 2008, 15:27       defunct Цитата(=GM= @ Oct 2 2008, 18:27) defuct, ... Oct 2 2008, 16:37        =GM= Цитата(defunct @ Oct 2 2008, 15:37) Если ... Oct 2 2008, 20:41      =GM= Проверил ещё раз, получаются другие результаты, но... Oct 3 2008, 08:30 dred73 Держи рабочие функции по расчету CRC8 и CRC16
Код... Jan 11 2009, 07:04 Kovrov Ребят, может кто нибудь оканчательный исходник выл... Aug 12 2009, 09:59 =GM= Код в посте #28, таблица для модбаса и тестовые ве... Aug 12 2009, 22:03 Kovrov В этом примере таблица находится в рам пусть и 64 ... Aug 13 2009, 13:38
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|