2009-10-09 15 views
1

J'ai une petite application écrite en C# qui écoute sur un SerialPort pour que l'information entre. Les informations sont en: STX + data + ETX + BCC. Nous calculons ensuite le BCC du paquet de transmission et le comparons. La fonction est:Pourquoi la somme de contrôle calculée ne correspond-elle pas au BCC envoyé via le port série?

private bool ConsistencyCheck(byte[] buffer) 
{ 
    byte expected = buffer[buffer.Length - 1]; 
    byte actual = 0x00; 

    for (int i = 1; i < buffer.Length - 1; i++) 
    { 
     actual ^= buffer[i]; 
    } 

    if ((expected & 0xFF) != (actual & 0xFF)) 
    { 
     if (AppTools.Logger.IsDebugEnabled) 
     { 
      AppTools.Logger.Warn(String.Format("ConsistencyCheck failed: Expected: #{0} Got: #{1}", expected, actual)); 
     } 
    } 

    return (expected & 0xFF) == (actual & 0xFF); 
} 

Et il semble fonctionner plus ou moins. Il n'inclut pas précisément le STX ou le BCC et inclut précisément l'ETX dans ses calculs. Il semble fonctionner dans un très grand pourcentage du temps, mais nous avons au moins deux machines sur lesquelles nous travaillons, toutes deux étant Windows 2008 64 bits dans lesquelles le calcul de BCC NE COMPTE JAMAIS. Tiré d'un journal récent j'avais dans un octet 20 a été envoyé et j'ai calculé 16 et un où 11 a été envoyé et j'ai calculé 27.

Je suis absolument perplexe quant à ce qui se passe ici. Est-ce qu'il y a peut-être un "getcha" 64 bits ou Windows 2008 qui me manque ici? Toute aide ou même des idées sauvages seraient appréciées.

EDIT:

Voici le code qui lit les données:

private void port_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e) 
{ 
    // Retrieve number of bytes in the buffer 
    int bytes = serialPort.BytesToRead; 

    // Create a byte array to hold the awaiting data 
    byte[] received = new byte[bytes]; 

    //read the data and store it 
    serialPort.Read(received, 0, bytes); 

    DataReceived(received); 
} 

Et la fonction DataReceived() prend cette chaîne et elle se adresse à l'objet global StringBuilder. Il reste ensuite en tant que générateur de chaîne jusqu'à ce qu'il soit passé à ces différentes fonctions, auquel cas le .ToString() est appelé.

EDIT2: Modification du code pour refléter mes routines modifiées qui fonctionnent sur des tableaux octets/octets plutôt que sur des chaînes.

EDIT3: Je n'ai toujours pas compris cela, et j'ai plus de données de test qui ont des résultats complètement incohérents (le montant que je suis hors de la somme de contrôle varie chaque fois sans motif). J'ai l'impression que je calcule mal la somme de contrôle, mais je ne sais pas comment.

+0

Il semble que vous ne sachiez toujours pas si le problème provient du port série recevant le paquet entier ou le calcul de BCC. Pouvez-vous écrire un petit programme autonome qui lit les données d'un fichier journal à partir d'un bon ordinateur connu, puis appelle 'DataReceived' et fait tout le traitement en aval? Si vous pouvez l'exécuter sur l'un de vos «mauvais» ordinateurs Win2008 64 bits, vous saurez peut-être où chercher. – mtrw

Répondre

2

Le tampon est défini comme une chaîne. Alors que je soupçonne que les données que vous transmettez sont des octets. Je recommanderais d'utiliser des tableaux d'octets (même si vous envoyez un encodage ascii/utf/quel que soit l'encodage). Ensuite, après que la somme de contrôle est valide, convertissez les données en une chaîne

+0

Même si je suis d'accord que c'est probablement une bonne idée, comment exactement cela pourrait-il me gagner quelque chose? Je n'ai pas vraiment envie de refactoriser l'application entière pour utiliser un tableau d'octets sans raison. – Morinar

+1

Je ne saurais pas si vous alimentez les octets 0 - 255 dans une chaîne, si les caractères de chaîne seraient aussi lus 0-255 ... comme une conversion a lieu à son format interne, il pourrait très bien être traduit et donc votre somme de contrôle sera erronée – Toad

+0

+1 pour la réponse de Morinar. les chaînes ne sont pas adaptées à la représentation de tableaux d'octets. Il devrait être trivial de refactoriser de chaîne en octet []. Je mettrais de l'argent sur votre problème étant l'utilisation d'une chaîne au lieu de byte []. – Bryan

0

Assurez-vous que le port est défini pour accepter des octets NULL quelque part dans votre code de configuration de port. (. Ce peut-être la valeur par défaut, je ne suis pas sûr)

port.DiscardNull = false; 

En outre, vérifiez le type d'octet arrivant à il port série, et accepte uniquement les données:

private void port_DataReceived(object sender, SerialDataReceivedEventArgs e) 
{ 
    if (e.EventType == SerialData.Chars) 
    { 
     // Your existing code 
    } 
} 
1

informatique BCC est pas standard, mais "défini par le client". nous programmons des interfaces pour nos clients et trouvons plusieurs fois des algorithmes différents, y compris sum, xor, masking, en séparant stx, etx, ou les deux, ou en séparant tous les octets connus. par exemple, la structure du paquet est "stx, code machine, code de commande, données, ..., données, etx, bcc", et le calcul de bcc est (spécifié par le client!) comme "somme binaire de tous les octets dernières données, inclusives, et toutes masquées avec 0xCD ". C'est-à-dire que nous devons d'abord ajouter tous les octets inconnus (cela n'a aucun sens d'ajouter du code stx, etx, ou du code machine, si ces octets ne correspondent pas, le cadre est défaussé de toute façon!leur valeur est testée quand ils sont, pour être sûr que la trame commence, se termine correctement, et elle est adressée à la machine réceptrice, et dans ce cas, nous devons uniquement cocher les octets qui peuvent changer dans le cadre, cela diminuera le temps, comme dans beaucoup de cas, nous travaillons avec des microcontrôleurs lents de 4 ou 8 bits, et attention, cela fait la somme des octets, et non pas les stocker, ce n'était qu'un exemple, un autre client veut autre chose), et ensuite la somme (qui peut être 16 bits si elle n'est pas tronquée lors de l'addition), on la masque (au niveau du bit AND) avec la clé (dans cet exemple 0xCD). Ce genre de choses est fréquemment utilisé pour tous les types de systèmes proches, comme les ATM par exemple (connexion d'un clavier série à un ATM) pour des raisons de protection, etc., en plus du cryptage et d'autres choses. Donc, vous devez vraiment vérifier (lire "crack") comment vos deux machines calculent leurs BCC (non standard).