8
votes

Comment détecter / empêcher un contre-flow

J'ai un compteur sur un champ de 16 bits incrémenté / décrémenté au fil du temps par un périphérique matériel.
J'empone périodiquement sa valeur pour résumer la différence dans un champ de 32bits.

Mon problème est de détecter le débordement / sous-fluide du champ de 16 bits lors de l'informatique de la différence. P>

Prenons l'exemple:
À l'échantillon N-1, la valeur de comptoir VN-1 est 65530.
En tant qu'échantillon N, la valeur de comptoir vn est 4.
Le compteur a été incrémenté par 10. Mais la différence (vn-vn-1), sera quelque chose comme 65529 (pas sûr de la valeur exacte). P>

Le seul moyen que j'ai trouvé pour détecter ce débordement est Pour comparer la valeur de différence à une valeur fixe supérieure à l'incrément maximal (je choisis 10000).
Connaissez-vous une solution pour gérer ce débordement sans comparer à cette valeur subjective? P>

Voici un exemple de code: P>

static sint32 overallCount = 0;
sint32 diff;
static sint16 previousValue = 0;
sint16 currentValue;

currentValue = sampleValue();

diff = ((sint32) currentValue) - previousValue;
if(diff > 10000) {
    diff -= 65536;
} else if ((-diff) > 10000) {
    diff += 65536;
}

overallCount += diff;


0 commentaires

4 Réponses :


1
votes

Voici quelques idées pour vous:

  1. Faites l'ajout dans un champ 32 bits et vérifiez que le résultat s'intégrera ensuite dans le champ 16 bits.
  2. Testez si la valeur élevée de l'ancienne valeur a changé à la suite de l'addition.
  3. Faites l'ajout en montage et vérifiez le drapeau de transport par la suite.

2 commentaires

À propos de votre premier point, l'addition est déjà effectuée sur un champ 32 bits. J'ai besoin de garder un compteur mondial qui ne déborde pas. Je vais considérer vos 2 autres idées.


Je pensais que vous avez dit que votre valeur actuelle débordait-elle? Je suggère que quelque chose comme int32 temp = courcentvalue & 0xFFFF; TEMP + = NewValue; Si (TEMP> 65535) Overflow! sinon CurrentValue = (int16) TEMP;



-1
votes

Vous pouvez essayer d'utiliser un Filtre Kalman pour détecter le débordement.


1 commentaires

Je cherche une solution simple qui ne nécessite pas beaucoup de frais généraux car je cours avec des ressources de traitement limitées. Mais merci pour cette idée!



8
votes

Ma réponse précédente Vous avez eu des erreurs donc je me suis réécrit, mais l'idée est la même, utilisez les types non signés correctement.

rendre courantvalue et précédentValuer les entiers non signés de la taille choisie (E.G. uint16_T). Puis simplement soustrayez-les. Étant donné que la différence sera implicitement promue à int code> si int code> est un type plus grand que uint16_t code>, vous devez lancer ou convertir implicitement le résultat. Retour à uint16_t code>. Donc: P>

static uint16_t previousValue;
uint16_t currentValue = sampleValue();
uint16_t diff = currentValue - previousValue;


5 commentaires

Pourriez-vous expliquer votre déclaration? Faire le calcul dans SIGNÉ ou non signé ne transférera que le débordement du 0/65535 au -32768/32768.


Désolé, j'espère que c'est mieux maintenant.


Je n'ai jamais vu cette conversion de type implicite de non signée en signée! CurrentValue - PrécédentValue sera toujours fait comme non signé et en cas de débordement de courant actuel, le diff n'est pas la différence effective


Dans C, Tout arithmétique est promu au moins à int . C'est pourquoi vous voyez des résultats erronés si vous ne moulez pas ou que vous vous attachez à un uint16_t .


OK compris! Vous avez raison :) La seule chose que je dois faire est de lancer la diffusée dans Sint16 pour la somme dans le champ 32 bits pour gérer les sous-flux.



1
votes

Une autre option consiste à garder une trace du nombre de débordements. Utilisation UINT16_T pour les valeurs,

if (currentValue < previousValue) overflows++;


1 commentaires

Cela ne fonctionne pas car le comptoir va dans les deux sens (incrément et décrément). Donc, l'actualisation peut être moins la valeur précédente sans déborder.