2011-04-01 66 views
6

我有一個計數器在一個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; 

回答

7

我以前的答案有一些錯誤,所以我重寫了它,但想法是一樣的,正確使用無符號類型。

使currentValue和previousValue都是所選大小的無符號整數(例如uint16_t)。然後只是減去它們。由於如果int是比uint16_t更大的類型,因此差異將隱式提升爲int,因此您需要將結果轉換或隱式轉換回uint16_t。因此:

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

這使用了賦值中的隱式轉換,但是如果您願意,可以進行轉換。

+0

你能解釋一下你的陳述嗎?以有符號或無符號進行計算只會將溢出從0/65535傳送到-32768/32768。 – greydet 2011-04-01 14:05:36

+0

對不起,希望現在好多了。 – 2011-04-01 14:24:32

+0

我從來沒有見過這種從unsigned到signed的隱式類型轉換! currentValue - previousValue將始終以無符號形式完成,並且在currentValue溢出的情況下,diff將不會是有效差異。 – greydet 2011-04-01 14:36:15

0

這裏有一些想法給你:

  1. 不要在一個32比特的字段,此外,並驗證結果將融入之後的16位字段。
  2. 測試舊值的高位是否因加法而改變。
  3. 在裝配中添加,然後檢查進位標誌。
+0

關於你的第一點,添加已經完成了32位字段。我需要保持一個不溢出的全局計數器。我會考慮你的另外兩個想法。 – greydet 2011-04-01 14:11:52

+0

我以爲你說你目前的價值溢出?我建議像'int32 temp = currentValue&0xffff; temp + = newValue;如果(溫度> 65535)溢出!其他currentValue =(int16)temp;' – Jonathan 2011-04-01 14:16:49

0

您可以嘗試使用Kalman filter來檢測溢出。

+0

我正在尋找一個簡單的解決方案,不需要太多的開銷,因爲我在有限的處理資源下運行。但是,感謝你的這個想法! – greydet 2011-04-01 14:08:13

1

另一種選擇是隻跟蹤溢出計數。使用uint16_t爲價值觀,

if (currentValue < previousValue) overflows++; 

然後得到一個32位的值,則結合了CurrentValue的溢出。

result = currentValue | (overflows << 16);

+0

這是行不通的,因爲計數器在兩個方向上都有增量和減量。所以currentValue可以小於以前的值而不會溢出。 – greydet 2011-04-01 19:49:25