Es capaz de utilizar cualquier CRC aunque he probado los normalizados.
Existe en la base de conocimientos un texto sobre el uso de estos códigos
'---------------------------------------------------------------------
' función que calcula el CRC de un mensaje.
' Parámetros de entrada:
' Mensaje --> El mensaje.
' Polinomio --> Polinomio generador. en formato hexadecimal
' CheckCrc --> Si se da es porque se desea comprobar. En este caso
' el resultado debe ser cero
' Salida:
' Crc --> El crc calculado en formato string-binario o si era una
' comprobación devolverá 0 si es correcto y otra cosa si no
' lo es
' ---------------------------------------------------------------------------------------------------
PUBLIC FUNCTION CalcularCrc(Mensaje AS String, Polinomio AS String, OPTIONAL CheckCrc AS String) AS String
DIM GradoPolinomio AS Integer, Resto AS String, ElCrc AS String
'Quitar al polinomio los ceros no significativos a la izquierda
Polinomio = QuitarCerosPolinomio(Polinomio)
'El polinomio se recibe en hexadecimal. Convertirlo a binario
Polinomio = ConvertirABin(Polinomio)
'Obtener el grado del polinomio
GradoPolinomio = ObtenerGradoPolinomio(Polinomio) 'Obtener el grado del polinomio generador
IF CheckCrc THEN
'anexar el crc a comprobar
Mensaje &= CheckCrc
ELSE
'Agregar tantos ceros a la derecha al mensaje como sea el grado del polinomio
Mensaje = AgregarCeros(Mensaje, GradoPolinomio)
ENDIF
'Obtener resultado
resto = DividirModuloDos(Mensaje, polinomio) 'efectuar división binaria
Elcrc = Right(resto, GradoPolinomio)
RETURN ElCrc
END
' función que calcula el CRC de un mensaje.
' Parámetros de entrada:
' Mensaje --> El mensaje.
' Polinomio --> Polinomio generador. en formato hexadecimal
' CheckCrc --> Si se da es porque se desea comprobar. En este caso
' el resultado debe ser cero
' Salida:
' Crc --> El crc calculado en formato string-binario o si era una
' comprobación devolverá 0 si es correcto y otra cosa si no
' lo es
' ---------------------------------------------------------------------------------------------------
PUBLIC FUNCTION CalcularCrc(Mensaje AS String, Polinomio AS String, OPTIONAL CheckCrc AS String) AS String
DIM GradoPolinomio AS Integer, Resto AS String, ElCrc AS String
'Quitar al polinomio los ceros no significativos a la izquierda
Polinomio = QuitarCerosPolinomio(Polinomio)
'El polinomio se recibe en hexadecimal. Convertirlo a binario
Polinomio = ConvertirABin(Polinomio)
'Obtener el grado del polinomio
GradoPolinomio = ObtenerGradoPolinomio(Polinomio) 'Obtener el grado del polinomio generador
IF CheckCrc THEN
'anexar el crc a comprobar
Mensaje &= CheckCrc
ELSE
'Agregar tantos ceros a la derecha al mensaje como sea el grado del polinomio
Mensaje = AgregarCeros(Mensaje, GradoPolinomio)
ENDIF
'Obtener resultado
resto = DividirModuloDos(Mensaje, polinomio) 'efectuar división binaria
Elcrc = Right(resto, GradoPolinomio)
RETURN ElCrc
END
La función previa hace dos cosas. Una es recibir como parámetros el mensaje sobre el que calcular el CRC y el polinomio a utilizar. En este caso calcula el CRC correspondiente.
La segunda cosa es comprobar un CRC manualmente. En este caso la función recibe el mensaje, el polinomio y el CRC a comprobar. En este caso la función retornará 0 si el CRC es correcto y otra cosa si el CRC no es correcto.
Esta es la función que calcula la división entera de dos polinomios. Existe un texto en la base de conocimientos que explica su funcionamiento.
'función que realiza la división entera de dos polinomios
' par ámetros de entrada:
' Dividendo - - > polinomio a dividir
' Divisor - - > polinomio divisor
' Salida:
' El resto de la división
PRIVATE FUNCTION DividirModuloDos(Dividendo AS String, Divisor AS String) AS String
DIM PosIni AS Integer = 1 'en un string de bytes posini indica el primer bit que debe ser xoreado si toca hacerlo
DIM Resto AS String = dividendo, NumDivisiones AS Integer = Len(Dividendo) - Len(divisor)
DO WHILE PosIni < NumDivisiones
'si el primer bit es 1 dividir y quedarse con el resto
IF Mid(Resto, PosIni, 1) = "1" THEN 'Si el primer dígito a operar es 1 y por tanto hay que hacer xor
resto = hacerxor(resto, divisor, posini) 'Hacer XOR a bits correspondientes y obtener el resultado
ENDIF
INC PosIni
LOOP 'ir a siguiente bit que tendrá que ser operado para xor si corresponde
RETURN resto 'devolver el resto de la división
END
' par ámetros de entrada:
' Dividendo - - > polinomio a dividir
' Divisor - - > polinomio divisor
' Salida:
' El resto de la división
PRIVATE FUNCTION DividirModuloDos(Dividendo AS String, Divisor AS String) AS String
DIM PosIni AS Integer = 1 'en un string de bytes posini indica el primer bit que debe ser xoreado si toca hacerlo
DIM Resto AS String = dividendo, NumDivisiones AS Integer = Len(Dividendo) - Len(divisor)
DO WHILE PosIni < NumDivisiones
'si el primer bit es 1 dividir y quedarse con el resto
IF Mid(Resto, PosIni, 1) = "1" THEN 'Si el primer dígito a operar es 1 y por tanto hay que hacer xor
resto = hacerxor(resto, divisor, posini) 'Hacer XOR a bits correspondientes y obtener el resultado
ENDIF
INC PosIni
LOOP 'ir a siguiente bit que tendrá que ser operado para xor si corresponde
RETURN resto 'devolver el resto de la división
END
Esta es la función que realiza XOR bit a bit entre dos string
'función que realiza xor de GradoPolinomio bits en los datos a partir del bit indicado en PosIni
PRIVATE FUNCTION hacerxor(Resto AS String, Divisor AS String, PosIni AS Integer) AS String
DIM contador AS Integer, s AS String 's=resultado de la operación tras el xor
DIM ByteResto AS String, ByteDivisor AS String, ByteResultado AS Byte
'Incluir en el resultado los bytes de la izquierda que no voy a xorear.
s = Left(Resto, PosIni - 1)
'Los bytes que voy a xorear son siempre left(Resto,Len(divisor) + PosIni - 1)
FOR contador = 1 TO Len(Divisor) 'recorrer los bits a operar
byteResto = Mid(Resto, PosIni + Contador - 1, 1)
byteDivisor = Mid(Divisor, Contador, 1)
ByteResultado = IIf(byteResto = byteDivisor, 0, 1)
s &= CStr(ByteResultado) 'almacenar resultado
NEXT
'Los restantes son siempre mid(Resto,len(divisor)+PosIni) y no van a ser operados en este cicle
s &= Mid(Resto, Len(divisor) + PosIni) 'añadir los bits que no he xoreado
RETURN s
END
PRIVATE FUNCTION hacerxor(Resto AS String, Divisor AS String, PosIni AS Integer) AS String
DIM contador AS Integer, s AS String 's=resultado de la operación tras el xor
DIM ByteResto AS String, ByteDivisor AS String, ByteResultado AS Byte
'Incluir en el resultado los bytes de la izquierda que no voy a xorear.
s = Left(Resto, PosIni - 1)
'Los bytes que voy a xorear son siempre left(Resto,Len(divisor) + PosIni - 1)
FOR contador = 1 TO Len(Divisor) 'recorrer los bits a operar
byteResto = Mid(Resto, PosIni + Contador - 1, 1)
byteDivisor = Mid(Divisor, Contador, 1)
ByteResultado = IIf(byteResto = byteDivisor, 0, 1)
s &= CStr(ByteResultado) 'almacenar resultado
NEXT
'Los restantes son siempre mid(Resto,len(divisor)+PosIni) y no van a ser operados en este cicle
s &= Mid(Resto, Len(divisor) + PosIni) 'añadir los bits que no he xoreado
RETURN s
END
Esta es la función que sirve para multiplicar un polinomio por X. Lo que se hace es añadir X ceros por la derecha.
Esta es la función que recibe un polinomio y calcula su grado. Deben haberse eliminado previamente los bits no significativos (ceros a la izquierda)
Esta es la función que recibe un polinomio y le quita los bits no significativos (quita los ceros a la izquierda)
Esta es la función que recibe un polinomio en formato hexadecimal y lo convierte a binario
Esta última función no forma parte de las anteriores. La agrego porque me resuttó útil para las comprobaciones porque comprobar en binario esos chorizos de unos y ceros se hace complicado. Lo que hace es coger un valor binario y devolverlo en hexadecimal
Es útil si se quiere escribir el CRC calculado en un textbox o donde sea. En vez de escribir un chorizo binario escribe un valor hexadecimal mas comprensible.