در قسمت قبل در مورد تایمر نگهبان مستقل صحبت کردیم. در این بخش میخواهیم تایمر نگهبان پنجرهای یا WWDG را بررسی کنیم پس با سیسوگ همراه باشید. در WWDG، یک شرط دیگر نیز برای ریست شدن وجود دارد. برای این تایمر نگهبان علاوه بر مقدار ابتدایی شمارنده، یک مقدار پنجره نیز تعریف میشود. درصورتیکه هنگام بازنشانی شمارنده، مقدار آن بزرگتر از مقدار پنجره باشد، میکروکنترلر ریست خواهد شد. یعنی اینکه برای جلوگیری از ریست توسط WWDG، باید مقدار شمارنده را قبل ازآنکه از 64 یا 0x40 (در مبنای 16) کمتر شود، و پس از آنکه از مقدار پنجره کمتر شد، بازنشانی کنیم. بنابراین عمل بازنشانی حتماً باید در یک بازه یا پنجره زمانی مشخص صورت گیرد و به همین دلیل است که به این تایمر نگهبان پنجرهای گفته میشود.
شمارنده نزولی 7 بیتی واحد WWDG، حداکثر میتواند روی عدد 127 تنظیم شود و حداقل مقدار آن نیز مقدار پنجره است. همچنین مقدار Window یا پنجره باید عددی در بازه 64 تا 127 باشد.
پس از فعالسازی این واحد، امکان غیر فعالسازی آن توسط برنامه وجود ندارد و تنها در صورت ریست شدن میکرو فعال میشود. پس از ریست دوباره میتواند توسط برنامه فعال شود. از WWDG نیز مانند IWDG برای خلاص کردن میکروکنترلر هنگام وقوع اشکالات پیشبینینشده استفاده میشود. کاربرد دیگر آن نیز، استفاده برای زمان Time_out توابع است. یک کاربرد نمونه آن زمانی است که میکرو دچار خطا شده باشد و مرتب مقدار شمارنده تایمر نگهبان را بازنشانی کند. با توضیحات دادهشده میدانیم که در این وضعیت استفاده از تایمر IWDG مشکل را حل نمیکند، اما درصورتیکه از تایمر نگهبان پنجرهای استفاده شود، به دلیل بازنشانی شمارنده قبل از رسیدن به پنجره، میکروکنترلر ریست خواهد شد.
در ادامه این واحد را در یک پروژه ساده راهاندازی میکنیم.
ایجاد پروژه
مثل بخش قبلی قسمت دیباگ و کلاک و USART1 را تنظیم میکنیم. بعدازآن باید پین PB0 را روی ورودی و در حالت pull-up تنظیم کنیم. سپس تایمر نگهبان پنجرهای را فعال میکنیم و تقسیمکننده کلاک آن را روی عدد دلخواه (مثلاً 8) تنظیم میکنیم. و مقدار شمارنده آن را 127 و مقدار پنجره را 90 قرار میدهیم:
اکنون تنظیمات درایورها را نیز مانند قبل انجام میدهیم و وارد بخش کدنویسی میشویم.
نوشتن کد پروژه
برای این پروژه نیز اعمال مربوط به ریدایرکت را انجام میدهیم. همچنین از همان تابع نمایش منبع ریست میکرو استفاده میکنیم. مانند پروژه قبل در تابع int main() ابتدا با تابعی که نوشتیم منبع ریست را نمایش میدهیم و سپس مثل قبل همه پرچمهای ریست را پاک میکنیم. سپس دو متغیر برای شمارش تعریف میکنیم:
1 | uint32_t i, count = 0; //test counters |
برای داشتن معیار دیگری برای دانستن ادامه کار میکرو یا ریست شدن آن، میتوانیم کد زیر را برای شمارش، در حلقه while(1) بنویسیم:
1 2 3 4 5 6 7 8 | /* printing the counter nearly every second */ i++; if(i > 500000) { count++; i = 0; printf("count is: %d\r\n", count); } |
در همین حلقه while(1)، یک شرط برای بازنشانی مقدار شمارندهی IWDG تعریف میکنیم، که در صورت عدم وقوع شمارنده به صفر رسیده و ریست اتفاق بیافتد:
1 2 3 4 5 6 7 8 | /* if push button connected to PB0 is pushed, then the WWDG counter wont be reset */ if(((LL_GPIO_ReadInputPort(GPIOB)) & (1<<0)) != 0) { if(LL_WWDG_GetCounter(WWDG) < 91) { LL_WWDG_SetCounter(WWDG, 127); } } |
اکنون باید یک کلید یا push-button به پایه PA5 متصل کنیم و برنامه را روی میکرو دانلود کنیم. نتیجه اجرا را در ترمینال سریال میبینیم:
میبینیم که اگر کلید PB0 را فشار ندهیم، میکرو به شمارش ادامه میدهد و در صورتی که کلید را فشار دهیم، میکرو ریست خواهد شد. در واقع فرکانس کلاک و سرعت شمارنده تایمر نگهبان در اینجا بسیار بالاست. با فشرده نگهداشتن کلید به مدت کوتاهی، شرط بازنشانی اجرا نخواهد شد که موجب ریست میکرو میشود. همچنین میتوان با تغییر عدد 91 و افزایش آن مشاهده کرد که در صورتی که عمل بازنشانی شمانده تایمر نگهبان زود انجام شود، میکرو ریست میشود.