Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Подсчет СRC
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > AVR
Pyku_He_oTTyda
Подскажите, как правильно посчитать на ассемблере контрольную сумму ключа I-BUTTON?
haker_fox
У меня тут правда на Си пример подсчета CRC8, но он очень простой и я думаю его не трудно перевести на ассембелр. Сам давно не работал с асмом. Если Вы не знаете Си, то прошу меня извинить, другого у меня не было.

Код
const unsigned char crc_table[256] = {
0x00,0x5E,0xBC,0xE2,0x61,0x3F,0xDD,0x83,0xC2,0x9C,0x7E,0x20,0xA3,0xFD,0x1F,0x41,
0x9D,0xC3,0x21,0x7F,0xFC,0xA2,0x40,0x1E,0x5F,0x01,0xE3,0xBD,0x3E,0x60,0x82,0xDC,
0x23,0x7D,0x9F,0xC1,0x42,0x1C,0xFE,0xA0,0xE1,0xBF,0x5D,0x03,0x80,0xDE,0x3C,0x62,
0xBE,0xE0,0x02,0x5C,0xDF,0x81,0x63,0x3D,0x7C,0x22,0xC0,0x9E,0x1D,0x43,0xA1,0xFF,
0x46,0x18,0xFA,0xA4,0x27,0x79,0x9B,0xC5,0x84,0xDA,0x38,0x66,0xE5,0xBB,0x59,0x07,
0xDB,0x85,0x67,0x39,0xBA,0xE4,0x06,0x58,0x19,0x47,0xA5,0xFB,0x78,0x26,0xC4,0x9A,
0x65,0x3B,0xD9,0x87,0x04,0x5A,0xB8,0xE6,0xA7,0xF9,0x1B,0x45,0xC6,0x98,0x7A,0x24,
0xF8,0xA6,0x44,0x1A,0x99,0xC7,0x25,0x7B,0x3A,0x64,0x86,0xD8,0x5B,0x05,0xE7,0xB9,
0x8C,0xD2,0x30,0x6E,0xED,0xB3,0x51,0x0F,0x4E,0x10,0xF2,0xAC,0x2F,0x71,0x93,0xCD,
0x11,0x4F,0xAD,0xF3,0x70,0x2E,0xCC,0x92,0xD3,0x8D,0x6F,0x31,0xB2,0xEC,0x0E,0x50,
0xAF,0xF1,0x13,0x4D,0xCE,0x90,0x72,0x2C,0x6D,0x33,0xD1,0x8F,0x0C,0x52,0xB0,0xEE,
0x32,0x6C,0x8E,0xD0,0x53,0x0D,0xEF,0xB1,0xF0,0xAE,0x4C,0x12,0x91,0xCF,0x2D,0x73,
0xCA,0x94,0x76,0x28,0xAB,0xF5,0x17,0x49,0x08,0x56,0xB4,0xEA,0x69,0x37,0xD5,0x8B,
0x57,0x09,0xEB,0xB5,0x36,0x68,0x8A,0xD4,0x95,0xCB,0x29,0x77,0xF4,0xAA,0x48,0x16,
0xE9,0xB7,0x55,0x0B,0x88,0xD6,0x34,0x6A,0x2B,0x75,0x97,0xC9,0x4A,0x14,0xF6,0xA8,
0x74,0x2A,0xC8,0x96,0x15,0x4B,0xA9,0xF7,0xB6,0xE8,0x0A,0x54,0xD7,0x89,0x6B,0x35}
;

//Вычисляет и возвращает crc8
//byte - очередной байт, для которого считаем контрольныю сумму
//crc8 - байт самой контрольной суммы
void do_crc_8(unsigned char byte, unsigned char *crc8)
{
*crc8=crc_table[(*crc8^byte)];
}
Pyku_He_oTTyda
Попробую разобратся, вроде понятно немного.
А можно просто в двух словах изложить алгоритм подсчета, как он делается...
haker_fox
Цитата
А можно просто в двух словах изложить алгоритм подсчета, как он делается...

К сожалению я не знаю алгоритм, сам выдрал пример из инета.
На всякий случай даю дизассемблированный текст, то что для меня создал IAR:
Код
    crc_table:
   \   00000000   5E00E2BC3F61       DB 0, 94, 188, 226, 97, 63, 221, 131, 194, 156, 126, 32, 163, 253, 31
   \              83DD9CC2207E
   \              FDA31F      
   \   0000000F   9D4121C3FC7F       DB 65, 157, 195, 33, 127, 252, 162, 64, 30, 95, 1, 227, 189, 62, 96
   \              40A25F1EE301
   \              3EBD60      
   \   0000001E   DC827D23C19F       DB 130, 220, 35, 125, 159, 193, 66, 28, 254, 160, 225, 191, 93, 3, 128
   \              1C42A0FEBFE1
   \              035D80      
   \   0000002D   3CDEBE6202E0       DB 222, 60, 98, 190, 224, 2, 92, 223, 129, 99, 61, 124, 34, 192, 158
   \              DF5C63817C3D
   \              C0229E      
   \   0000003C   431DFFA11846       DB 29, 67, 161, 255, 70, 24, 250, 164, 39, 121, 155, 197, 132, 218, 56
   \              A4FA7927C59B
   \              DA8438      
   \   0000004B   E56659BBDB07       DB 102, 229, 187, 89, 7, 219, 133, 103, 57, 186, 228, 6, 88, 25, 71
   \              6785BA3906E4
   \              195847      
   \   0000005A   FBA526789AC4       DB 165, 251, 120, 38, 196, 154, 101, 59, 217, 135, 4, 90, 184, 230, 167
   \              3B6587D95A04
   \              E6B8A7      
   \   00000069   1BF9C6457A98       DB 249, 27, 69, 198, 152, 122, 36, 248, 166, 68, 26, 153, 199, 37, 123
   \              F82444A6991A
   \              25C77B      
   \   00000078   643AD886055B       DB 58, 100, 134, 216, 91, 5, 231, 185, 140, 210, 48, 110, 237, 179, 81
   \              B9E7D28C6E30
   \              B3ED51      
   \   00000087   4E0FF2102FAC       DB 15, 78, 16, 242, 172, 47, 113, 147, 205, 17, 79, 173, 243, 112, 46
   \              937111CDAD4F
   \              70F32E      
   \   00000096   92CC8DD3316F       DB 204, 146, 211, 141, 111, 49, 178, 236, 14, 80, 175, 241, 19, 77, 206
   \              ECB2500EF1AF
   \              4D13CE      
   \   000000A5   72906D2CD133       DB 144, 114, 44, 109, 51, 209, 143, 12, 82, 176, 238, 50, 108, 142, 208
   \              0C8FB05232EE
   \              8E6CD0      
   \   000000B4   0D53B1EFAEF0       DB 83, 13, 239, 177, 240, 174, 76, 18, 145, 207, 45, 115, 202, 148, 118
   \              124CCF91732D
   \              94CA76      
   \   000000C3   AB2817F50849   DB 40, 171, 245, 23, 73, 8, 86, 180, 234, 105, 55, 213, 139, 87, 9, 235
   \              B45669EAD537
   \              578BEB09    
   \   000000D3   36B58A6895D4       DB 181, 54, 104, 138, 212, 149, 203, 41, 119, 244, 170, 72, 22, 233
   \              29CBF47748AA
   \              E916        
   \   000000E1   55B7880B34D6       DB 183, 85, 11, 136, 214, 52, 106, 43, 117, 151, 201, 74, 20, 246, 168
   \              2B6A97754AC9
   \              F614A8      
   \   000000F0   2A7496C84B15       DB 116, 42, 200, 150, 21, 75, 169, 247, 182, 232, 10, 84, 215, 137, 107
   \              F7A9E8B6540A
   \              89D76B      
   \   000000FF   35                 DB 53
     12          0x00,0x5E,0xBC,0xE2,0x61,0x3F,0xDD,0x83,0xC2,0x9C,0x7E,0x20,0xA3,0xFD,0x1F,
0x41,
     13          0x9D,0xC3,0x21,0x7F,0xFC,0xA2,0x40,0x1E,0x5F,0x01,0xE3,0xBD,0x3E,0x60,0x82,
0xDC,
     14          0x23,0x7D,0x9F,0xC1,0x42,0x1C,0xFE,0xA0,0xE1,0xBF,0x5D,0x03,0x80,0xDE,0x3C,
0x62,
     15          0xBE,0xE0,0x02,0x5C,0xDF,0x81,0x63,0x3D,0x7C,0x22,0xC0,0x9E,0x1D,0x43,0xA1,
0xFF,
     16          0x46,0x18,0xFA,0xA4,0x27,0x79,0x9B,0xC5,0x84,0xDA,0x38,0x66,0xE5,0xBB,0x59,
0x07,
     17          0xDB,0x85,0x67,0x39,0xBA,0xE4,0x06,0x58,0x19,0x47,0xA5,0xFB,0x78,0x26,0xC4,
0x9A,
     18          0x65,0x3B,0xD9,0x87,0x04,0x5A,0xB8,0xE6,0xA7,0xF9,0x1B,0x45,0xC6,0x98,0x7A,
0x24,
     19          0xF8,0xA6,0x44,0x1A,0x99,0xC7,0x25,0x7B,0x3A,0x64,0x86,0xD8,0x5B,0x05,0xE7,
0xB9,
     20          0x8C,0xD2,0x30,0x6E,0xED,0xB3,0x51,0x0F,0x4E,0x10,0xF2,0xAC,0x2F,0x71,0x93,
0xCD,
     21          0x11,0x4F,0xAD,0xF3,0x70,0x2E,0xCC,0x92,0xD3,0x8D,0x6F,0x31,0xB2,0xEC,0x0E,
0x50,
     22          0xAF,0xF1,0x13,0x4D,0xCE,0x90,0x72,0x2C,0x6D,0x33,0xD1,0x8F,0x0C,0x52,0xB0,
0xEE,
     23          0x32,0x6C,0x8E,0xD0,0x53,0x0D,0xEF,0xB1,0xF0,0xAE,0x4C,0x12,0x91,0xCF,0x2D,
0x73,
     24          0xCA,0x94,0x76,0x28,0xAB,0xF5,0x17,0x49,0x08,0x56,0xB4,0xEA,0x69,0x37,0xD5,
0x8B,
     25          0x57,0x09,0xEB,0xB5,0x36,0x68,0x8A,0xD4,0x95,0xCB,0x29,0x77,0xF4,0xAA,0x48,
0x16,
     26          0xE9,0xB7,0x55,0x0B,0x88,0xD6,0x34,0x6A,0x2B,0x75,0x97,0xC9,0x4A,0x14,0xF6,
0xA8,
     27          0x74,0x2A,0xC8,0x96,0x15,0x4B,0xA9,0xF7,0xB6,0xE8,0x0A,0x54,0xD7,0x89,0x6B,
0x35};
     28          
     29          //Вычисляет и возвращает crc8

   \                                 In segment CODE, align 2, keep-with-next
     30          void do_crc_8(unsigned char byte, unsigned char *crc8)
   \                     do_crc_8:
     31          {
     32          *crc8=crc_table[(*crc8^byte)];
   \   00000000   ....               LDI     R20, LOW(crc_table)
   \   00000002   ....               LDI     R21, (crc_table) >> 8
   \   00000004   01F9               MOVW    R31:R30, R19:R18
   \   00000006   8160               LD      R22, Z
   \   00000008   E010               LDI     R17, 0
   \   0000000A   2706               EOR     R16, R22
   \   0000000C   0F40               ADD     R20, R16
   \   0000000E   1F51               ADC     R21, R17
   \   00000010   01FA               MOVW    R31:R30, R21:R20
   \   00000012   9104               LPM     R16, Z
   \   00000014   01F9               MOVW    R31:R30, R19:R18
   \   00000016   8300               ST      Z, R16
     33          }
   \   00000018   9508               RET
arttab
это табличный метод (CRC8) - для скорости.
Вот обычный, но на CRC16

WORD CalcCRC(BYTE *pBuff, BYTE n)
{
unsigned char i,carry;
WORD crc16=0xFFFF;
while(n)
{
crc16 ^=*pBuff;
for (i = 0; i < 8; i++)
{
carry = crc16 & 1;
crc16 >>= 1;
if (carry) crc16 ^= 0xA001;
}
n--;
pBuff++;
}
return crc16;
}
вместо WORD пишите int. Опять же это на си.
andrvisht
Держи еще такой вариант.
;------------------- CRC FOR N BYTES
; var in : FSR (pointer to 1-st byte), crc_byte_count (# bytes)
; var out: crc_my
; var local: W, R0, R1
crc_n
clrf crc_my
crc_byte
MOVLF .8,crc_bit_count
movf INDF0,W
movwf R1
crc_bit
xorwf crc_my, W
movwf R0
movlb 0x0F
bcf STATUS,C
movlb 0x00
rrcf R0, W
movf crc_my, W
movlb 0x0F
btfsc STATUS,C
xorlw 18h
movlb 0x00
movwf R0
rrcf R0, W
movwf crc_my
rrcf R1
movf R1, W
decfsz crc_bit_count
goto crc_bit
movlb 0x0F
infsnz FSR0L
incf FSR0H
movlb 0x00
decfsz crc_byte_count
goto crc_byte
return
;------------------- CRC END
Это правда для мелкочипов было, так что movlb можешь игнорировать.
Идея CRC заключается в генерации выходного кода на основе полинома.
так же как в генераторах псевдослучайного воздействия есть наиболее подходящие полиномы дающие наилучьшее кодирование... или наибольший отлов ошибок...
В 8-битном это 0x18
Данный вариант сократит код, но удлинит время обработки.
Pyku_He_oTTyda
А как вручную подсчитать CRC для ключа с номером "00000ССА061Е", на калькуляторе у меня что то не совпало с оригинальнымsad.gif
andrvisht
Цитата(Pyku_He_oTTyda @ Nov 17 2005, 11:56) *
А как вручную подсчитать CRC для ключа с номером "00000ССА061Е", на калькуляторе у меня что то не совпало с оригинальнымsad.gif

1. 00h 00h
2. 00h 00h
3. 0Ch A3h
4. CAh F9h
5. 06h 35h
6. 1Eh 03h

Оригинал то какой ???
и чего они там пишут по поводу начального значения и полинома ?
Pyku_He_oTTyda
CRC ASSEMBLY LANGUAGE PROCEDURE

DO_CRC:
CRC_LOOP:
ZERO:
PUSH ACC
PUSH B
PUSH ACC
MOV B,#8
XRL A,CRC
RRC A
MOV A,CRC
JNC ZERO
XRL A,#18H
RRC A
MOV CRC,A
POP ACC
RR A
PUSH ACC
DJNZ B,CRC_LOOP
POP ACC
POP B
POP ACC
RET
CRC GENERATION

To validate the data transmitted from the DS1990A, the bus master may generate a CRC value from the
data as it is received. This generated value is compared to the value stored in the last eight bits of the
DS1990A. The bus master computes the CRC over the 8-bit family code and all 48 ID number data bits,
but not over the stored CRC value itself. If the two CRC values match, the transmission is error-free.
An example of how to generate the CRC using assembly language software is shown in Table 1. This
assembly language code is written for the DS5000 Soft microcontroller which is compatible with the
8031/51 Microcontroller family. The procedure DO_CRC calculates the cumulative CRC of all the bytes
passed to it in the accumulator. It should be noted that the variable CRC needs to be initialized to 0 before
the procedure is executed. Each byte of the data is then placed in the accumulator and DO-CRC is called
to update the CRC variable. After all the data has been passed to DO_CRC, the variable CRC will contain
the result. The equivalent polynomial function of this software routine is:

CRC = x^8+ x^5+ x^4+ 1
NULL
Есть хорошая статья про CRC. Многое становится понятно.
andrvisht
Ну тогда все верно.
У меня данный код на DS18B20 работает.
И все таки что он вычитывает

код устройства - ?
48 бит ROM - ?
CRC8 - ?
а то проверять не с чем...
PaulS
Цитата(Pyku_He_oTTyda @ Nov 17 2005, 08:59) *
Подскажите, как правильно посчитать на ассемблере контрольную сумму ключа I-BUTTON?

Например так:
ldi tempA,$18
ldi tempC,8 ; Счетчик бит
rk_CRCloop: ;----------------- Вычисление CRC байта --------------
mov tempD,current_byte
eor tempD,tempB
ror tempD
mov tempD,tempB
brcc rk_zero
eor tempD,tempA
rk_zero:
ror tempD
mov tempB,tempD
lsr current_byte
dec tempC
brne rk_CRCloop
rjmp rk_NEXTbyte_loop
Antony Ugolev
CRC8 на С, не табличная версия:

Код
void Update_CRC(char in, char *crc)
{
    #define POLYNOMIAL 0x1D // x^8 + x^4 + x^3 + x^2 + 1
    *crc = *crc ^ in;
    for (unsigned char i=0; i<8; i++)
    {
        *crc = (*crc & 0x80)? (*crc << 1) ^ POLYNOMIAL : (*crc << 1);    
    }
}
Pyku_He_oTTyda
Cпасибо! Буду вечером осмысливать, разбиратся.
Тему не закрываюsmile.gif
попробую вручную получить требуемое значение, потом в код переводить.
Жаль нет готового исходника, апнота например
Pyku_He_oTTyda
&-rey буду премного благодарен!
Ящик cam()mart.ru
В свою очередь обязуюсь выполнять авторские права.
Laksus
Цитата
Подскажите, как правильно посчитать на ассемблере контрольную сумму ключа I-BUTTON?
....
Тему не закрываю...
...
Жаль нет готового исходника, апнота например


А это не поможет:
на сайте http://www.elin.ru/1-Wire/01.htm среди кучи всего,
лежит:
" Основные положения 1-Wire-интерфейса
iButton and MicroLAN Standards. - Основополагающее описание стандарта 1-Wire (Dallas Semiconductor, Engl.), 1,06М, 24.10.99"
вот выдержка из оглавления:
"...
APPENDIX 1 UNDERSTANDING AND USING CYCLIC REDUNDANCY CHECKS WITH...125
iButton PRODUCTS
Introduction
Background
Description Dallas Semiconductor One-Wire CRC
CRC-16 Computation for RAM Records in iButtons
..."
По моему там дается и рассчетный и табличный методы определения CRC. Но сам я к сожалению в этом деле разбираюсь слабо.
2005 11 18
Александр
laksus mail.ru
Pyku_He_oTTyda
Александр, спасибо за ссылку! *.pdf действительно то, что надо.
Вчерашний день прошел зазря, теперь все выходные впередиsmile.gif, буду дальше разбиратся.
add
rolleyes.gif CRC для AVR :


;*****************************************************************************
;* ПРОЦЕДУРА ВЫЧИСЛЕНИЯ 8-БИТНОЙ CRC для микроконтроллеров AVR. *
;*****************************************************************************
; Пример использования:
clr fCRC ; Перед вычислением надо обнулять fCRC.
mov fTEMP,fBYTE1 ; Названия байтов к примеру.
rcall DO_CRC
; В fCRC сейчас находится контрольная сумма байта fBYTE1.
mov fTEMP,fBYTE2
rcall DO_CRC
; В fCRC сейчас находится контрольная сумма байтов fBYTE1 и fBYTE2.
mov fTEMP,fBYTE3
rcall DO_CRC
; В fCRC сейчас находится контрольная сумма байтов fBYTE1, fBYTE2, fBYTE3.
; И так далее.
; 8-битная CRC теряет эффективность при размере пакета более 200 байт.

.def SAVE_W =r16 ;
.def fBIT_CNT =r17 ; Счетчик прочитанных битов.
.def fTEMP =r18 ; Временный регистр только для локального использования.
.def fCRC =r19 ; Контрольная сумма.

; Процедура обновления CRC (циклическая контрольная сумма). Параметр в fTEMP.
DO_CRC:
mov SAVE_W,fTEMP
ldi fBIT_CNT,8
CRC_LOOP:
eor fTEMP,CRC
ror fTEMP
mov fTEMP,CRC
brcc ZERO
ldi CRC,0x18
eor fTEMP,CRC
ZERO:
ror fTEMP
mov CRC,fTEMP
lsr SAVE_W
mov fTEMP,SAVE_W
dec fBIT_CNT
brne CRC_LOOP
ret
;-----------------------------------------------------------------------------

и вот :
;----------------------------------------------------------------
crc_calc: ;вычисляем CRC текущего байта
mov r16,r17
ldi r18,8
crc_loop:
eor r17,r19
ror r17
brcc zero
ldi r17,0x18
eor r19,r17
zero: ror r19
lsr r16
mov r17,r16
dec r18
brne crc_loop
ret
ksv198
Цитата(Pyku_He_oTTyda @ Nov 17 2005, 08:59) *
Подскажите, как правильно посчитать на ассемблере контрольную сумму ключа I-BUTTON?

Вот еще подпрограммка, использовал для подсчета CRC карточек RFID типа EM-Marine:
---------------------------------------------------------------------------------------------------------
;Программы вычисления CRC8 блока памяти начиная с указателя Z
;длиной 7 байт; использует регистры Z, R0
;на выходе CRC8 в temp
CRC8calc:
clr temp
ldi dly3,7 ;счетчик байт
ldi dly1, 0x0C
CRC8_l1:
ld R0, Z+
ldi dly2,8 ;счетчик бит
CRC8_l2:
ror R0
ror temp
brcc CRC8_l3
subi temp, 0x80
CRC8_l3:
brpl CRC8_l4
eor temp, dly1
CRC8_l4:
dec dly2
brne CRC8_l2
dec dly3
brne CRC8_l1
ret

За основу был взят код найденный на просторах Инета, точно уже не помню откуда.
Pyku_He_oTTyda
Благодарю!
Работы предостаточно на выходные скопилось, буду разбиратсяsmile.gif
greg
Привожу пример для Pic 18f452. Проверено на DS1991, DS1994 - работает 100% !
halfdoom
Попросили оптимизировать CRC8 для ИАРа, получилось очень близко к ассемблерной вставке из avr-lib.
Код
/*
* Polynome (X^8 + X^5 + X^4 + 1)
*/
static uint8_t ml_crc_buf2(const void *buf, uint8_t len, uint8_t pat);

uint8_t
ml_crc_buf(const void *buf, uint8_t len)
{
    return ml_crc_buf2(buf, len, 0x8c);
}

#pragma optimize=no_inline
uint8_t
ml_crc_buf2(const void *buf, uint8_t len, uint8_t pat)
{
    const char *bp = buf;
    uint8_t sc, crc = 0, v;

    for (; len; len--) {
        crc ^= *bp++;
        for (sc = 8; sc; sc--) {
            v = crc;
            crc >>= 1;
            if (v & 1)
                crc ^= pat;
        }
    }
    return crc;
}

Результат:
Код
        LDI     R19, 140
        REQUIRE ml_crc_buf2
       ;               // Fall through to label ml_crc_buf2
ml_crc_buf2:
        MOVW    R31:R30, R17:R16
        LDI     R16, 0
        TST     R18
        BREQ    ??ml_crc_buf2_0
??ml_crc_buf2_1:
        LD      R17, Z+
        EOR     R16, R17
        LDI     R17, 8
??ml_crc_buf2_2:
        MOV     R20, R16
        LSR     R16
        BST     R20, 0
        BRTC    ??ml_crc_buf2_3
        EOR     R16, R19
        DEC     R17
        BRNE    ??ml_crc_buf2_2
        DEC     R18
        BRNE    ??ml_crc_buf2_1
??ml_crc_buf2_0:
        RET
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.