Как обнаружить / предотвратить переполнение счетчика - PullRequest
6 голосов
/ 01 апреля 2011

У меня есть счетчик для 16-битного поля, которое увеличивается / уменьшается с течением времени с помощью аппаратного периферийного устройства.
Я периодически выбираю его значение, чтобы сложить разницу в 32-битное поле.

Моя проблема заключается в обнаружении переполнения / недостаточного заполнения 16-битного поля при вычислении разницы.

Давайте рассмотрим пример:
В образце n-1 значение счетчика Vn-1 равно 65530.
В качестве образца n значение счетчика Vn равно 4.
Счетчик был увеличен на 10. Но разница (Vn - Vn-1) будет примерно равна 65529 (не уверен в точном значении).

Единственный способ обнаружить переполнение, которое я нашел, - это сравнить значение разности с фиксированным значением, превышающим максимальный прирост (я выбираю 10000).
Знаете ли вы решение для управления этим переполнением, не сравнивая с этим субъективным значением?

Вот пример кода:

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;

Ответы [ 4 ]

7 голосов
/ 01 апреля 2011

В моем предыдущем ответе были некоторые ошибки, поэтому я переписал его, но идея та же, правильно использовать типы без знака.

Сделать currentValue и previousValue обоими целыми числами без знака выбранного размера (например, uint16_t).Тогда просто вычтите их.Поскольку разница будет неявно повышена до int, если int - это больший тип, чем uint16_t, вам нужно будет преобразовать или неявно преобразовать результат обратно в uint16_t.Итак:

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

Это использует неявное преобразование в назначении, но вы можете разыграть, если хотите.

1 голос
/ 01 апреля 2011

Другой вариант - просто отслеживать количество переполнений.Используя uint16_t для значений,

if (currentValue < previousValue) overflows++;

Затем, чтобы получить 32-битное значение, вы объединяете переполнения с currentValue.

result = currentValue | (overflows << 16);

0 голосов
/ 01 апреля 2011

Вы можете попробовать использовать фильтр Калмана для обнаружения переполнения.

0 голосов
/ 01 апреля 2011

Вот несколько идей для вас:

  1. Выполните сложение в 32-битном поле и убедитесь, что результат будет соответствовать 16-битному полю.
  2. Проверьте, не изменился ли старший бит старого значения в результате добавления.
  3. Выполните добавление в сборке, а затем проверьте флаг переноса.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...