विषयसूची:

एवीआर माइक्रोकंट्रोलर। टाइमर का उपयोग कर एलईडी फ्लैशर। टाइमर बाधित। टाइमर सीटीसी मोड: 6 कदम
एवीआर माइक्रोकंट्रोलर। टाइमर का उपयोग कर एलईडी फ्लैशर। टाइमर बाधित। टाइमर सीटीसी मोड: 6 कदम

वीडियो: एवीआर माइक्रोकंट्रोलर। टाइमर का उपयोग कर एलईडी फ्लैशर। टाइमर बाधित। टाइमर सीटीसी मोड: 6 कदम

वीडियो: एवीआर माइक्रोकंट्रोलर। टाइमर का उपयोग कर एलईडी फ्लैशर। टाइमर बाधित। टाइमर सीटीसी मोड: 6 कदम
वीडियो: AVR Microcontroller. LED flasher using timers. Timers interrupts. Timer CTC Mode. 2024, नवंबर
Anonim
Image
Image

सभी को नमस्कार!

इलेक्ट्रॉनिक्स के क्षेत्र में टाइमर एक महत्वपूर्ण अवधारणा है। हर इलेक्ट्रॉनिक कंपोनेंट टाइम बेस पर काम करता है। इस बार आधार सभी कामों में तालमेल बिठाने में मदद करता है। सभी माइक्रोकंट्रोलर कुछ पूर्वनिर्धारित घड़ी आवृत्ति पर काम करते हैं, उन सभी में टाइमर सेट करने का प्रावधान है। AVR में एक टाइमर होने का दावा किया गया है जो बहुत सटीक, सटीक और विश्वसनीय है। यह इसमें बहुत सारी सुविधाएँ प्रदान करता है, इस प्रकार इसे एक विशाल विषय बनाता है। सबसे अच्छी बात यह है कि टाइमर पूरी तरह से सीपीयू से स्वतंत्र है। इस प्रकार, यह CPU के समानांतर चलता है और इसमें CPU का कोई हस्तक्षेप नहीं होता है, जो टाइमर को काफी सटीक बनाता है। इस खंड में मैं एवीआर टाइमर की बुनियादी अवधारणाओं की व्याख्या करता हूं। मैं टाइमर का उपयोग करके एलईडी फ्लैशर को नियंत्रित करने के लिए सी कोड में सरल प्रोग्राम लिख रहा हूं।

चरण 1: विवरण

समस्या कथन १: प्रत्येक ५० एमएस. पर पहले एलईडी (हरा) फ्लैश करें
समस्या कथन १: प्रत्येक ५० एमएस. पर पहले एलईडी (हरा) फ्लैश करें

ATMega328 में तीन प्रकार के टाइमर हैं:

Timer/Counter0 (TC0) - एक सामान्य प्रयोजन 8-बिट टाइमर/काउंटर मॉड्यूल है, जिसमें दो स्वतंत्र OutputCompare Units, और PWM सपोर्ट है;

टाइमर/काउंटर1 (टीसी1) - 16-बिट टाइमर/काउंटर यूनिट सटीक प्रोग्राम निष्पादन समय (इवेंट मैनेजमेंट), वेव जनरेशन और सिग्नल टाइमिंग मापन की अनुमति देता है;

टाइमर/काउंटर2 (टीसी2)-एक सामान्य उद्देश्य, चैनल, पीडब्लूएम और एसिंक्रोनस ऑपरेशन के साथ 8-बिट टाइमर/काउंटर मॉड्यूल है;

चरण 2: समस्या विवरण 1: आइए हर 50 एमएस. पर पहले एलईडी (हरा) फ्लैश करें

समस्या कथन १: प्रत्येक ५० एमएस. पर पहले एलईडी (हरा) फ्लैश करें
समस्या कथन १: प्रत्येक ५० एमएस. पर पहले एलईडी (हरा) फ्लैश करें
समस्या कथन १: प्रत्येक ५० एमएस. पर पहले एलईडी (हरा) फ्लैश करें
समस्या कथन १: प्रत्येक ५० एमएस. पर पहले एलईडी (हरा) फ्लैश करें

कार्यप्रणाली:

- पूर्णांक विभाजन द्वारा उच्च आवृत्ति विद्युत संकेत को कम आवृत्ति तक कम करने के लिए टाइमर0 प्रीस्केलर का उपयोग करना;

- हर बार Timer0 के ओवरफ्लो होने पर एक रुकावट का उपयोग करना;

Timer0 (8 बिट) यह 0 से 255 तक गिना जाता है उसके बाद, वे अतिप्रवाह करते हैं, यह मान हर घड़ी की नाड़ी पर बदल जाता है।

F_CPU=16MHz: घड़ी की समयावधि = 1000ms / 16000000Hz = 0.0000625ms

टाइमर गिनती = (आवश्यक देरी / घड़ी की समय अवधि) -1 = (५०ms / ०.००००६२५ms) = ७९९९९

केवल ५० एमएस की देरी देने के लिए घड़ी पहले ही ७९९९९९ बार टिक कर चुकी है!

हम आवृत्ति विभाजन की तकनीक का उपयोग कर सकते हैं जिसे टाइमर गिनती कम करने के लिए प्रीस्केलिंग कहा जाता है। AVR हमें चुनने के लिए निम्नलिखित प्रीस्केलर मान प्रदान करता है: 8, 64, 256 और 1024। तालिका देखें विभिन्न प्रीस्केलर का उपयोग करने के परिणामों का सारांश।

काउंटर मान हमेशा एक पूर्णांक होना चाहिए। आइए एक प्रीस्कूलर 256 चुनें!

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

चूंकि आवश्यक देरी (50ms) अधिकतम संभव देरी से अधिक है: 4, 096ms = 1000ms / 62500Hz * 256, जाहिर है कि टाइमर ओवरफ्लो हो जाएगा। और जब भी टाइमर ओवरफ्लो होता है, एक इंटरप्ट निकाल दिया जाता है।

इंटरप्ट को कितनी बार निकाल दिया जाना चाहिए?

50ms / 4.096ms = 3125/256 = 12.207 यदि टाइमर 12 बार ओवरफ्लो हो गया है, तो 12 * 4.096ms = 49.152ms बीत चुका होगा। 13वें पुनरावृत्ति में, हमें 50ms - 49.152ms = 0.848ms की देरी की आवश्यकता है।

62500Hz (prescaler = 256) की आवृत्ति पर, प्रत्येक टिक 0.016ms लेता है। इस प्रकार 0.848ms की देरी प्राप्त करने के लिए, इसे 0.848ms / 0.016ms = 53 टिक की आवश्यकता होगी। इस प्रकार, 13वें पुनरावृत्ति में, हम केवल टाइमर को 53 तक गिनने की अनुमति देते हैं, और फिर इसे रीसेट करते हैं।

टाइमर0/काउंटर प्रारंभ करें (तस्वीर देखें):

TCCR0B | = (1 << CS02) // प्रीस्केलर के साथ टाइमर सेट करें = 256 TCNT0 = 0 // इनिशियलाइज़ काउंटर TIMSK0 | = (1 << TOIE0) // ओवरफ्लो इंटरप्ट को सक्षम करें () // ग्लोबल इंटरप्ट को सक्षम करें tot_overflow = 0 // ओवरफ्लो काउंटर वैरिएबल को इनिशियलाइज़ करें

चरण ३: समस्या कथन २: आइए प्रत्येक 1s. पर दूसरी एलईडी (नीला) फ्लैश करें

समस्या कथन 2: आइए हर 1 सेकंड में दूसरी एलईडी (नीला) फ्लैश करें
समस्या कथन 2: आइए हर 1 सेकंड में दूसरी एलईडी (नीला) फ्लैश करें
समस्या कथन 2: आइए हर 1 सेकंड में दूसरी एलईडी (नीला) फ्लैश करें
समस्या कथन 2: आइए हर 1 सेकंड में दूसरी एलईडी (नीला) फ्लैश करें
समस्या कथन 2: आइए हर 1 सेकंड में दूसरी एलईडी (नीला) फ्लैश करें
समस्या कथन 2: आइए हर 1 सेकंड में दूसरी एलईडी (नीला) फ्लैश करें

कार्यप्रणाली:

- पूर्णांक विभाजन द्वारा उच्च आवृत्ति विद्युत संकेत को कम आवृत्ति तक कम करने के लिए टाइमर 1 प्रीस्केलर का उपयोग करना;

- तुलना (सीटीसी) मोड पर क्लियर टाइमर का उपयोग करना;

- सीटीसी मोड के साथ इंटरप्ट्स का उपयोग करना;

Timer1 (16 बिट) यह 0 से 65534 तक गिना जाता है, उसके बाद वे ओवरफ्लो हो जाते हैं। यह मान हर घड़ी की नाड़ी पर बदलता है।

F_CPU=16MHz: क्लॉक टाइम पीरियड = 1000ms / 16000000Hz = 0.0000625msटाइमर काउंट = (आवश्यक देरी / क्लॉक टाइम पीरियड) -1 = (1000ms / 0.0000625ms) = 15999999

1s की देरी देने के लिए घड़ी पहले ही 15999999 बार टिक कर चुकी है!

हम आवृत्ति विभाजन की तकनीक का उपयोग कर सकते हैं जिसे टाइमर गिनती कम करने के लिए प्रीस्केलिंग कहा जाता है। AVR हमें चुनने के लिए निम्नलिखित प्रीस्केलर मान प्रदान करता है: 8, 64, 256 और 1024। तालिका देखें विभिन्न प्रीस्केलर का उपयोग करने के परिणामों का सारांश। काउंटर मान हमेशा एक पूर्णांक होना चाहिए। आइए एक प्रीस्कूलर 256 चुनें!

तुलना (सीटीसी) मोड पर स्पष्ट टाइमर में, काउंटर रिज़ॉल्यूशन में हेरफेर करने के लिए ओसीआर 1 ए या आईसीआर 1 रजिस्टर का उपयोग किया जाता है। सीटीसी मोड में जब काउंटर वैल्यू (टीसीएनटी1) ओसीआर1ए या आईसीआर1 से मेल खाती है तो काउंटर को शून्य कर दिया जाता है। OCR1A या ICR1 काउंटर के लिए शीर्ष मूल्य को परिभाषित करता है, इसलिए इसका संकल्प भी। यह मोड तुलना मैच आउटपुट फ़्रीक्वेंसी के अधिक नियंत्रण की अनुमति देता है यह बाहरी घटनाओं की गणना के संचालन को भी सरल करता है। हमें AVR को टाइमर1/काउंटर को रीसेट करने के लिए कहना चाहिए जैसे ही इसका मूल्य 62500 के मूल्य तक पहुंच जाता है, इस प्रकार 1s की देरी प्राप्त करने के लिए।

टाइमर 1 / काउंटर प्रारंभ करें (तस्वीर देखें):

TCCR1B | = (1 << WGM12)|(1 << CS12) // प्रीस्केलर = 256 और CTC मोड के साथ टाइमर सेट करें TCNT1 = 0 // इनिशियलाइज़ काउंटर TIMSK1 |= (1 << OCIE1A) // इंटरप्ट OCR1A की तुलना सक्षम करें = ६२५०० // आरंभिक तुलना मूल्य

चरण 4: समस्या विवरण 3: आइए हर 16ms. पर तीसरी एलईडी (लाल) फ्लैश करें

समस्या कथन 3: आइए हर 16ms. पर तीसरी एलईडी (लाल) फ्लैश करें
समस्या कथन 3: आइए हर 16ms. पर तीसरी एलईडी (लाल) फ्लैश करें
समस्या कथन 3: आइए हर 16ms. पर तीसरी एलईडी (लाल) फ्लैश करें
समस्या कथन 3: आइए हर 16ms. पर तीसरी एलईडी (लाल) फ्लैश करें
समस्या कथन 3: आइए हर 16ms. पर तीसरी एलईडी (लाल) फ्लैश करें
समस्या कथन 3: आइए हर 16ms. पर तीसरी एलईडी (लाल) फ्लैश करें
समस्या कथन 3: आइए हर 16ms. पर तीसरी एलईडी (लाल) फ्लैश करें
समस्या कथन 3: आइए हर 16ms. पर तीसरी एलईडी (लाल) फ्लैश करें

कार्यप्रणाली:

- पूर्णांक विभाजन द्वारा उच्च आवृत्ति विद्युत संकेत को कम आवृत्ति तक कम करने के लिए टाइमर 2 प्रीस्केलर का उपयोग करना;

- तुलना (सीटीसी) मोड पर क्लियर टाइमर का उपयोग करना;

- बिना रुकावट के हार्डवेयर सीटीसी मोड का उपयोग करना;

Timer2 (8 बिट) यह 0 से 255 तक गिना जाता है, उसके बाद वे ओवरफ्लो हो जाते हैं। यह मान हर घड़ी की नाड़ी पर बदलता है।

F_CPU=16MHz: घड़ी की समयावधि = 1000ms / 16000000Hz = 0.0000625ms

टाइमर गिनती = (आवश्यक देरी / घड़ी की समय अवधि) -1 = (16ms / 0.0000625ms) = 255999

16ms की देरी देने के लिए घड़ी पहले ही 255999 बार टिक कर चुकी है!

तालिका देखें विभिन्न प्रीस्केलर का उपयोग करने के परिणामों को सारांशित करता है। काउंटर मान हमेशा एक पूर्णांक होना चाहिए। आइए एक प्रीस्कूलर 1024 चुनें!

सीटीसी मोड में काउंटर को शून्य कर दिया जाता है जब काउंटर वैल्यू (टीसीएनटी 2) ओसीआर 2 ए या आईसीआर 2 से मेल खाती है। पिन PB3 TIMER2 - OC2A (आरेख देखें) का आउटपुट तुलना पिन भी है।

टाइमर/काउंटर2 कंट्रोल रजिस्टर ए - टीसीसीआर2ए बिट 7:6 - COM2A1:0 - तुलना यूनिट ए के लिए आउटपुट मोड की तुलना करें। चूंकि हमें एलईडी को टॉगल करने की आवश्यकता है, हम विकल्प चुनते हैं: ओसी 2 ए को तुलना मैच पर टॉगल करें जब भी कोई तुलना मैच होता है, तो OC2A पिन अपने आप चालू हो जाता है। किसी ध्वज बिट की जांच करने की आवश्यकता नहीं है, किसी भी व्यवधान में भाग लेने की आवश्यकता नहीं है।

Timer2/काउंटर प्रारंभ करें

TCCR2A |= (1 << COM2A0)|(1 << WGM21) // टॉगल मोड और CTC मोड में टाइमर OC2A पिन सेट करें TCCR2B |= (1 << CS22)|(1 << CS21)|(1 << CS20) // प्रीस्केलर के साथ टाइमर सेट करें = 1024 TCNT2 = 0 // इनिशियलाइज़ काउंटर OCR2A = 250 // इनिशियलाइज़ तुलना मूल्य

चरण 5: सी में एक प्रोग्राम के लिए कोड लिखना। माइक्रोकंट्रोलर फ्लैश मेमोरी में एचईएक्स फ़ाइल अपलोड करना

सी में एक प्रोग्राम के लिए कोड लिखना। माइक्रोकंट्रोलर फ्लैश मेमोरी में एचईएक्स फ़ाइल अपलोड करना
सी में एक प्रोग्राम के लिए कोड लिखना। माइक्रोकंट्रोलर फ्लैश मेमोरी में एचईएक्स फ़ाइल अपलोड करना
सी में एक प्रोग्राम के लिए कोड लिखना। माइक्रोकंट्रोलर फ्लैश मेमोरी में एचईएक्स फ़ाइल अपलोड करना
सी में एक प्रोग्राम के लिए कोड लिखना। माइक्रोकंट्रोलर फ्लैश मेमोरी में एचईएक्स फ़ाइल अपलोड करना

एकीकृत विकास मंच - एटमेल स्टूडियो का उपयोग करके सी कोड में एवीआर माइक्रोकंट्रोलर एप्लिकेशन लिखना और बनाना।

F_CPU हर्ट्ज में घड़ी की आवृत्ति को परिभाषित करता है और avr-libc पुस्तकालय का उपयोग करने वाले कार्यक्रमों में आम है। इस मामले में इसका उपयोग विलंब दिनचर्या द्वारा यह निर्धारित करने के लिए किया जाता है कि समय की देरी की गणना कैसे करें।

#ifndef F_CPU

#define F_CPU 16000000UL // कंट्रोलर क्रिस्टल फ़्रीक्वेंसी (16 मेगाहर्ट्ज AVR ATMega328P) को बता रहा है #endif

पिन पर डेटा प्रवाह नियंत्रण को सक्षम करने के लिए #include // हेडर। पिन, पोर्ट आदि को परिभाषित करता है।

पहली शामिल फ़ाइल avr-libc का हिस्सा है और इसका उपयोग आपके द्वारा काम किए जाने वाले किसी भी AVR प्रोजेक्ट में किया जाएगा। io.h आपके द्वारा उपयोग किए जा रहे CPU को निर्धारित करेगा (यही कारण है कि आप संकलन करते समय भाग निर्दिष्ट करते हैं) और बदले में हम जिस चिप का उपयोग कर रहे हैं उसके लिए उपयुक्त IO परिभाषा शीर्षलेख शामिल करें। यह बस आपके सभी पिनों, बंदरगाहों, विशेष रजिस्टरों आदि के लिए स्थिरांक को परिभाषित करता है।

#शामिल करें // इंटरप्ट को सक्षम करने के लिए हेडर

अस्थिर uint8_t tot_overflow; // वैश्विक चर अतिप्रवाह की संख्या की गणना करने के लिए

समस्या वक्तव्य की पद्धति: फ्लैश फर्स्ट (हरा) एलईडी प्रत्येक 50 एमएस

- पूर्णांक विभाजन द्वारा उच्च आवृत्ति विद्युत संकेत को कम आवृत्ति तक कम करने के लिए टाइमर0 प्रीस्केलर का उपयोग करना;

- Timer0 के ओवरफ्लो होने पर हर बार रुकावट का उपयोग करना;

शून्य टाइमर0_इनिट () // टाइमर 0 को इनिशियलाइज़ करें, इंटरप्ट और वेरिएबल

{ टीसीसीआर0बी |= (1 << सीएस02); // प्रीस्कूलर के साथ टाइमर सेट करें = २५६ टीसीएनटी० = ०; // इनिशियलाइज़ काउंटर TIMSK0 |= (1 << TOIE0); // अतिप्रवाह सक्षम करें इंटरप्ट सेई (); // वैश्विक व्यवधान को सक्षम करें tot_overflow = 0; // ओवरफ्लो काउंटर वेरिएबल को इनिशियलाइज़ करें}

समस्या विवरण की पद्धति: फ्लैश सेकेंड एलईडी (नीला) प्रत्येक 1s

- पूर्णांक विभाजन द्वारा उच्च आवृत्ति विद्युत संकेत को कम आवृत्ति तक कम करने के लिए टाइमर 1 प्रीस्केलर का उपयोग करना;

- तुलना (सीटीसी) मोड पर क्लियर टाइमर का उपयोग करना;

- सीटीसी मोड के साथ इंटरप्ट्स का उपयोग करना;

शून्य टाइमर1_इनिट () // टाइमर 1, इंटरप्ट और वैरिएबल को इनिशियलाइज़ करें {TCCR1B | = (1 << WGM12) | (1 << CS12); // प्रीस्केलर = 256 और सीटीसी मोड टीसीएनटी 1 = 0 के साथ टाइमर सेट करें; // काउंटर शुरू करें OCR1A = 62500; // आरंभिक तुलना मूल्य TIMSK1 |= (1 << OCIE1A); // इंटरप्ट की तुलना सक्षम करें}

समस्या वक्तव्य की पद्धति: फ्लैश तीसरे एलईडी (लाल) हर 16ms

- पूर्णांक विभाजन द्वारा उच्च आवृत्ति विद्युत संकेत को कम आवृत्ति तक कम करने के लिए टाइमर 2 प्रीस्केलर का उपयोग करना;

- तुलना (सीटीसी) मोड पर क्लियर टाइमर का उपयोग करना;

- बिना रुकावट के हार्डवेयर सीटीसी मोड का उपयोग करना;

शून्य टाइमर2_इनिट () // टाइमर 2 प्रारंभ करें {टीसीसीआर 2 ए | = (1 << COM2A0) | (1 << WGM21); // टॉगल मोड और सीटीसी मोड में टाइमर OC2A पिन सेट करें TCCR2B |= (1 << CS22)|(1 << CS21)|(1 << CS20); // प्रीस्कूलर = १०२४ टीसीएनटी२ = ० के साथ टाइमर सेट करें; // प्रारंभ काउंटर OCR2A = २५०; // तुलना मूल्य शुरू करें}

TCNT0 ओवरफ्लो होने पर TIMER0 ओवरफ्लो इंटरप्ट सर्विस रूटीन को कॉल किया जाता है:

आईएसआर (TIMER0_OVF_vect)

{ टोट_ओवरफ्लो++; // ओवरफ्लो की संख्या पर नज़र रखें}

जब भी कोई मैच होता है तो इस ISR को निकाल दिया जाता है, यहां टॉगल का नेतृत्व किया जाता है:

ISR (TIMER1_COMPA_vect){ PORTC ^= (1 << 1); // यहां टॉगल का नेतृत्व किया}

मुख्य अंतर (शून्य)

{ डीडीआरबी |= (1 << 0); // कनेक्ट 1 (हरा) PB0 DDRC को पिन करने के लिए नेतृत्व किया |= (1 << 1); // कनेक्ट 2 (नीला) पीसी 1 डीडीआरबी को पिन करने के लिए नेतृत्व किया | = (1 << 3); // कनेक्ट 3 (लाल) PB3 (OC2A) टाइमर 0_init () को पिन करने के लिए नेतृत्व किया; // टाइमर को प्रारंभ करें टाइमर 1_इनिट (); // टाइमर 1 टाइमर 2_इनिट शुरू करें (); // टाइमर 2 को इनिशियलाइज़ करें जबकि (1) // लूप हमेशा के लिए {

अगर Timer0 12 बार ओवरफ्लो हो गया है, तो 12 * 4.096ms = 49.152ms बीत चुके होंगे। 13वें पुनरावृत्ति में, हमें 50ms - 49.152ms = 0.848ms की देरी की आवश्यकता है। इस प्रकार, 13वें पुनरावृत्ति में, हम केवल टाइमर को 53 तक गिनने की अनुमति देते हैं, और फिर इसे रीसेट करते हैं।

अगर (tot_overflow>= 12) // जांचें कि क्या नहीं। ओवरफ्लो का = 12 नोट: '>=' का प्रयोग किया जाता है

{ if (TCNT0 >= 53) // जांचें कि क्या टाइमर की संख्या 53 तक पहुंच गई है { PORTB ^= (1 << 0); // एलईडी TCNT0 = 0 को टॉगल करता है; // रीसेट काउंटर tot_overflow = 0; // ओवरफ्लो काउंटर रीसेट करें } } } }

माइक्रोकंट्रोलर फ्लैश मेमोरी में HEX फाइल अपलोड करना:

डॉस प्रॉम्प्ट विंडो में टाइप करें कमांड:

avrdude –c [प्रोग्रामर का नाम] –p m328p –u –U फ़्लैश: w: [आपकी हेक्स फ़ाइल का नाम] मेरे मामले में यह है: avrdude –c ISPProgv1 –p m328p –u –U फ़्लैश:w:Timers.hex

यह कमांड माइक्रोकंट्रोलर की मेमोरी में हेक्स फाइल लिखता है। माइक्रोकंट्रोलर फ्लैश मेमोरी बर्निंग के विस्तृत विवरण के साथ वीडियो देखें:

माइक्रोकंट्रोलर फ्लैश मेमोरी बर्निंग…

ठीक! अब, माइक्रोकंट्रोलर हमारे कार्यक्रम के निर्देशों के अनुसार काम करता है। चलो पता करते हैं!

चरण 6: विद्युत परिपथ बनाना

विद्युत परिपथ बनाना
विद्युत परिपथ बनाना
विद्युत परिपथ बनाना
विद्युत परिपथ बनाना
विद्युत परिपथ बनाना
विद्युत परिपथ बनाना

योजनाबद्ध आरेख के अनुसार घटकों को कनेक्ट करें।

सिफारिश की: