2009-09-15 9 views
5

मैं माइक्रो-नियंत्रक हैकिंग में जा रहा हूं और जब मैं बिटवाई ऑपरेटरों के साथ बहुत सहज हूं और हार्डवेयर के ठीक से बात कर रहा हूं, तो मुझे परिणामस्वरूप कोड बहुत वर्बोज़ और बॉयलरप्लेट मिल रहा है। मेरे में उच्च स्तर का प्रोग्रामर इसे साफ करने के लिए एक प्रभावी लेकिन कुशल तरीका खोजना चाहता है।ए सी प्रीप्रोसेसर मैक्रो एक बाइट में बिटफील्ड पैक करने के लिए?

उदाहरण के लिए, रजिस्टरों में स्थापित करने के झंडे के लिए बहुत कुछ है:

/* Provided by the compiler */ 
#define SPIE 7 
#define SPE 6 
#define DORD 5 
#define MSTR 5 
#define CPOL 4 
#define CPHA 3 

void init_spi() { 
    SPCR = (1 << SPE) | (1 << SPIE) | (1 << MSTR) | (1 << SPI2X);  
} 

शुक्र है वहाँ मैक्रो कि वास्तविक पोर्ट आईओ परिचालन (बाएं हाथ की ओर) को छिपाने के हैं, तो यह एक सरल काम की तरह लग रहा है। लेकिन मेरे लिए यह वाक्यविन्यास गन्दा है।

आवश्यकताओं हैं:

  • यह केवल 8 बिट को संभाल करने के लिए है,
  • बिट पदों में सक्षम होना चाहिए किसी भी क्रम में पारित होने के लिए, और
  • केवल सेट की आवश्यकता होती है चाहिए बिट्स होने के लिए बीतने के।

वाक्य रचना मैं चाहता है:

SPCR = बिट्स (एसपीई, SPIE, MSTR, SPI2X);

सबसे अच्छा मैं अब तक लेकर आए हैं एक कॉम्बो मैक्रो/समारोह है:

#define bits(...) __pack_bits(__VA_ARGS__, -1) 

uint8_t __pack_bits(uint8_t bit, ...) { 
    uint8_t result = 0; 
    va_list args; 
    va_start(args, bit); 

    result |= (uint8_t) (1 << bit); 

    for (;;) { 
     bit = (uint8_t) va_arg(args, int); 
     if (bit > 7) 
      break; 
     result |= (uint8_t) (1 << bit); 
    } 
} 

यह मेरा विशेष आर्किटेक्चर पर 32 बाइट्स संकलित करता है तथा निष्पादित करने के लिए 61-345 चक्र लेता है (कितने पर निर्भर करता है बिट्स पास हुए थे)।

आदर्श रूप से यह प्रीप्रोसेसर में किया जाना चाहिए क्योंकि परिणाम निरंतर है, और आउटपुट मशीन निर्देशों को केवल एक रजिस्टर के लिए 8 बिट मान का असाइनमेंट होना चाहिए।

क्या यह बेहतर किया जा सकता है?

उत्तर

6

हाँ, मैक्रोज़ ABC को 1 << ABC के रूप में फिर से परिभाषित करें, और आप इसे सरल बनाते हैं। एक साथ थोड़ा मुखौटा बनाना एक बहुत ही आम मुहावरे है जिसे कोई भी पहचान लेगा। अपने चेहरे से शिफ्ट की स्थिति प्राप्त करने से बहुत मदद मिलेगी।

आपका कोड

#define SPIE 7 
#define SPE 6 
#define DORD 5 
#define MSTR 5 
#define CPOL 4 
#define CPHA 3 

void init_spi() { 
    SPCR = (1 << SPE) | (1 << SPIE) | (1 << MSTR) | (1 << SPI2X);  
} 

से इस

#define BIT(n) (1 << (n)) 
#define SPIE BIT(7) 
#define SPE BIT(6) 
#define DORD BIT(5) 
#define MSTR BIT(5) 
#define CPOL BIT(4) 
#define CPHA BIT(3) 

void init_spi() { 
    SPCR = SPE | SPIE | MSTR | SPI2X; 
} 

यह सुझाव मान है कि थोड़ा-क्षेत्र परिभाषाओं से अधिक उनमें से परिभाषाएं दी गई हैं कई बार उपयोग किया जाता है को जाता है।


मुझे लगता है कि वहाँ किसी तरह इस बात के लिए variadic macros उपयोग करने के लिए हो सकता है, लेकिन मैं कुछ भी है कि आसानी से अभिव्यक्ति के रूप में इस्तेमाल किया जा सकता पर समझ नहीं सकता। पर विचार करें, फिर भी, एक सरणी एक समारोह अपने निरंतर पैदा अंदर शाब्दिक बनाने:

#define BITS(name, ...) \ 
    char name() { \ 
     char[] bits = { __VA_ARGS__ }; \ 
     char byte = 0, i; \ 
     for (i = 0; i < sizeof(bits); ++i) byte |= (1 << bits[i]); \ 
     return byte; } 

/* Define the bit-mask function for this purpose */ 
BITS(SPCR_BITS, SPE, SPIE, MSTR, SPI2X) 

void init_spi() { 
    SPCR = SPCR_BITS(); 
} 

यदि आपके संकलक अच्छा है, यह पूरे समारोह संकलन समय पर स्थिर है कि देखेंगे, और परिणामी मूल्य इनलाइन।

+0

कि शायद है मैं क्या कर सकता है, तो नहीं बिट स्थिति परिभाषाओं पहले से ही वास्तुकला विशिष्ट संकलक समर्थन से परिभाषित किया जा रहा के लिए (में, इस मामले avr-gcc)। मुझे लगता है कि सुंदर गूंगा। यदि कहीं भी है तो उन्हें बाएं-शिफ्ट तर्क के अलावा अन्य उपयोग किया जाना चाहिए ... मुझे यह नहीं मिल रहा है। पर अब जो है वो है। –

+1

इसके अलावा, मैंने जो कोड देखा है, वह अब तक << XX फ़ॉर्म का उपयोग करके और _BV (XX) का उपयोग करने के बीच भिन्न होता है। _BV एक प्रदत्त मैक्रो है जो (1 << n) करता है। लेकिन इसका अभी भी बहुत अधिक टाइपिंग का मतलब है। –

+0

अच्छा विचार। लेकिन सुरक्षा कारणों से, मैं एन # बीआईटी (एन) (1 << (एन)) परिभाषित करता हूं, मैक्रोज़ बुरा हो सकता है। बीआईटी (5-1) के साथ मैक्रो का उपयोग कर किसी की कल्पना करें ... – Roland

0

क्यों नहीं पूर्व निर्धारित लोगों के अलावा अपनी खुद की परिभाषाओं बनाने ...

#define BIT_TO_MASK(n) (1 << (n)) 

#define SPIE_MASK BIT_TO_MASK(SPIE) 
#define SPE_MASK BIT_TO_MASK(SPE) 
#define DORD_MASK BIT_TO_MASK(DORD) 
#define MSTR_MASK BIT_TO_MASK(MSTR) 
#define CPOL_MASK BIT_TO_MASK(CPOL) 
#define CPHA_MASK BIT_TO_MASK(CPHA) 

void init_spi() { 
    SPCR = SPE_MASK | SPIE_MASK | MSTR_MASK | SPI2X_MASK; 
} 
संबंधित मुद्दे