2011-04-01 22 views
6

मेरे पास 16 बिट्स फ़ील्ड पर एक काउंटर है जो हार्डवेयर परिधीय समय के दौरान बढ़ाया/घट गया है।
मैं 32 बिट फ़ील्ड में अंतर को मापने के लिए समय-समय पर अपना मान नमूना देता हूं।काउंटर ओवरफ़्लो का पता लगाने/रोकने के लिए कैसे करें

मेरी समस्या अंतर की गणना करते समय 16 बिट्स फ़ील्ड के अतिप्रवाह/अंडरफ्लो का पता लगाना है।

के एक उदाहरण लेते हैं: नमूना n-1 पर
, काउंटर मूल्य वी.एन. -1 65530.
नमूना n के रूप में है, काउंटर मूल्य वी.एन. है 4.
काउंटर से 10 से वृद्धि की गई है लेकिन अंतर (वीएन - वीएन -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

मेरे पिछले उत्तर में कुछ गलतियां थीं इसलिए मैंने इसे फिर से लिखा है, लेकिन विचार समान है, हस्ताक्षरित प्रकारों का सही ढंग से उपयोग करें।

वर्तमान वैल्यू और पिछले वैल्यू को चुने हुए आकार (जैसे uint16_t) दोनों के हस्ताक्षरित पूर्णांक बनाएं। फिर केवल उन्हें घटाएं। चूंकि अंतर को int पर लागू किया जाएगा यदि intuint16_t से बड़ा प्रकार है, तो आपको परिणामों को uint16_t पर कास्ट या निहित रूप से परिवर्तित करने की आवश्यकता होगी। तो:

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

यह असाइनमेंट में अंतर्निहित रूपांतरण का उपयोग करता है, लेकिन यदि आप चाहें तो आप कास्ट कर सकते हैं।

+0

क्या आप अपना बयान समझा सकते हैं? हस्ताक्षरित या हस्ताक्षरित में गणना करना केवल ओवरफ़्लो को 0/65535 से -32768/32768 पर स्थानांतरित कर देगा। – greydet

+0

क्षमा करें, उम्मीद है कि यह अब बेहतर है। –

+0

मैंने इस निहित प्रकार के रूपांतरण को हस्ताक्षरित हस्ताक्षर से कभी नहीं देखा! currentValue - पिछला वैल्यू हमेशा हस्ताक्षरित के रूप में किया जाएगा और वर्तमान के ओवरफ्लो के मामले में diff प्रभावी अंतर नहीं होगा – greydet

0

यहाँ आप के लिए कुछ विचार कर रहे हैं::

  1. एक 32-बिट क्षेत्र में इसके अलावा, और सत्यापित करें कि परिणाम में फिट होगा

    यहाँ एक कोड उदाहरण है बाद में 16-बिट फ़ील्ड।

  2. परीक्षण करें कि पुराने मूल्य की उच्च बिट अतिरिक्त के परिणामस्वरूप बदल गई है या नहीं।
  3. असेंबली में अतिरिक्त करें, और बाद में लेयर फ्लैग की जांच करें।
+0

अपना पहला बिंदु के बारे में, इसके अलावा पहले से ही 32-बिट क्षेत्र से अधिक किया जाता है। मुझे एक वैश्विक काउंटर रखना है जो अतिप्रवाह नहीं है। मैं आपके 2 अन्य विचारों पर विचार करूंगा। – greydet

+0

मैंने सोचा कि आपने कहा था कि आपका वर्तमान मूल्य बह रहा है? मैं सुझाव दे रहा हूं कि 'int32 temp = currentValue और 0xffff जैसे कुछ करें; temp + = newValue; अगर (temp> 65535) अतिप्रवाह!else currentValue = (int16) temp; ' – Jonathan

0

आप अतिप्रवाह का पता लगाने के लिए Kalman filter का उपयोग करने का प्रयास कर सकते हैं।

+0

मैं एक साधारण समाधान की तलाश में हूं जिसके लिए बहुत अधिक आवश्यकता नहीं है क्योंकि मैं सीमित प्रसंस्करण संसाधनों के साथ चल रहा हूं। लेकिन इस विचार के लिए धन्यवाद! – greydet

1

एक और विकल्प केवल अतिप्रवाह गणना का ट्रैक रखना है। मूल्यों के लिए uint16_t का उपयोग करना,

if (currentValue < previousValue) overflows++; 

तब एक 32-बिट मूल्य प्राप्त करने के लिए, आप गठबंधन currentValue साथ overflows।

result = currentValue | (overflows << 16);

+0

यह काम नहीं करता है क्योंकि काउंटर दोनों दिशाओं (वृद्धि और कमी) में चला जाता है। तो वर्तमान वैल्यू बिना प्रवाह के पिछले मूल्य कम हो सकता है। – greydet

संबंधित मुद्दे