Как обнаружить/предотвратить переполнение счетчика
У меня есть счетчик на 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);
вот несколько идей для вас:
- сделайте добавление в 32-битном поле и убедитесь, что результат будет вписываться в 16-битное поле после этого.
- Проверьте, изменился ли высокий бит старого значения в результате добавления.
- сделайте добавление в сборке,а затем проверьте флаг переноса.
вы можете попробовать использовать фильтр Калмана для обнаружения переполнения.