Hallo lezers van het CO Forum
Na een tijdje gezocht te hebben naar informatie over CRC heb ik een beetje een idee wat het is. Maar nog niet helemaal en dat om ben ik hier.
Maar laat ik eerst eens zeggen waarvoor ik het nodig heb.
Ik probeer een Crystalfontz display, de CFA635, te Emuleeren(Na apen) met een ATMega32 , een 4*20 lcd'tje en een MAX232.
Dit CFA635 display stuurt en ontvangt pakketjes met een CRC16 controle er bij. Maar hoe kan ik zelf een CRC controlle uit voeren in BasCom.
Ik zag dat er in BasCom een CRC16 comando is maar met welk getal hij dit doet.
Welk getal ik nodig heb is X^16 + X^12 + X^5 + X^0 = 0x8408
Hier nog even de link naar de datasheet van CFA635.
http://www.crystalfontz.com/products/635/data_sheets/CFA635-TMF_v1.4c.…
Ik hoop dat ik helder ben geweest.
Alvast bedankt,
Oscar
Ik weet niet of je hier wat aan hebt, het is in assembly. Ooit eens CRC bereken routines gemaakt. Standaard methode met bitshiften, snelle methode met lookup. 1x lookup tabel genereren op basis van je gewenste polynoom, dan CRC'en maar.
Overigens, de polynoom die je opgeeft is 4129 decimaal.
; =================================================================================================
; Definitions
; =================================================================================================
.include "m128def.inc"
.equ XX = 0
; =================================================================================================
; RAM variabeles
; =================================================================================================
.dseg
.org SRAM_START
CRCLookup: .byte 512
DataStream: .byte 1024
; =================================================================================================
; Interrupt vector table
; =================================================================================================
.cseg
.org 0x0000
RJMP PrgInit ;Reset vector
; =================================================================================================
; Program
; =================================================================================================
.org INT_VECTORS_SIZE ;Start of application area
PrgInit: ;** Setup stack
LDI R16, Low(RAMEND) ;Initialize the stack pointer
OUT SPL, R16
LDI R16, High(RAMEND)
OUT SPH, R16
;** Copy 200 bytes data from ROM to RAM and terminate with 2x 0x00
LDI R24, 200
RCALL PrgInitRAM
;** Generate some CRC with ole bitshifting
LDI XL, Low(DataStream)
LDI XH, High(DataStream)
LDI R24, 202
LDI R23, 0x10
LDI R22, 0x21
RCALL PrgCRC
;** Generate lookup for polynomian
LDI XL, Low(CRCLookup)
LDI XH, High(CRCLookup)
LDI R23, 0x10
LDI R22, 0x21
RCALL PrgLookup
;** Generate some CRC using lookup
LDI XL, Low(DataStream)
LDI XH, High(DataStream)
LDI R24, 202
RCALL PrgCRCLUT
PrgEnd: RJMP PrgEnd
;** Input
;
; XH:XL RAM Pointer
; R24 Byte Count
;
;** Output
;
; R21 CRC High
; R20 CRC Low
;
;** Modifies
; ZH:ZL Lookup address
; R25 0
; R19 Feeder
PrgCRCLUT: CLR R25
LDI R21, 0xFF
LDI R20, 0xFF
PrgCRCLUTLoop: LD R19, X+
LDI ZH, High(CRCLookup)
MOV ZL, R21
LSL ZL
ADC ZH, R25
LD R21, Z+
EOR R21, R20
LD R20, Z+
EOR R20, R19
DEC R24
BRNE PrgCRCLUTLoop
SBIW XH:XL, 0x0002
ST X+, R21
ST X+, R20
RET
;** Input
;
; XH:XL RAM Pointer
; R23 Poly High
; R22 Poly Low
;
;** Modifies
;
; R25 Bit Counter
; R24 Byte Counter
; R21 Intermediate
; R20 Intermediate
; R19 Intermediate
; R18 Intermediate
; R16 Intermediate
PrgLookup: LDI R24, 0
PrgLookupByte: LDI R25, 8
MOV R20, R24
CLR R19
CLR R18
PrgLookupBit: LSL R19
ROL R18
LSL R20
BRCC PrgLookupNoXor
EOR R20, R23
EOR R19, R23
EOR R18, R22
PrgLookupNoXor: DEC R25
BRNE PrgLookupBit
ST X+, R19
ST X+, R18
INC R24
BRNE PrgLookupByte
RET
;** Input
;
; XH:XL RAM Pointer
; R24 Byte Count
; R23 Poly High
; R22 Poly Low
;
;** Output
;
; R21 CRC High
; R20 CRC Low
;
;** Modifies
; R25 Bit counter
; R19 Feeder
PrgCRC: LDI R21, 0xFF
LDI R20, 0xFF
PrgCRCByteLoop: LD R19, X+
LDI R25, 8
PrgCRCBitLoop: LSL R19
ROL R20
ROL R21
BRCC PrgCRCNoXor
EOR R21, R23
EOR R20, R22
PrgCRCNoXor: DEC R25
BRNE PrgCRCBitLoop
DEC R24
BRNE PrgCRCByteLoop
SBIW XH:XL, 0x0002
ST X+, R21
ST X+, R20
RET
PrgInitRAM: LDI ZL, 0x00
LDI ZH, 0x00
LDI XL, Low(DataStream)
LDI XH, High(DataStream)
PrgInitRAMLoop: LPM R16, Z+
ST X+, R16
DEC R24
BRNE PrgInitRAMLoop
LDI R16, 0
ST X+,R16
ST X+,R16
RET
MagicBox bedankt voor de snelle reactie maar ik denk niet dat ik veel aan je code heb, ik progerameer in BasCom. Maar bedankt.
Maar je zou me er erg helpen om deze routine in pseudocode uit te legen of een mischien heb je een goed link (liefst Nederlands) waar goede/duidelijke uitleg staat.
En 0x8408 heb ik direct uit de datasheet getrokken. Maar ik denk dat ze de het in Hex bedoelen.
Groet,
Oscar
Ik heb geen idee van BasCom, ik zou geen vertaling voor je kunnen maken. Het is allemaal bitshift werk wat er moet gebeuren. Het beste zou zijn om een software uitvoering van een hardware matige CRC te maken. Googlen op 'CRC circuit' en je vind ze wel.
Waar je op moet letten is om je reeks bytes af te sluiten met 2x 00h als je gaat genereren. Als je over 100 bytes CRC wil maken, dan je routine over 102 bytes laten gaan waarbij de laatste 2 00h zijn die je er zelf aanplakt.
Die laatste 2 dan vervangen met de gegenereerde code en dat clubje versturen. De ontvanger zal over die reeks van 102 bytes dezelfde routine uitvoeren. De uitkomst zal aan zijn kant weer 2x 00h moeten zijn. Zijn ze dat niet, was er iets fout gegaan tijdens het versturen. Dat is het principe.
Even gezocht voor je op het bascom forum;
Bascom uses &H1021 (dec 4129) as the polynome for it's CRC16 function
Is dat wat je bedoelde?
Dat is de goeie ja. de x16+x12+x5+x0 is de standaard voor telecommunicatie, wordt ook wel CCITT genoemd. Lijkt er op dat je gewoon die BasCom functie gebruiken kan dan.
met deze code bereken je enventueel aan de andere kant (PC) je CRC16 gelijk aan die van Bascom:
misschien heb je daar ook wat aan in latere projectjes die met de PC moeten communiceren, het is in Delphi maar de basis moet wel duidelijk zijn voor iedere andere taal...
procedure DoCRC16(X: Byte);
var
I : Byte;
F : Boolean;
begin
for I := 1 to 8 do begin
F := Odd(X xor CRC16);
CRC16 := CRC16 shr 1;
X := X shr 1;
if F then
CRC16 := CRC16 xor $A001;
end;
end;
en dat is in C++ voor CRC8 van Bascom:
unsigned char Data[9];
Data = {D1,D2,D3,D4,D5,D6,D7,D8,D9};
BYTE j,k,m,x;
BYTE _crc8;
_crc8 = 0;
for(m=1;m<=9;m++)
{
x = Data[m];
for(k=0;k<=7;k++)
{
j = 1 & (x ^ _crc8);
_crc8 = (_crc8 >> 1) & 0xff;
x = (x >> 1) & 0xff;
if (j != 0)
{
_crc8 = _crc8 ^ 0x8C;
}
}
}
crc = _crc8;
}
[Bericht gewijzigd door shortcircuit op (30%)]
Ja BasCom gebruikt inderdaad 4129 als polynoom. Ik heb dat ff gecheckt met deze site. http://www.lammertbies.nl/comm/info/nl_crc-calculation.html?crc=0100&a…)
Maar het debug programma van de Crystalfontz web site geeft Hex169F als CRC over Hex0100 terwijl dit met BasCom en via die site Hex3331 moet zijn.
Hier kan je het debug programma downloaden om het met eigen ogen te zien.
http://www.crystalfontz.com/software/635_WinTest/index.html
Maar ik krijg het idee dat die debug software nog iest anders doet dan allen CRC16.
Dit staat in de datasheet:
"The polynomial used is X16 + X12 + X5 + X0 (0x8408)
The result is bit-wise inverted before being returned."
Maar wat bedoelen ze met bit-wise inverted?
Iedereen bedankt, ik snap nu wel wat CRC is en hoe het werkt,maar nog niet hoe dat display het gebruikt.
Groet,
Oscar
lol ik zie het nu
0x1021 is 0x8408 achterstevoren
0001 0000 0010 0001 = 0x1021
1000 0100 0000 1000 = 0x8408
De reeks wordt gewoon omgedraaid.
Ow oke.
1 0000 1000 0001 0001
Is de Polynoom voor crc-CCITT volgens mij.
Maar wat is dat Bit-wise inverted dan?
Of is dat wat jij bedoelt MagicBox?
Groet,
Oscar
Dat is wat ik bedoelde ja.. die term is een beetje klungelig gekozen van ze daar bitwise inverteren een xor met allemaal 1'en is. 1'tjes worden 0, 0'en worden 1.
Oke dat snap nu.
Maar hoe kommen ze dan aan 169F als ze CRC16 over hex0100 uit voeren. Mischien heb je het Debug programma gedownload. Want daar kan je bij pakket debugger zien hoe de pakketjes zijn op gebouwd en welke crc word mee gestuurt.
De pakketjes zijn zo opgebouwt:
<type><data_length><data><CRC>
Waar type = hex01
Waar data_length = hex00
Waar data = niks en word dus ook niet verstuurt
Dus de string waar de crc over gaat is hex0100 en zou hex3331 als CRC terug moeten geven, maar de software van Crystalfontz geeft hex169F als CRC terug.
Gebruiken ze toch een ander polynoom of doen ze eerst nog wat met de data string voordat ze CRC'en of zie ik wat over het hoofd?
Groet,
Oscar