Как обнаружить/предотвратить переполнение счетчика

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

моя проблема заключается в обнаружении переполнения/подтока 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 ответов


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

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

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

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


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

if (currentValue < previousValue) overflows++;

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

result = currentValue | (overflows << 16);


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

  1. сделайте добавление в 32-битном поле и убедитесь, что результат будет вписываться в 16-битное поле после этого.
  2. Проверьте, изменился ли высокий бит старого значения в результате добавления.
  3. сделайте добавление в сборке,а затем проверьте флаг переноса.

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