Как вычислять контрольную сумму - CRC8 CRC16 ?
- avr123.nm.ru
- Вечно гонимый
- Сообщения: 331
- Зарегистрирован: Пн сен 04, 2006 20:25:28
- Откуда: самоучитель по микроконтроллерам
- Контактная информация:
Как вычислять контрольную сумму - CRC8 CRC16 ?
подскажите как вычислять контрольную сумму - CRC8 и CRC16 ?
- avr123.nm.ru
- Вечно гонимый
- Сообщения: 331
- Зарегистрирован: Пн сен 04, 2006 20:25:28
- Откуда: самоучитель по микроконтроллерам
- Контактная информация:
- xelos
- Потрогал лапой паяльник
- Сообщения: 336
- Зарегистрирован: Пн мар 20, 2006 13:05:08
- Контактная информация:
на С# - я писал расчет СRС16 - переложить на С, проблем не должно составить.
полином не помню откуда я взял.
полином не помню откуда я взял.
- Вложения
-
- crc.c
- (4.02 КБ) 1893 скачивания
Я просто верю в то, что рушить догмы - лучший способ не стареть.
- avr123.nm.ru
- Вечно гонимый
- Сообщения: 331
- Зарегистрирован: Пн сен 04, 2006 20:25:28
- Откуда: самоучитель по микроконтроллерам
- Контактная информация:
- avr123.nm.ru
- Вечно гонимый
- Сообщения: 331
- Зарегистрирован: Пн сен 04, 2006 20:25:28
- Откуда: самоучитель по микроконтроллерам
- Контактная информация:
Вот написал CRC на Си в CVAVR и симуляция в VMLAB. Таблично и быстро.
- Вложения
-
- CRC_Tabl_Fast.rar
- (23.36 КБ) 1785 скачиваний
- tych
- Э...
- Сообщения: 2792
- Зарегистрирован: Ср апр 04, 2007 08:39:14
- Откуда: Москва
- Контактная информация:
Вот посмотри - там и время выполнения я указал.
- Вложения
-
- CRC16 табличный atmega64.rar
- (2.4 КБ) 1021 скачивание
Думайте сами, решайте сами ... а вот он-лайн перевод на корявый русский http://translate.ru
- romeuz
- Первый раз сказал Мяу!
- Сообщения: 20
- Зарегистрирован: Пт июл 28, 2006 13:28:14
- Откуда: Москва
- Контактная информация:
Ну вот, собственно, то что было нужно... Может кому пригодится...
- Вложения
-
- crc16_8005_ffff.asm
- CRC16, табличный метод
- (8.57 КБ) 907 скачиваний
- Lonleystranger
- Потрогал лапой паяльник
- Сообщения: 361
- Зарегистрирован: Ср янв 21, 2009 00:45:33
CRC-8 tiny2313
Прочитав тему http://www.radiokot.ru/articles/13/ -спасибо автору
!написал интерфейсик, все работает кроме CRC...В статье указан код на MCS-51:
DO_CRC:
PUSH ACC ; сохраняем аккумулятор
PUSH B ; сохраняем регистр В
PUSH ACC ; сохраняем байт данных
MOV B, #8 ; кол-во битов (счетчик циклов)
CRC_LOOP:
XRL A, CRC ; XOR с предыдущим значением контрольной суммы
RRC A ; сдвиг вправо через флаг переноса
MOV A, CRC ; берем последнее значение CRC
JNC ZERO ; переход, если не было переноса
XRL A, #18H ; обновляем значение CRC путем XOR с константой
ZERO:
RRC A ; снова сдвигаем CRC
MOV CRC, A ; сохраняем новое значение CRC
POP ACC ; восстанавливаем байт данных
RR A ; циклически сдвигаем вправо
PUSH ACC ; снова сохраняем значение
DJNZ B, CRC_LOOP ; повторяем цикл 8 раз (для каждого бита)
POP ACC ; очищаем стек
POP B ; восстанавливаем прежние значения регистров из стека
POP ACC
RET ; завершение процедуры
Я переделал его на AVR ASM
DO_CRC:
PUSH DURATION ; сохраняем аккумулятор
PUSH TEMP2 ; сохраняем регистр В
PUSH DURATION ; сохраняем байт данных
ldi TEMP2, 8 ; кол-во битов (счетчик циклов)
CRC_LOOP:
eor TEMP, CRC ; XOR с предыдущим значением контрольной суммы
ROR TEMP ; сдвиг вправо через флаг переноса
MOV TEMP, CRC ; берем последнее значение CRC
BRCC ZERO ; переход, если не было переноса
ldi exper,0x18
eor TEMP, exper ; обновляем значение CRC путем XOR с константой
ZERO:
ROR TEMP ; снова сдвигаем CRC
MOV CRC, TEMP ; сохраняем новое значение CRC
POP DURATION ; восстанавливаем байт данных
LSR TEMP ; циклически сдвигаем вправо
PUSH DURATION ; снова сохраняем значение
dec TEMP2
brne CRC_LOOP ; повторяем цикл 8 раз (для каждого бита)
POP DURATION ; очищаем стек
POP TEMP2 ; всстанавливаем прежние значения регистров из стека
POP DURATION
RET ; завершение процедуры
Но где-то ошибка...Ввожу номер 1990 iButton'a 8-ми байтовый (с CRC включительно), а 0 не получаю...
Помогите пожалуйста-где я ошибся?
!написал интерфейсик, все работает кроме CRC...В статье указан код на MCS-51:
DO_CRC:
PUSH ACC ; сохраняем аккумулятор
PUSH B ; сохраняем регистр В
PUSH ACC ; сохраняем байт данных
MOV B, #8 ; кол-во битов (счетчик циклов)
CRC_LOOP:
XRL A, CRC ; XOR с предыдущим значением контрольной суммы
RRC A ; сдвиг вправо через флаг переноса
MOV A, CRC ; берем последнее значение CRC
JNC ZERO ; переход, если не было переноса
XRL A, #18H ; обновляем значение CRC путем XOR с константой
ZERO:
RRC A ; снова сдвигаем CRC
MOV CRC, A ; сохраняем новое значение CRC
POP ACC ; восстанавливаем байт данных
RR A ; циклически сдвигаем вправо
PUSH ACC ; снова сохраняем значение
DJNZ B, CRC_LOOP ; повторяем цикл 8 раз (для каждого бита)
POP ACC ; очищаем стек
POP B ; восстанавливаем прежние значения регистров из стека
POP ACC
RET ; завершение процедуры
Я переделал его на AVR ASM
DO_CRC:
PUSH DURATION ; сохраняем аккумулятор
PUSH TEMP2 ; сохраняем регистр В
PUSH DURATION ; сохраняем байт данных
ldi TEMP2, 8 ; кол-во битов (счетчик циклов)
CRC_LOOP:
eor TEMP, CRC ; XOR с предыдущим значением контрольной суммы
ROR TEMP ; сдвиг вправо через флаг переноса
MOV TEMP, CRC ; берем последнее значение CRC
BRCC ZERO ; переход, если не было переноса
ldi exper,0x18
eor TEMP, exper ; обновляем значение CRC путем XOR с константой
ZERO:
ROR TEMP ; снова сдвигаем CRC
MOV CRC, TEMP ; сохраняем новое значение CRC
POP DURATION ; восстанавливаем байт данных
LSR TEMP ; циклически сдвигаем вправо
PUSH DURATION ; снова сохраняем значение
dec TEMP2
brne CRC_LOOP ; повторяем цикл 8 раз (для каждого бита)
POP DURATION ; очищаем стек
POP TEMP2 ; всстанавливаем прежние значения регистров из стека
POP DURATION
RET ; завершение процедуры
Но где-то ошибка...Ввожу номер 1990 iButton'a 8-ми байтовый (с CRC включительно), а 0 не получаю...
Помогите пожалуйста-где я ошибся?
- nictrace
- Мучитель микросхем
- Сообщения: 492
- Зарегистрирован: Вс янв 11, 2009 09:29:08
- Откуда: Ярославль
- Контактная информация:
Обзор нетабличных методов для CRC8
Хе-хе... Кого-то энта тема интересовала и до меня
Вот пример реализации CRC8 на Си из AppNotes:
Так скажем - неплохо, но можно лучше!
А что же на ассемблере?
Вот отсюда - http://avr-asm.tripod.com/dallas1.html я извлек следующий алгоритм:
Буэээ... Мерзость!
Самое смешное, что этот код, к тому же не без ошибок, был раскопирован во множество проектов!
На Коте вот что нашел:
Вроде, ничего, но уж больно код плохо читается! Короче, подумал и придумал собственный алгоритм:
Как это ни странно, программа выдает те же результаты, что и предыдущие
Вот пример реализации CRC8 на Си из AppNotes:
Код: Выделить всё
unsigned char OWI_ComputeCRC8(unsigned char inData, unsigned char seed)
{
unsigned char bitsLeft;
unsigned char temp;
for (bitsLeft = 8; bitsLeft > 0; bitsLeft--)
{
temp = ((seed ^ inData) & 0x01);
if (temp == 0)
{
seed >>= 1;
}
else
{
seed ^= 0x18;
seed >>= 1;
seed |= 0x80;
}
inData >>= 1;
}
return seed;
}
Так скажем - неплохо, но можно лучше!
А что же на ассемблере?
Вот отсюда - http://avr-asm.tripod.com/dallas1.html я извлек следующий алгоритм:
Код: Выделить всё
CRCGEN:
PUSH R1
LDI R20,8
LDI R18,0x18
PUSH R1
CRC_L: lds R3,CRC
EOR R1,R3
ROR R1
MOV R1,R3
BRCC ZERO
EOR R1,R18
ZERO: ROR R1
sts CRC,R1
POP R1
SEC
SBRS R1,0
CLC
ROR R1
PUSH R1
DEC R20
BRNE CRC_L
POP R1
POP R1
RET
Буэээ... Мерзость!
Самое смешное, что этот код, к тому же не без ошибок, был раскопирован во множество проектов!
На Коте вот что нашел:
Код: Выделить всё
_w1_dow_crc8:
clr r30
ld r24,y
tst r24
breq __w1_dow_crc83
ldi r22,0x18
ldd r26,y+1
clr r27
__w1_dow_crc80:
ldi r25,8
ld r31,x+
__w1_dow_crc81:
mov r23,r31
eor r23,r30
ror r23
brcc __w1_dow_crc82
eor r30,r22
__w1_dow_crc82:
ror r30
lsr r31
dec r25
brne __w1_dow_crc81
dec r24
brne __w1_dow_crc80
__w1_dow_crc83:
adiw r28,2
ret
Вроде, ничего, но уж больно код плохо читается! Короче, подумал и придумал собственный алгоритм:
Код: Выделить всё
crc_go2:
ldi mask,0x8C ; полином
clr crc ; вначале был 0
loc1: lpm ; data - в r0
adiw ZL,1 ; может быть на границе блока
ldi bits,8
eor crc,r0
loc2: lsr crc ; left shift
brcc loc3
eor crc,mask
loc3: dec bits
brne loc2
dec buflen
brne loc1 ; do next byte
ret
Как это ни странно, программа выдает те же результаты, что и предыдущие
Хорошие примеры на C для CRC8, 16, 32
http://ru.wikipedia.org/wiki/CRC16
http://ru.wikipedia.org/wiki/CRC16
- Lonleystranger
- Потрогал лапой паяльник
- Сообщения: 361
- Зарегистрирован: Ср янв 21, 2009 00:45:33
Совершенно ничего не понимаю! Взял оригинальный код из crc16.h
#include <util>
// Dallas iButton test vector.
uint8_t serno[] = { 0x02, 0x1c, 0xb8, 0x01, 0, 0, 0, 0xa2 };
int
checkcrc(void)
{
uint8_t crc = 0, i;
for (i = 0; i < sizeof serno / sizeof serno[0]; i++)
crc = _crc_ibutton_update(crc, serno[i]);
return crc; // must be 0
}
main (void)
{
checkcrc();
return (0);
}
откомпилировал, залез в отладчик,
E6E0 LDI R30,0x60 Load immediate
+00000042: E0F0 LDI R31,0x00 Load immediate
+00000043: E090 LDI R25,0x00 Load immediate
+00000044: 9181 LD R24,Z+ Load indirect and postincrement
+00000045: 2798 EOR R25,R24 Exclusive OR
+00000046: E028 LDI R18,0x08 Load immediate
+00000047: E88C LDI R24,0x8C Load immediate
+00000048: FB90 BST R25,0 Bit store from register to T
+00000049: 9596 LSR R25 Logical shift right
+0000004A: F40E BRTC PC+0x02 Branch if T flag cleared
+0000004B: 2798 EOR R25,R24 Exclusive OR
+0000004C: 952A DEC R18 Decrement
+0000004D: F7D1 BRNE PC-0x05 Branch if not equal
+0000004E: E080 LDI R24,0x00 Load immediate
+0000004F: 36E8 CPI R30,0x68 Compare with immediate
+00000050: 07F8 CPC R31,R24 Compare with carry
+00000051: F791 BRNE PC-0x0D
начал отладку, да, тот код,что указан дает в регистре R25 ноль, вставляю свой в ОЗУ- не работает!
Я просто в диком архишоке!
Единственное различие - идентификатор устройства в примере 02, а у меня DS1990 т.е 01.....
код из статьи http://ru.wikipedia.org/wiki/CRC16
unsigned char Crc8(unsigned char *pcBlock, unsigned char len)
{
unsigned char crc = 0xFF;
unsigned char i;
while (len--)
{
crc ^= *pcBlock++;
for (i = 0; i < 8; i++)
crc = crc & 0x80 ? (crc << 1) ^ 0x31 : crc << 1;
}
return crc;
}
Вообще выдает непонятно что...
#include <util>
// Dallas iButton test vector.
uint8_t serno[] = { 0x02, 0x1c, 0xb8, 0x01, 0, 0, 0, 0xa2 };
int
checkcrc(void)
{
uint8_t crc = 0, i;
for (i = 0; i < sizeof serno / sizeof serno[0]; i++)
crc = _crc_ibutton_update(crc, serno[i]);
return crc; // must be 0
}
main (void)
{
checkcrc();
return (0);
}
откомпилировал, залез в отладчик,
E6E0 LDI R30,0x60 Load immediate
+00000042: E0F0 LDI R31,0x00 Load immediate
+00000043: E090 LDI R25,0x00 Load immediate
+00000044: 9181 LD R24,Z+ Load indirect and postincrement
+00000045: 2798 EOR R25,R24 Exclusive OR
+00000046: E028 LDI R18,0x08 Load immediate
+00000047: E88C LDI R24,0x8C Load immediate
+00000048: FB90 BST R25,0 Bit store from register to T
+00000049: 9596 LSR R25 Logical shift right
+0000004A: F40E BRTC PC+0x02 Branch if T flag cleared
+0000004B: 2798 EOR R25,R24 Exclusive OR
+0000004C: 952A DEC R18 Decrement
+0000004D: F7D1 BRNE PC-0x05 Branch if not equal
+0000004E: E080 LDI R24,0x00 Load immediate
+0000004F: 36E8 CPI R30,0x68 Compare with immediate
+00000050: 07F8 CPC R31,R24 Compare with carry
+00000051: F791 BRNE PC-0x0D
начал отладку, да, тот код,что указан дает в регистре R25 ноль, вставляю свой в ОЗУ- не работает!
Я просто в диком архишоке!
Единственное различие - идентификатор устройства в примере 02, а у меня DS1990 т.е 01.....
код из статьи http://ru.wikipedia.org/wiki/CRC16
unsigned char Crc8(unsigned char *pcBlock, unsigned char len)
{
unsigned char crc = 0xFF;
unsigned char i;
while (len--)
{
crc ^= *pcBlock++;
for (i = 0; i < 8; i++)
crc = crc & 0x80 ? (crc << 1) ^ 0x31 : crc << 1;
}
return crc;
}
Вообще выдает непонятно что...
- mr.Kirill
- Мучитель микросхем
- Сообщения: 438
- Зарегистрирован: Вт сен 25, 2007 19:40:26
- Откуда: Челябинск
Lonleystranger писал(а):Совершенно ничего не понимаю!...
...
Вообще выдает непонятно что...
Прежде всего - научитесь правильно оформлять код программы, который вставляете в пост!
Чем не понравился результат кода crc8 по ссылке?
http://ru.wikipedia.org/wiki/CRC16
Сам его не раз применял, все работает как положено. В чем у Вас проблема?
- nictrace
- Мучитель микросхем
- Сообщения: 492
- Зарегистрирован: Вс янв 11, 2009 09:29:08
- Откуда: Ярославль
- Контактная информация:
Re: CRC-8 tiny2313
Lonleystranger писал(а):
ROR TEMP ; сдвиг вправо через флаг переноса
MOV TEMP, CRC ; берем последнее значение CRC
BRCC ZERO ; переход, если не было переноса
Но где-то ошибка...Ввожу номер 1990 iButton'a 8-ми байтовый (с CRC включительно), а 0 не получаю...
Помогите пожалуйста-где я ошибся?
А ошибка в выделенном куске. Нельзя тупо копировать код, вы же с чужого языка не дословно предложение переводите?
Команда МОV обнуляет флаг С!
Возьмите мой код - чуть выше по ветке. Он значительно короче и работает!
- Lonleystranger
- Потрогал лапой паяльник
- Сообщения: 361
- Зарегистрирован: Ср янв 21, 2009 00:45:33
Спасибо всем за понимание и советы, в результате все-таки взял CRC16.H (спасибо ARV), откомпилировал, взял из бугера код, вставил как ASM, подредактировал немного (спасибо nictrace за дельные советы и код), вот что получилось:
Все работает, УРА!А раньше скорее всего просто не учел переносов из WinASM в AVRStudio...
Код: Выделить всё
Do_Crc:
EOR CRC,temp ;Exclusive OR
LDI R18,0x08 ;Load immediate
LDI temp,0x8C ;Load immediate
BST CRC,0 ;Bit store from register to T
LSR CRC ;Logical shift right
BRTC PC+0x02 ;Branch if T flag cleared
EOR CRC,temp ;Exclusive OR
DEC R18 ;Decrement
BRNE PC-0x05 ;Branch if not equal
LDI temp,0x00 ;Load immediate
ret
Все работает, УРА!А раньше скорее всего просто не учел переносов из WinASM в AVRStudio...
Re: CRC-8 tiny2313
nictrace писал(а):...
Команда МОV обнуляет флаг С!
...
А вот этого не надо, команда mov не воздействует на флаги результата.