সাধারণ আইএসআরের মতো এভিআর ওয়াচডগ ব্যবহার করুন


17

আমি এটিটিইএনএক্স 5 সিরিজে ওয়াচডগ টাইমারের চারপাশে আমার মাথা মোড়ানোর চেষ্টা করছি। সুতরাং আমি যে জিনিসগুলি পড়েছি তা দেখে মনে হয়েছে আপনি প্রোগ্রামটিকে এন সেকেন্ডের জন্য নির্দিষ্ট কিছু করার জন্য এটি ব্যবহার করতে পারেন তবে কীভাবে বাস্তবে প্রদর্শিত হয়নি। অন্যরা মনে হয়েছিল এটি কেবল চিপটিকে পুনরায় সেট করবে যদি না এর মধ্যে কোড পুনরায় সেট করা থাকে তবে এর মধ্যে এমন কিছু গণনা করা হয় (যা "সাধারণ" ব্যবহার বলে মনে হয়)।

আপনি যেমন TIMER1_COMPA_vect বা অনুরূপ ডাব্লুডিটি ব্যবহার করার কোন উপায় আছে কি? আমি লক্ষ্য করেছি যে এটিতে 1 সেকেন্ডের টাইমআউট মোড রয়েছে এবং আমি আমার কোডটিতে প্রতি 1 সেকেন্ডে কিছু ঘটতে (এবং পছন্দমতো ঘুমিয়ে থাকি) ব্যবহার করতে সক্ষম হতে চাই really

থটস?

* আপডেট: * যেহেতু এটি জিজ্ঞাসা করা হয়েছিল, এটিটিটিএনএক্স 5 ডেটাশিটের 8.4 অনুচ্ছেদটি উল্লেখ করছি । এমন নয় যে আমি এটি পুরোপুরি বুঝতে পেরেছি, যা আমার সমস্যা ...


1
বাক্সের বাইরে চিন্তা করার জন্য +1। আপনি AVR এর জন্য ডেটাশিটের সাথে একটি লিঙ্ক যুক্ত করলে অতিরিক্ত থাম্বস আপ হয়।
জিপ্পি

উত্তর:


23

আপনি অবশ্যই পারেন। ডেটাশিট অনুসারে, ওয়াচডোগ টাইমারটি এমসইউটিকে পুনরায় সেট করতে সেট করতে পারে বা ট্রিগার হওয়ার সাথে সাথে কোনও বাধা সৃষ্টি করতে পারে। দেখে মনে হচ্ছে আপনি বাধাপ্রাপ্ত সম্ভাবনার পক্ষে আরও আগ্রহী।

ডাব্লুডিসিটি সাধারণ টাইমারের চেয়ে সেটআপ করা ঠিক একই কারণে এটি কার্যকর হিসাবে কার্যকর: কম বিকল্প options এটি অভ্যন্তরীণভাবে ক্যালিব্রেটেড 128kHz ঘড়িতে চালিত হয় যার অর্থ এটির সময়টি এমসইউর মূল ঘড়ির গতি দ্বারা প্রভাবিত হয় না। এটি জাগ্রত উত্স সরবরাহ করতে গভীর ঘুমের মোডের সময় চলতেও পারে।

আমি বেশ কয়েকটি ডেটাশিটের উদাহরণ এবং পাশাপাশি কিছু কোড ব্যবহার করেছি (সি তে)।

অন্তর্ভুক্ত ফাইল এবং সংজ্ঞা

শুরু করার জন্য, আপনি সম্ভবত জিনিসগুলি কাজ করার জন্য নিম্নলিখিত দুটি শিরোনাম ফাইল অন্তর্ভুক্ত করতে চাইবেন:

#include <avr/wdt.h>        // Supplied Watch Dog Timer Macros 
#include <avr/sleep.h>      // Supplied AVR Sleep Macros

এছাড়াও, আমি ম্যাক্রো <_BV (বিআইটি)> ব্যবহার করি যা নীচের হিসাবে মানক AVR শিরোনামগুলির মধ্যে একটিতে সংজ্ঞায়িত হয়েছে (যা আপনার পক্ষে আরও পারিবারিক হতে পারে):

#define _BV(BIT)   (1<<BIT)

কোডের সূচনা

যখন এমসিইউ প্রথম শুরু করা হয়, আপনি সাধারণত I / O শুরু করতে পারেন, টাইমার সেট আপ করুন ইত্যাদি কোথাও কোথাও ডাব্লুডিটি পুনরায় সেট করার কারণ হয়নি তা নিশ্চিত করার জন্য এটি ভাল সময় কারণ এটি আপনার প্রোগ্রামকে সামনে রেখে পুনরায় কাজ করতে পারে, একটি অস্থির লুপ

if(MCUSR & _BV(WDRF)){            // If a reset was caused by the Watchdog Timer...
    MCUSR &= ~_BV(WDRF);                 // Clear the WDT reset flag
    WDTCSR |= (_BV(WDCE) | _BV(WDE));   // Enable the WD Change Bit
    WDTCSR = 0x00;                      // Disable the WDT
}

ডাব্লুডিটি সেটআপ

তারপরে, আপনি বাকি চিপটি সেটআপ করার পরে, ডাব্লুডিটি আবার করুন। ডাব্লুডিটি সেট আপ করার জন্য "সময়সীমাবদ্ধ ক্রম" দরকার তবে এটি করা সত্যিই সহজ ...

// Set up Watch Dog Timer for Inactivity
WDTCSR |= (_BV(WDCE) | _BV(WDE));   // Enable the WD Change Bit
WDTCSR =   _BV(WDIE) |              // Enable WDT Interrupt
           _BV(WDP2) | _BV(WDP1);   // Set Timeout to ~1 seconds

অবশ্যই, আপনার বাধা এই কোডের সময় অক্ষম করা উচিত। পরে এগুলি পুনরায় সক্ষম করতে ভুলবেন না!

cli();    // Disable the Interrupts
sei();    // Enable the Interrupts

ডাব্লুডিটি বিঘ্নিত পরিষেবার রুটিন সম্পর্কে চিন্তার পরবর্তী বিষয় হ'ল ডাব্লুডিটি আইএসআর পরিচালনা করা R এটি যেমন করা হয়:

ISR(WDT_vect)
{
  sleep_disable();          // Disable Sleep on Wakeup
  // Your code goes here...
  // Whatever needs to happen every 1 second
  sleep_enable();           // Enable Sleep Mode
}

MCU ঘুম

ডাব্লুডিটি আইএসআরের অভ্যন্তরে এমসিইউ রাখার পরিবর্তে, আমি আইএসআর শেষে কেবল স্লিপ মোডটি সক্রিয় করার পরামর্শ দিই, তারপরে MAIN প্রোগ্রামটি MCU কে ঘুমাতে দেবে। এইভাবে, প্রোগ্রামটি আসলে ঘুমানোর আগে আইএসআর ছেড়ে চলেছে, এবং এটি জেগে উঠবে এবং সরাসরি ডাব্লুডিটি আইএসআরে ফিরে যাবে।

// Enable Sleep Mode for Power Down
set_sleep_mode(SLEEP_MODE_PWR_DOWN);    // Set Sleep Mode: Power Down
sleep_enable();                     // Enable Sleep Mode  
sei();                              // Enable Interrupts 

/****************************
 *  Enter Main Program Loop  *
 ****************************/
 for(;;)
 {
   if (MCUCR & _BV(SE)){    // If Sleep is Enabled...
     cli();                 // Disable Interrupts
     sleep_bod_disable();   // Disable BOD
     sei();                 // Enable Interrupts
     sleep_cpu();           // Go to Sleep

 /****************************
  *   Sleep Until WDT Times Out  
  *   -> Go to WDT ISR   
  ****************************/

   }
 }

বাহ ... খুব বিস্তারিত ধন্যবাদ! আমি ঘুমের অংশটি থেকে একটু বিভ্রান্ত হয়েছি যেখানে আপনি মূল লুপটি দেখান (যদি (এমসিইউসিআর & _বিভি (এসই)) {// যদি ঘুম সক্ষম হয় ... ইত্যাদি) আমি কেন বিভ্রান্ত হয়ে পড়েছি মূল চেহারাতে আপনি কেন ক্রমাগত অক্ষম এবং সক্ষম বাধা। এবং এই বিভাগের শীর্ষে অংশ (সেট_স্লিপ_মোড (SLEEP_MODE_PWR_DOWN);) কোথায় চালানোর কথা?
অ্যাডাম হাইল

ঠিক আছে, "সেট_স্লিপ_মোড (মোডে)" অংশটি মূল লুপের আগে মূলত হওয়া উচিত, আদর্শভাবে অন্য আরম্ভের কোডে যেখানে আপনি আই / ও পোর্টস, টাইমারস সেটআপ করেন ইত্যাদি আপনার সত্যিকারের সক্রিয় করার দরকার নেই (); এই মুহুর্তে, এটি আপনার প্রথম ডাব্লুডিটি ট্রিগার পরে সম্পন্ন হবে। মূল লুপের ভিতরে, এই স্লিপ কোডটি কেবলমাত্র যদি সক্রিয় করা হয় তবে এটি কার্যকর করা হবে, এবং সেখানে বাধাগুলি অক্ষম / পুনরায় সক্ষম করা সম্পূর্ণভাবে প্রয়োজনীয় নয়, কেবলমাত্র যদি আপনি ঘুম_বড_ডিজিয়েবল () করছেন; এই সম্পূর্ণ আইএফ বিবৃতিটি আপনি সেখানে চালিত অন্যান্য কোডের পরে মেইন লুপের নীচে (তবে এখনও ভিতরে) থাকতে পারে।
কার্ট ই। ক্লোথিয়র

ঠিক আছে ... এটি এখন আরও অর্থবোধ করে। আমি শেষ যে বিষয়টি নিয়ে অস্পষ্ট হয়েছি তা হ'ল এই "সময়সীমা" কী ...
অ্যাডাম হেইল

সাইড নোট: আমি জানি তুমি কেন ঘুম যেতে চাই, কিন্তু আমি অনুমান আপনি না আছে যখন WDT ব্যবহার কিভাবে?
অ্যাডাম হেইল

ডেটাশিটের এই ছোট্ট বিভাগটি একবার দেখুন: 8.4.1। মূলত, ডাব্লুডিটি রেজিস্টার পরিবর্তন করতে, আপনাকে পরিবর্তন বিট সেট করতে হবে এবং তারপরে এতগুলি ঘড়ির চক্রের মধ্যে যথাযথ ডাব্লুডিটিসিআর বিট সেট করতে হবে। আমি ডাব্লুডিটি সেটআপ বিভাগে সরবরাহিত কোডটি প্রথমে ডাব্লুডি পরিবর্তন বিট সক্ষম করে এটি করে। এবং না, আপনার ঘুমের কার্যকারিতা একেবারেই ডাব্লুডিটি-র সাথে ব্যবহার করতে হবে না। আপনি যে কোনও কারণেই এটি স্ট্যান্ডার্ড টাইমড বাধা উত্স হতে পারে।
কার্ট ই। ক্লোথিয়ার

1

ডাটাশিট অনুসারে এটি সম্ভব। আপনি উভয় সক্ষম করতে পারেন, একটি বাধা এবং পুনরায় সেট। যদি উভয়ই সক্ষম হয়, তবে প্রথম ওয়াচডগের সময়সীমা বাধাগুলি ট্রিগার করবে যা বাধাপ্রাপ্ত সক্ষম বিটটিকে আনসেট করার জন্য (বাধা অক্ষম) তৈরি করে। পরের টাইমআউটটি আপনার সিপিইউটিকে পুনরায় সেট করবে। আপনি যদি ইন্টারপটটিকে কার্যকর করার পরে সরাসরি সক্ষম করে থাকেন তবে পরবর্তী সময়সীমা (আবার) কেবল একটি বাধা সৃষ্টি করবে।

আপনি কেবল বাধা সক্ষম করতে পারবেন এবং পুনরায় সেট করতে সক্ষম হবেন না। প্রতিবার বিঘ্নিত হওয়ার সাথে সাথে আপনাকে ডাব্লুআইডিআই বিট সেট করতে হবে।


হুঁ .... আমি মনে করি এটি বোধগম্য হয়। আমি এটি একটি শট দিতে হবে। আমি সর্বদা জিনিসগুলি তাদের উদ্দেশ্যে নয় এমন উদ্দেশ্যে ব্যবহার করা পছন্দ করি :)
অ্যাডাম হেইল

আসলে আমি মনে করি এটি একটি চতুর নকশা। ওয়াচডগ কার্যকারিতা রাখার সময় আপনাকে একটি টাইমার বাঁচায়।
টম এল।

2
ডাব্লুডিটি-র এই প্রাথমিক সময়সীমা এবং পরবর্তী বাধাদানকে এমন কিছু অ্যাপ্লিকেশনগুলির সুবিধার জন্য ব্যবহার করা যেতে পারে যা ডাব্লুডিটিকে আসল হ্যাঙ্গআপ পুনরুদ্ধারের জন্য সক্ষম করে। "অপ্রত্যাশিত সময়সীমা" যখন ঘটেছিল তখন কোডটি কী করার চেষ্টা করছিল তা নির্ধারণের জন্য ডাব্লুডিটি আইএসআরের স্ট্যাকযুক্ত রিটার্ন ঠিকানাটি দেখতে পারেন।
মাইকেল কারাস

1

এটি উপরে এবং অন্য কোথাও প্রস্তাবিত চেয়ে অনেক সহজ।

যতক্ষণ না WDTONফিউজ প্রোগ্রাম না করা হয় (এটি ডিফল্টরূপে প্রোগ্রাম করা হয় না), তবে আপনার কেবলমাত্র ...

  1. ওয়াচডগ নিয়ন্ত্রণ রেজিস্ট্রে ওয়াচডোগ ইন্ট্র্রেপ সক্ষম বিট এবং টাইমআউট সেট করুন।
  2. বাধা সক্ষম করুন।

এখানে একটি কোড উদাহরণ দেওয়া হয়েছে যা প্রতি 16 মাইল প্রতি একবার আইএসআর কার্যকর করবে ...

ISR(WDT_vect) {
   // Any code here will get called each time the watchdog expires
}

void main(void) {
   WDTCR =  _BV(WDIE);    // Enable WDT interrupt, leave existing timeout (default 16ms) 
   sei();                                           // Turn on global interrupts
   // Put any code you want after here.
   // You can also go into deep sleep here and as long as 
   // global interrupts are eneabled, you will get woken 
   // up when the watchdog timer expires
   while (1);
}

সত্যিই এটি। যেহেতু আমরা কখনই নজরদারি পুনরায় সেট করতে সক্ষম করি না, তাই এটি নিষ্ক্রিয় করার জন্য আমাদের সময়সীম ক্রমগুলি নিয়ে কখনই গোলমাল করতে হবে না। আইএসআর ডাকা হলে ওয়াচডগ বিঘ্নিত পতাকাটি স্বয়ংক্রিয়ভাবে সাফ হয়ে যায়।

আপনি যদি প্রতি 1 সেকেন্ডের চেয়ে আলাদা সময়কাল চান তবে উপযুক্ত মানগুলি এখানে সেট করতে আপনি এখানে এই মানগুলি ব্যবহার করতে পারেন WDTCR...

এখানে চিত্র বর্ণনা লিখুন

নোট করুন যে টাইমআউটটি পরিবর্তন করতে আপনার সময়সীমা অনুসরণ করতে হবে। এখানে কোডটি সময়সীমা 1 সেকেন্ডে সেট করে ...

   WDTCR = _BV(WDCE) | _BV(WDE);                   // Enable changes
   WDTCR = _BV(WDIE) | _BV( WDP2) | _BV( WDP1);    // Enable WDT interrupt, change timeout to 1 second

সেটআপ করার সময় সময়সীমা অনুসরণ না করা কোডের একটি লাইন সংরক্ষণ করে - একটি পঠন-পরিবর্তন করুন-লেখার ক্রিয়া write প্রাথমিক ক্রমটি ডাটাশিটে সুপারিশ করা হয় "যদি ওয়াচডগ দুর্ঘটনাক্রমে সক্ষম হয়ে থাকে, উদাহরণস্বরূপ কোনও রানওয়ে পয়েন্টার বা বাদামী আউট শর্ত দ্বারা" এবং আমার বাকী কোডটি ডাব্লুডিটি ব্যবহার করে স্লিপ মোডের সাথে সংযুক্ত করে নির্দিষ্ট করা হয়, যেমন অনুরোধ করা হয়েছিল ওপি। আপনার সমাধানটি সহজ নয়, আপনি কেবলমাত্র প্রস্তাবিত / প্রয়োজনীয় বয়লার প্লেট কোডটি উপেক্ষা করেছেন।
কুর্ট ই। ক্লোটিয়ার

@ কার্ট.ক্লোটিয়ার দুঃখিত, সর্বাধিক সহজ উদাহরণ দেওয়ার চেষ্টা করছি!
bigjosh
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.