Librerie per il calcolo del CRC16 e CRC32

erpomata:
Ok compila anche per attiny85, non l'ho ancora provato.

Mah ... sai, l'unico problema è sulle piattaforme dove NON è (ancora) rilasciata la avr/pgmspace.h , perché, per il resto, è C puro ... :wink:

Guglielmo

Un paio di domande.

Inserendo questa libreria nel mio sketch mi sono sorti un paio di dubbi:

  • Il primo è un pò OT, ho scoperto, forse copiato involontariamente, che utilizzavo un tipo di dato "unsigned char", e per questo non compilava, ma che differenza c'è tra un "unsigned char" ed un "char", lo capisco con i tipi di dato numerici ma con i char...;
  • Il secondo invece riguarda questa libreria, ma come mai gli devo dare la lunghezza come secondo parametro? Di che lunghezza parliamo?
  1. Bé, come dice il nome, il "char" è segnato e va da -128 a +127, mentre l' "unsigned char" non è segnato e va da 0 a 255, comunque ... sempre un byte occupa :wink:

  2. Il primo parametro è il puntatore a ciò di cui vuoi calcolare il CRC, il secondo indica quanti bytes è lungo ciò di cui vuoi calcolare il CRC ... semplice no ? :slight_smile:

Guglielmo

Ok grazie.
Ma la lunghezza non può ricavarsela dalla stringa passata in ingresso?

... :slight_smile: ... e mica serve solo a calcolare CRC di stringhe ... le funzioni vedono solo sfilze di bytes, che poi siano array di char[], byte[], di int[], di double[] o di float[] ... "nun glié ne po' fregà de meno" ... basta che gli dici quanti bytes sono e quella calcola :smiley:

Ottimo :smiley: ma mi ci vorrà un pò per capirlo :fearful:

ma guarda è semplice ... immaginalo come una "firma" di un qualche cosa che un blocco di byte. Se tu vuoi essere sicuro che quel blocco di dati è proprio lui, confronti il CRC prima e dopo ... se è uguale, e sicuramente (... va bé ... diciamo con molta, molta probabilità) lui.

Esistono ovviamente algoritmi molto più complessi e sicuri (es. MD5), ma sono molto più pesanti e il CRC32 è già una bella sicurezza :slight_smile:

ahah si scusa non ci siamo capiti.
Lo so cosa è il crc(16/32) o l'md5, quello che mi rimane difficile è capire quanti byte occupa ciò di cui voglio il crc.

Ancora qualche domanda:
ma per la lunghezza non si potrebbe usare la funzione "sizeof"?
se volessi continuare ad usare gli "unsigned char" dovrei riscrivermi le funzioni? o sbaglio qualcosa?

Si è possibile, ma poi per ogni tipo passato dovresti crearti una funzione apposita con overloading o utilizzare un template.

... si, forse si potrebbe anche usare il sizeof() ... ma così al volo ... non ricordo se è applicabile a tutti, tutti i casi (comprese le strutture e quant'altro) ... :roll_eyes:

Per gli unsigned char ... usali pure e passali con un bel cast davanti XD

Guglielmo

Ok grazie per ora basta domande e domani all'opera.
Preparatevi :smiley:

Ciao scusate, ma da dove scarico la libreria e gli esempi?

Ho l'ide 1.0.5 e non la trovo! =(

... i due moduli sono in uno zip allegato al primo post di questo thread :wink:

Guglielmo

ok, trovata.
Ho copiato la cartella in arduino/libraries ma quando vado a compilare l'esempio mi da tanti warning? Dove sbaglio?

Se ben ricordo NON avevo strutturato la cosa come una vera libreria, ma come due moduli C separati dei quali includevi solo quello che ti serviva direttamente nel tuo progetto (copiando il .h ed il .c nella cartella dove hai il tuo .ino) :wink:

Guglielmo

Ok, quindi dovrei utilizzere o quello a 16crc o 32crc?
Cioè dato questo sketch:

#include "crc16.h"
#include "crc32.h"

unsigned int myCrc16;
unsigned long myCrc32;

void setup() {

   delay(3000);
   
   Serial.begin(9600);
   
   myCrc16 = calc_crc16("123456789", 9);
   myCrc32 = calc_crc32("123456789", 9);
   
   #ifdef __SAM3X8E__
      Serial.println("Calculate CRC on string 123456789");
      Serial.print("CRC16 = 0x");
      Serial.println(myCrc16, HEX);
      Serial.print("CRC32 = 0x");
      Serial.println(myCrc32, HEX);
   #else
      Serial.println(F("Calculate CRC on string 123456789"));
      Serial.print(F("CRC16 = 0x"));
      Serial.println(myCrc16, HEX);
      Serial.print(F("CRC32 = 0x"));
      Serial.println(myCrc32, HEX);
   #endif
}

void loop() {

}

Cosa devo cancellare?

Grazie

... devi usare ... quello che ti serve nella TUA applicazione ... XD

Quindi includi solo il .h del crc che vuoi calcolare (o crc16.h per calcolare il crc16 oppure crc32.h se invece vuoi calcolare il crc32) ed, ovviamente, solo le variabili che ti servono :wink:

Guglielmo

P.S. : Il codice DEVE SEMPRE essere racchiuso negli appositi tag "code" e "/code" ... te li mette automaticamente con il bottoncino # che trovi in alto quando scrivi il messaggio. Grazie.

A chi mai servisse, vi allego anche una semplicissima routine che calcola il CRC-8 usando le formule di Dallas/Maxim.

//CRC-8 - algoritmo basato sulle formule di CRC-8 di Dallas/Maxim 
byte CRC8(const byte *data) {
    byte crc = 0x00;

    while (*data) {
        byte extract = *data++;
        for (byte tempI = 8; tempI; tempI--) {
            byte sum = (crc ^ extract) & 0x01;
            crc >>= 1;
            if (sum) {
                crc ^= 0x8C;
            }
            extract >>= 1;
        }
    }
    return crc;
}

Per usarlo basta passare un array di byte e si ha indietro il CRC8.
Esempio:

byte vettore[5] = {2, 3, 56, 10, 1};
....
byte risultato = CRC8(vettore);

E' comodo nella trasmissione di piccoli pacchetti dati, giusto come somma di controllo. Se serve maggior sicurezza, usate CRC16 o CRC32.

Bella Leo ... la metto assieme alle altre due ... cosÌ si ha l'imbarazzo della scelta XD XD XD

Guglielmo

P.S. : Sai che non mi è chiaro da dove pesca la lunghezza del vettore che gli passi ... riceve solo un pointer ... come fa a sapere quanti bytes contiene ??? O deve terminare con un byte a 0x00 ???

Dovrebbe funzionare per il fatto che byte in Arduino è un alias di unsigned char. In pratica un array di byte altro non è che un array di unsigned char. Il compilatore dovrebbe mettere il valore \0 alla fine come nel caso dei *char.

Non ho disassemblato il binario però, quindi congetturo.