एक पिन परिवर्तन रुकावट का सही उपयोग


10

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

अगर मुझे डेटशीट सही मिली तो पिन चेंज इंटरप्ट का उपयोग करने के लिए निम्नलिखित चीजें करनी चाहिए:

  1. PCMSK रजिस्टर में वह पिन सेट करें जिसे आप नियंत्रित करना चाहते हैं
  2. पिन चेंज इंटरप्ट कंट्रोल (PCICR) के लिए पिन रजिस्टर को सक्षम करें
  3. बीच में सक्षम करें
  4. संबंधित इंटरप्ट वेक्टर का उपयोग करें

प्रोजेक्ट: सिंपल मूडलैंप, कलर्स को 4 बटन्स के जरिए कंट्रोल किया गया।

सेट अप:

  • Atmega168A-पीयू
  • 4 मिनी पुश बटन स्विच
  • मेरे 3 वाट आरजीबी एलईडी को नियंत्रित करने के लिए मोसेस

यहां वह कोड है जो मैं उपयोग कर रहा हूं जो अपेक्षित रूप से काम नहीं कर रहा है:

#include <avr/io.h>
#include <stdint.h>
#include <avr/interrupt.h>
#include <util/delay.h>

#define BUTTON1 (1<<PC5) 
#define BUTTON2 (1<<PC4) 
#define BUTTON3 (1<<PC3) 
#define BUTTON4 (1<<PC2) 

#define GREEN   (1<<PB1) 
#define BLUE    (1<<PB2) 
#define RED     (1<<PB3) 

void init() {

        // enable LED
        DDRB |= GREEN;
        DDRB |= BLUE;
        DDRB |= RED;

        // button pullups
        PORTC |= BUTTON1;
        PORTC |= BUTTON2;
        PORTC |= BUTTON3;
        PORTC |= BUTTON4;

        // pin change interrupts for buttons
        PCMSK1 |= PCINT13;
        PCMSK1 |= PCINT12;
        PCMSK1 |= PCINT11;
        PCMSK1 |= PCINT10;

        // enable pin change for buttons
        PCICR |= PCIE2;

        sei();

}

ISR(PCINT2_vect) {

                PORTB = BLUE;
}


void ledTest() {

                PORTB ^= RED;
                _delay_ms(250);
                PORTB ^= RED;
                _delay_ms(250);
                PORTB ^= RED;
                _delay_ms(250);
                PORTB ^= RED;


                PORTB ^= BLUE;
                _delay_ms(250);
                PORTB ^= BLUE;
                _delay_ms(250);
                PORTB ^= BLUE;
                _delay_ms(250);
                PORTB ^= BLUE;

                PORTB ^= GREEN;
                _delay_ms(250);
                PORTB ^= GREEN;
                _delay_ms(250);
                PORTB ^= GREEN;
                _delay_ms(250);
                PORTB ^= GREEN;
}

int main() {

        init();
        ledTest();

        _delay_ms(500);
        PORTB |= GREEN;

        while(1) {
                _delay_ms(100);
        }
}

नोट: बटन पर बहस की जानी चाहिए। जब से मैं इस कदम से कदम बढ़ा रहा हूं और इसे एलईडी चालू करने के लिए मैटर नहीं करना चाहिए, मैंने इसे यहां नजरअंदाज कर दिया।

प्रश्न: क्या मैं जिस तरह से इंटरप्ट का उपयोग करने की कोशिश कर रहा हूं वह सही है?

मेरे सेटअप में समस्याएँ:

  • बटन 1-3 को पूरी तरह से नजरअंदाज कर दिया जाता है।
  • Button4, Atmega के एक रीसेट को ट्रिगर कर रहा है

जिन चीजों की मैंने जाँच की:

  • बटन किसी भी तरह से रीसेट पिन से जुड़े नहीं हैं
  • यदि दबाया गया तो बटन ठीक से GND से जुड़े होते हैं
  • बटन दबाए जाने पर GND से कनेक्ट नहीं होते हैं
  • यदि मैं बिना किसी बाधा के उनका उपयोग करता हूं, तो बटन अच्छी तरह से काम करते हैं, जैसे:

    अगर ((PINC और BUTTON4)) {PORTB ^ = BLUE; }

  • 16MHZ बाहरी क्रिस्टल / आंतरिक क्रिस्टल
  • राउटिंग में कोई त्रुटि
  • मैं atmga पर PWR और GND के बीच 100nF कैपेसिटर का उपयोग कर रहा हूं
  • वीसीसी (7), जीएनडी (8), जीएनडी (22), एवीसीसी (20) जुड़े हुए हैं (क्योंकि मुझे एरेएफ की जरूरत नहीं है, इसके कनेक्ट नहीं हैं)

आप PCIE1 ध्वज (नहीं PCIE2) और PCINT1_vect (नहीं PCINT2) की जरूरत है
microtherion

PCIE1 क्यों? मैं C रजिस्टर का उपयोग कर रहा हूं, इसलिए यदि मैं गिनता हूं तो यह A (PCIE0), B (PCIE1), C (PCIE1) होगा? वैसे भी, मैंने इसे PCIE1 nad PCINT1_vect के साथ आज़माया और बटन दबाने पर कोई प्रतिक्रिया नहीं होती है।
20

1
इस तरह के असाइनमेंट में ऑर्थोगोनलिटी मानना ​​थोड़ा जोखिम भरा हो सकता है। इस विशेष मामले में, आप लगभग सही होंगे, सिवाय इसके कि ATmega168 में पोर्ट ए नहीं है। किसी भी स्थिति में, मैं डेटशीट और पिनआउट द्वारा गया था। एक और टिप-बंद यह था कि आप पीसीआईई 2 का उपयोग कर रहे थे, लेकिन पीसीएमएसके 1 में बिट्स सेट करना; यह संभवतः सही नहीं हो सकता (दुर्भाग्य से, मुझे नहीं पता कि आपका संशोधित स्केच अभी भी काम क्यों नहीं कर रहा है)।
माइक्रोट्रियन

धन्यवाद, मैं यह भी समझता हूं कि डिबगिंग सॉफ़्टवेयर का संयोजन जो स्वयं बिल्ड हार्डवेयर पर निर्भर करता है, उतना आसान नहीं है ;-)
echox

जवाबों:


14

पिन परिवर्तन व्यवधान आमतौर पर बटन कार्यों का पता लगाने का एक अच्छा तरीका नहीं है। ऐसा इसलिए है क्योंकि मैकेनिकल बटन बाउंस करते हैं, और आपको बहुत सारे व्यर्थ के व्यवधान आएंगे, और फिर आपको अभी भी किसी भी तरह से डिबगिंग करना होगा।

एक बेहतर तरीका यह है कि हर 1 एमएस (1 किलोहर्ट्ज़ दर) की तरह आवधिक अवरोध हो। अधिकांश प्रोसेसर पर यह एक लंबा समय है, इसलिए बीच में बिताए समय का अंश छोटा होगा। बस बटन राज्य हर बाधा का नमूना। यदि आपने एक पंक्ति में नया राज्य 50 ms देखा है, तो एक नया बटन स्थिति घोषित करें। 50 एमएस अधिकांश बटनों की तुलना में अधिक लंबा है, लेकिन अभी भी इतना कम है कि मनुष्य लैग के बारे में ध्यान नहीं देगा या देखभाल नहीं करेगा।

ध्यान दें कि इस तरह से आप एक ही आवधिक 1 एमएस इंटरप्ट में कई बटन भी संभाल सकते हैं। आप सभी की जरूरत है प्रत्येक बटन के लिए एक काउंटर है।

बहस के समय पर अधिक:

कभी-कभी, जैसा कि इस मामले में, कोई कहता है कि 50 एमएस बहुत लंबे समय तक एक बहस का समय है। यह मनुष्यों द्वारा दबाए गए साधारण बटन के लिए सही नहीं है। यह स्टॉपवॉच जैसे बहुत समय-महत्वपूर्ण अनुप्रयोगों में शायद एक मुद्दा हो सकता है, लेकिन अभी तक मैं एक में नहीं चला हूं। मैंने 1980 के दशक के प्रारंभ में इस पर परीक्षण किया, और बहुत से अन्य लोगों ने भी किया।

यह सच है कि सामान्य पुशबटन का उछाल समय लगभग 10 एमएस है, बस 25 एमएस द्वारा बसने के बारे में। बहस के समय पर सीमित कारक मानवीय धारणा है। 50 एमएस थोड़ा छोटा है, जहां लोग इसकी तलाश में देरी शुरू करते हैं, जब वे इसकी तलाश नहीं करते हैं। फिर भी, इसे कष्टप्रद होने में अधिक समय लगता है। किसी व्यक्ति के लिए कुछ मामलों में 50 एमएस और 0 एमएस देरी के बीच अंतर का पता लगाना संभव हो सकता है यदि वे विशेष रूप से इसकी तलाश कर रहे हैं , लेकिन यह एक बटन को धकेलने और कुछ घटित होने और देरी के बारे में नहीं सोचने से काफी अलग है।

50 एमएस इसलिए एक अच्छा बहस का समय है क्योंकि देरी सामान्य अनुप्रयोगों में धारणा सीमा से नीचे है, झुंझलाहट सीमा से नीचे है, और अधिकांश स्विच के उछाल समय से ऊपर है। मुझे ऐसे स्विच मिले हैं जो लगभग लंबे समय तक उछलते रहे, इसलिए आप धारणा की सीमा तक धकेल सकते हैं क्योंकि कुछ भी ढीला नहीं है।

मैंने फर्मवेयर-डिबल्ड बटन के साथ कई उत्पाद किए हैं जिसमें 50 एमएस डिब्यू टाइम का उपयोग किया गया है। एक बार भी किसी ग्राहक ने देरी का उल्लेख नहीं किया। वे सभी बिना किसी समस्या के ठीक काम करने वाले बटन को स्वीकार करते थे।


1
कुछ मामलों के लिए 50ms बहुत लंबा हो सकता है (आमतौर पर, 10-20ms मानव धारणा की सीमा है, और यह बहस के लिए पर्याप्त होना चाहिए), लेकिन यहां वर्णित विधि जाने का रास्ता है।
लास्ज़्लो वल्को

1
@ लेज़्लो: नहीं, 50 एमएस सामान्य मामले के लिए बहुत लंबा नहीं है। मेरे जवाब के अलावा देखें।
ओलिन लेथ्रोप

मैंने 50ms की कोशिश की, जो मेरे लिए ठीक काम करता है :-) मैं अभी भी उत्सुक हूं कि पिन बदलने की बाधा क्यों काम नहीं कर रही है (उछलती हुई चीज के बगल में), लेकिन यह काम करता है :-) धन्यवाद।
20

1

पिन चेंज इंटरप्रिट्स मतदान की तुलना में बहस करने का एक बेहतर तरीका है। व्यवधान आमतौर पर कुछ तर्क जैसे डी-फ्लिप फ्लॉप, या डी-लैच से गुजरता है। हालांकि यह सच है, उच्च स्तर के कंपाइलर के साथ इस डिबेट रूटीन को लागू करना कठिन है। एक बार जब व्यवधान होता है, तो अवरोधक ध्वज को साफ़ नहीं किया जाता है और विलंब सक्षम होने तक अवरोधक सक्षम हो जाता है। एक बार विलंब होने पर पिन की स्थिति की जाँच की जाती है और यदि यह अभी भी दिए गए राज्य में है, तो इससे व्यवधान उत्पन्न होता है, जिससे बटन की स्थिति बदल जाती है और व्यवधान ध्वज साफ़ हो जाता है और व्यवधान सक्षम हो जाता है। यदि राज्य में ऐसा नहीं है जो आरंभ का कारण बनता है, तो बाधा सक्षम करना निर्धारित है और राज्य एक ही रहता है। यह प्रोसेसर को अन्य कार्यों के लिए मुक्त करता है। समय-समय पर कार्यक्रम में समय बर्बाद होता है।


-1

"पिन परिवर्तन व्यवधान आमतौर पर बटन कार्यों का पता लगाने का एक अच्छा तरीका नहीं है।"

गलत। PC INT सबसे अच्छा विकल्प है। यदि आप एक बटन की स्थिति की जांच करने के लिए मतदान का उपयोग करते हैं, तो अधिकांश समय कुछ भी नहीं किया जाएगा। आप बहुत कीमती CPU समय बर्बाद करते हैं। पीसी INT केवल अनुरोध पर कार्रवाई करने की अनुमति देता है।

"यह इसलिए है क्योंकि मैकेनिकल बटन उछाल लेते हैं, और आपको बहुत सारे अर्थहीन व्यवधान आएंगे, और फिर आपको अभी भी किसी भी तरह से बहस करना होगा।"

बाउंसिंग के बारे में सही। फिर भी, आपको एक अवरोध दिनचर्या (समान कारण: CPU समय की बर्बादी) के अंदर एक बटन / स्विच को छोड़ देना चाहिए। ISRs वास्तव में कम और कुशल, कोड-वार होने के लिए होते हैं। बस हार्डवेयर डिबगिंग का उपयोग करें। अपने सॉफ्टवेयर को साफ रखें!

हार्डवेयर डिबगिंग अधिक सुविधाजनक है, संदर्भ के लिए यहाँ देखें / आरसी डिबेंचिंग + श्मिट ट्रिगर । मैंने इसे पीसी INT के साथ अनगिनत बार उपयोग किया है, यह कभी विफल नहीं हुआ।

तो हाँ, आप एक बटन स्थिति प्राप्त करने के लिए PC INT का उपयोग कर सकते हैं (और करना चाहिए)। लेकिन आपको उचित हार्डवेयर डिबगिंग का भी उपयोग करना होगा।


2
सॉफ्टवेयर डिबगिंग एक मान्य दृष्टिकोण है, और ज्यादातर समय अतिरिक्त सीपीयू ओवरहेड अप्रासंगिक है। यह कहना कि आपको आमतौर पर हार्डवेयर में बहस करना चाहिए सबसे अच्छा है। यह कहते हुए कि आपको सभी मामलों में हार्डवेयर डिबॉन्डिंग का उपयोग करना है, यह गलत है।
ओलिन लेट्रोप

अधिकांश अनुप्रयोगों में नियंत्रक वैसे भी ज्यादातर समय बेकार चल रहा है, मुख्य लूप चला रहा है। इसके अलावा, IO राज्य की जांच करने के लिए सीपीयू समय की आवश्यकता होती है और एक चर में संभावित वृद्धि न्यूनतम होती है। सॉफ्टवेयर में सरल डिबॉन्डिंग को लागू करना "फ्री" के लिए लगभग आता है, हार्डवेयर में पैसा खर्च होता है। और कुछ सेंट, विधानसभा लागत के रूप में अच्छी तरह से पैसे नहीं हँसते हैं और यदि आप उत्पाद के उच्च संस्करणों को मध्यम चलाते हैं तो यह नगण्य नहीं है। यह सच है कि आईएसआर समय को कम रखा जाना चाहिए, लेकिन इस मामले में शायद ही कोई तर्क है। यह संभवतः अधिक महत्वपूर्ण है यदि उछल-कूद के कारण पीसी INT ISR पंक्ति में 50 बार फायर करता है।
Rev1.0

@ नेल्सन, 'CPU समय की बर्बादी' कुछ अनुप्रयोगों में मायने रखती है और कई अन्य में नहीं। आपको अपना जवाब उस स्थिति के लिए प्राप्त करना चाहिए जहां CPU समय महत्वपूर्ण है।
user1139880
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.