чего-то никак не въеду в CRC, вроде всё понятно, но правильного значения не получается. Где ошибаюсь? CRC16 CCITT (полином 0x1021)
инициализирующее значение 0xFFFF, финализирующее - нулевое
тестовый ряд - стандартный 1 2 3 4 5 6 7 8 9 (т.е. 0x31 0x32 0x33 0x34 0x35 0x36 0x37 0x38 0x39)
должно быть значение CRC 0x29B1, получается 0xE5CC
(немного переосмыслил теорию, но всё равно, один фиг - не считает правильно)
Алгоритм примерно такой:
Стартовое значение CRC-0xFFFF
установим счётчик бит в 7
A: побайтно(на самом деле побитно) вдвигаем справа в CRC-регистр вектор данных (старшими битами вперёд) (lsl DATA; rol CRC0; rol CRC1)
если выдвинутый в "carry" бит = 1, то XOR CRC регистра и полинома, если =0, ничего не делаем
счётчик бит --
если счётчик бит <0 (carry), то уходим (EXIT), иначе повтопяем итерации (jmp A)
EXIT: финализируем CRC регистр (дополняем вектор данных ещё двумя нулевыми байтами, считаем CRC)
Ассемблерный код примерно такой:
call CRC_INIT
ldi TMP,'1'
call CRC16_update
ldi TMP,'2'
call CRC16_update
ldi TMP,'3'
call CRC16_update
ldi TMP,'4'
call CRC16_update
ldi TMP,'5'
call CRC16_update
ldi TMP,'6'
call CRC16_update
ldi TMP,'7'
call CRC16_update
ldi TMP,'8'
call CRC16_update
ldi TMP,'9'
call CRC16_update
;
call CRC16_FINALIZE
;----------------------------------------------------------------------
CRC_INIT:
#define CRC16_INIT_Const 0xFFFF
ldi TMP,BYTE1(CRC16_INIT_Const)
sts S_CRC_byte0,TMP
ldi TMP,BYTE2(CRC16_INIT_Const)
sts S_CRC_byte1,TMP
ret
;-----------------------------------------
CRC16_FINALIZE:
#define CRC16_FINALIZE_Const 0x0000
clr TMP ;дополняем обсчитываемое сообщение "нулями" в длину полинома (16 бит)
call CRC16_update
clr TMP
call CRC16_update
;
ldi TMP2,low(CRC16_FINALIZE_Const) ;XORим результат с финализируещей константой
lds TMP,S_CRC_byte0
eor TMP,TMP2
sts S_CRC_byte0,TMP
ldi TMP2,high(CRC16_FINALIZE_Const)
lds TMP,S_CRC_byte1
eor TMP,TMP2
sts S_CRC_byte1,TMP
ret
;-----------------------------------------
#define CRC_polynom 0x1021
;CRC16 - CCITT (XMODEM)
;
;Test string: '123456789' (0x031,0x032,0x033,0x034,0x035,0x036,0x037,0x038,0x039)
;Result: 0x29b1
;
;
;TMP, TMP2, Y
;В TMP лежат исходные данные (подсчитываемый байт данных)
CRC16_update:
LDX CRC_polynom ;Полином для операции XOR-SHIFT
lds YL,S_CRC_byte0 ;Загрузим в "Y" текущее значение байт результата CRC
lds YH,S_CRC_byte1
;
ldi TMP2,7 ;В TMP2 организуем счётчик бит для операций сдвига байта исходных данных
;В TMP на данный момент лежат исходные данные (подсчитываемый байт данных)
CRC_Count:
lsl TMP ;Задвигаем побитно данные в CRC-регистр (Y).
rol YL
rol YH
brcc CRC_CheckByteEnd ;Если "выдвинутый" из CRC-регистра бит - нулевой, то проверяем, не закончились ли биты в байте входных данных
eor YL,XL ; иначе считаем, что выдвинулась "1", сл-но нужно поXORить CRC регистр с полиномом
eor YH,XH ; (!! важный момент, - так как выдвинутая "1" "потерялась", но у полинома старший (17-й) бит = "1"
; то это совершенно неважно. т.к. XOR выдвинутой "1" и старшего бита полинома даст "0")
CRC_CheckByteEnd:
subi TMP2,1 ;Проверяем счётчик бит (сдвигов) для исходного байта данных
brcc CRC_Count ; продолжаем цикл подсчёта CRC, если не все разряды исходного байта просмотрены.
;
sts S_CRC_byte0,YL ;Если просмотрели все разряды исходного байта, то сохраняем результат
sts S_CRC_byte1,YH
ret
где собака зарыта ??