PDA

Ver la Versión Completa : calculo de CRC Xmodem


emeceuy
09-10-2008, 14:07:20
Estimados, hola !

Les comento el GRAN :o problema que tengo ! Estoy trabajando con una aplicación que envia datos a un dispositivo a través de un puerto serial. El problema es que cada cadena de datos que se le envía tiene al final 2 bytes de CRC.

Para un dispositivo que usa CRC-16 confeccioné un procedimiento (que no será eficiente, pero funciona) y calcula muy bien el CRC ! El problema es que al comunicarme con otro tipo de dispositivo que usa CRC-16 XMODEM no funciona ! y creo que la unica diferencia que hay es el polinomio generador.

Como me di cuenta que CRC utiliza cada dispositivo? en esta página: http://www.lammertbies.nl/comm/info/crc-calculation.html?crc=02+A5&method=hex

Entonces, que puede ser? Tres posibilidades:

1. Agrego abajo el codigo que utilizo por si alguien lo quiere analizar y capaz que ven algun error.
2. Alguien conoce algun lugar de donde descargar una funcion que se le pueda pasar un string de datos y devuelva su CRC 16 XMODEM?
3. He visto varias funciones en internet, pero están en "C", hay manera de utilizarlas en delphi? (como se puede hacer con Assembler, por ejemplo)?

Muchisimas gracias desde ya ! salu2 !


procedure fCalculaCRC;

// FUNCIONES AUXILIARES

function ComparaXOR(Datos1,Datos2: string):string;
var vloop:integer;
vbol1,vbol2:boolean;
begin
if length(Datos1)<>length(Datos2) then showmessage('Error');
for vloop:=1 to length(Datos2) do
begin
if Datos1[vloop]='1' then vbol1:=true else vbol1:=false;
if Datos2[vloop]='1' then vbol2:=true else vbol2:=false;
if vbol1 xor vbol2 then result[vloop]:='1' else result[vloop]:='0';
end;
result:=trim(result);
end;

function EliminaMSB(Datos:string):string;
begin
EliminaMSB:=trim(copy(Datos,2,999));
end;

function ProximoDato:string;
begin
if length(vBinario)>0 then ProximoDato:=vBinario[1]
else
begin
ProximoDato:='0';
showmessage('Error');
end;
vBinario:=trim(copy(vBinario,2,999));
end;

function Invierte(Datos: string):string;
var vloop:integer;
begin
for vloop:=1 to length(Datos) do result[vloop]:=Datos[length(Datos)+1-vloop];
result:=trim(result);
end;

// AQUI COMIENZA LA FUNCION PROPIAMENTE DICHA

begin
vBinario:='';
for vloop:=0 to length(pDatos)-1 do vBinario:=vBinario+Invierte(inttobin(pDatos[vloop]));

vGenerador:='10001000000100001';
vCeros:='00000000000000000';

vBinario:=vBinario+copy(vCeros,1,length(vCeros)-1); // 16 bits por el CRC-16

vLargoDAT:=length(vBinario);
vLargoGEN:=length(vGenerador);
setlength(mCRC,0,0);
setlength(mCRC,vLargoDAT-vLargoGEN+10,17);

vResultado:='X'+copy(vBinario,1,vLargoGEN-1);
vBinario:=trim(copy(vBinario,vLargoGEN,999));

repeat
begin
vDividendo:=EliminaMSB(vResultado)+ProximoDato;
if vDividendo[1]='1' then vDivisor:=vGenerador else vDivisor:=vCeros;

vResultado:=DATparaXOR(vDividendo,vDivisor);

if vResultado[1]='1' then showmessage('Error, MSB del resultado es "1"');
end
until length(vBinario)=0;

vResultado:=Invierte(EliminaMSB(vResultado));

vCRCH:=bintoint(copy(vresultado,9,8));
vCRCL:=bintoint(copy(vresultado,1,8));

vCaracteres:=vCaracteres+char(vCRCH)+char(vCRCL);
end;