در قسمت قبل از سری آموزش STM32 با توابع HAL، در مورد PWM و نحوه تولید شکل موج توسط آن، صحبت شد. در این قسمت، تایمرهای نگهبان مستقل و پنجرهای (IWDG و WWDG) را بررسی میکنیم. با سیسوگ همراه باشید.
تایمر نگهبان مستقل (Independent watchdog)
یکی از تایمرهای نگهبان، واحد IWDG است که شامل یک شمارنده نزولی 12 بیتی میباشد که با کلاک داخلی کمسرعت میکرو (LSI) و مستقل از کلاک سیستم کار میکند. همچنین یک تقسیمکننده کلاک در این واحد وجود دارد که میتوان بهوسیله آن به نرخ کلاک موردنیاز دست پیدا کرد.
پس از فعالسازی این واحد، امکان غیر فعالسازی آن توسط برنامه وجود ندارد و درصورتیکه قبل از صفر شدن شمارنده آن، مقدار شمارش بازنویسی نشود، میکروکنترلر ریست خواهد شد. از این قابلیت برای خلاص کردن میکروکنترلر هنگام وقوع اشکالات پیشبینینشده استفاده میشود. کاربرد دیگر آن نیز، استفاده برای زمان Time_out توابع است.
در ادامه تایمر نگهبان مستقل IWDG را در یک پروژه ساده راهاندازی میکنیم.
در این قسمت آموزش از میکروکنترلر STM32F103RET6 استفاده میکنیم. اگرچه این میکروکنترلر از بسیاری جهات مشابه میکروکنترلر STM32F103C8T6 است، اما تفاوتهایی نیز دارند. بااینوجود کد نوشتهشده برای STM32F103C8T6، بر روی STM32F103RET6 نیز قابلاجرا است.
ایجاد پروژه
مثل بخشهای قبلی قسمت کلاک و USART1 را تنظیم میکنیم و دیباگ را برای این بورد در حالت JTAG(5 pins) انتخاب میکنیم. بعدازآن باید یک پایه (مثلاً PA5) را بهعنوان ورودی و در حالت pull-up تنظیم کنیم. سپس از بخش System Core، IWDG را فعال میکنیم و تقسیمکننده کلاک آن را روی یک عدد دلخواه (مثلاً 16) تنظیم و مقدار شمارنده آن را در مقدار پیشفرض 4095، باقی میگذاریم.
تنظیم IWDG.
همانطور که قبلاً گفته شد، کلاک این واحد از طریق مدار RC داخلی (با فرکانس 40KHz) تأمین میشود.
منبع کلاک IWDG.
اکنون میتوانیم به سراغ کد پروژه برویم.
نوشتن کد پروژه
مانند پروژههای پیشین، اعمال مربوط به ریدایرکت کردن USART1 را انجام میدهیم. بنابراین در بدنه تابع int main، قبل از حلقه while(1)، کد زیر را برای راهاندازی ریتارگت usart، نمایش منبع ریست و همچنین پاک کردن پرچمهای مربوط به ریست، مینویسیم. همچنین یک متغیر برای شمارش و یک متغیر برای زمانبندی تعریف میکنیم:
1 2 3 4 5 6 | RetargetInit(&huart1); // initializing the stdio retargetting show_reset_sources(); // print the reset sources __HAL_RCC_CLEAR_RESET_FLAGS(); // clear the reset flags uint32_t count = 0; // variable for counting |
اکنون کد زیر را در بدنه حلقه while(1) مینویسیم:
1 2 3 4 5 6 7 8 9 10 11 12 | /* if PA5 is pressed, then IWDG counter will be reset */ if (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_5) == 0) { HAL_IWDG_Refresh(&hiwdg); HAL_Delay(250); printf("IWDG counter reset\r\n"); HAL_IWDG_Refresh(&hiwdg); } /* print the count value*/ printf("count: %d\r\n", count++); HAL_Delay(145); |
در این قطعه کد، ابتدا شرط فشرده بودن کلید چک میشود و در صورت برقراری این شرط، شمارنده IWDG، بازنشانی خواهد شد و از ابتدا شروع به شمارش خواهد کرد. در غیر این صورت نیز مقدار متغیر count چاپشده و افزایش داده میشود. زمانبندیهای برنامه بهصورتی انجامشده است که اگر تا زمانی که count مقدار 10 را شمارش میکند (حدود 1.5 ثانیه)، کلید فشرده نشود، میکرو بهوسیله IWDG ریست شود.
نتیجه اجرای برنامه را میتوانیم در ترمینال سریال مشاهده کنیم:
نتیجه عملکرد IWDG در ترمینال سریال.
تایمر نگهبان پنجرهای (Window watchdog)
یکی دیگر از تایمرهای نگهبان، تایمر نگهبان پنجرهای است و برای این تایمر نگهبان علاوه بر مقدار ابتدایی شمارنده، یک مقدار پنجره نیز تعریف میشود. درصورتیکه هنگام بازنشانی شمارنده، مقدار آن بزرگتر از مقدار پنجره باشد، میکروکنترلر ریست خواهد شد. یعنی اینکه برای جلوگیری از ریست توسط WWDG، باید مقدار شمارنده را قبل ازآنکه از 64 یا 0x40 (در مبنای 16) کمتر شود، و پس ازآنکه از مقدار پنجره کمتر شد، بازنشانی کنیم. بنابراین عمل بازنشانی حتماً باید در یک بازه یا پنجره زمانی مشخص صورت گیرد و به همین دلیل است که به این تایمر نگهبان پنجرهای گفته میشود.
شمارنده نزولی در WWDG. پنجره گفته شده را میتوان در این شکل مشاهده کرد.
شمارنده نزولی 7 بیتی واحد WWDG، حداکثر میتواند روی عدد 127 تنظیم شود و حداقل مقدار آن نیز مقدار پنجره است. همچنین مقدار Window یا پنجره باید عددی در بازه 64 تا 127 باشد.
بلوک دیاگرام واحد IWDG.
پس از فعالسازی این واحد، امکان غیر فعالسازی آن توسط برنامه وجود ندارد و تنها در صورت ریست شدن میکرو فعال میشود. پس از ریست دوباره میتواند توسط برنامه فعال شود. از WWDG نیز مانند IWDG برای خلاص کردن میکروکنترلر هنگام وقوع اشکالات پیشبینینشده استفاده میشود. کاربرد دیگر آن نیز، استفاده برای زمان Time_out توابع است. یک کاربرد نمونه آن زمانی است که میکرو دچار خطا شده باشد و مرتب مقدار شمارنده تایمر نگهبان را بازنشانی کند. با توضیحات دادهشده میدانیم که در این وضعیت استفاده از تایمر IWDG مشکل را حل نمیکند، اما درصورتیکه از تایمر نگهبان پنجرهای استفاده شود، به دلیل بازنشانی شمارنده قبل از رسیدن به پنجره، میکروکنترلر ریست خواهد شد.
در ادامه این واحد را در پروژه راهاندازی میکنیم.
تغییرات پیکربندی
برای استفاده از WWDG، میتوانیم بهسادگی تنظیمات پیکربندی پروژه قبلی را تغییر دهیم و واحد WWDG را فعال کنیم. این واحد را مشابه IWDG از بخش Systme core انتخاب و بهصورت زیر تنظیم میکنیم:
تنظیم WWDG.
در تصویر بالا میبینیم که مقدار window روی 80 و مقدار اولیه شمارش، بیشترین حد خود، یعنی، 127 انتخابشده است. با توجه به توضیحات دادهشده در مورد WWDG، با تنظیمات انجامشده، زمان بازنشانی مقدار شمارنده WWDG باید بعد از 47 شمارش (یعنی بعد از رسیدن به 80) صورت گیرد.
اکنونکه واحد WWDG را تنظیم کردهایم، مجدداً به سراغ کد میرویم.
کد WWDG
برای استفاده از واحد WWDG، میتوانیم از بخشی از کد نوشتهشده در قسمت قبل استفاده کنیم. اما نیاز داریم که قطعه کد درون بدنه while(1) را کامنت کنیم. قبل از حلقه while(1) نیز یک متغیر برای ایجاد زمانبندیهای موردنیاز تعریف میکنیم:
1 | uint32_t i = 0; // variable for timing |
اکنون کد زیر را در بدنه حلقه while(1) مینویسیم:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | HAL_IWDG_Refresh(&hiwdg); // the IWDG will not reset the MCU /* printing the counter nearly every second */ i++; if(i > 600000) { count++; i = 0; printf("count is: %lu\r\n", count); } /* if push button connected to PB0 is pushed, then the WWDG counter wont be reset */ if(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_5) == 0) { if(hwwdg.Instance->CR <= (255 - (hwwdg.Init.Counter - hwwdg.Init.Window))) { HAL_WWDG_Refresh(&hwwdg); } } |
در خط اول، کد بازنشانی شمارنده IWDG را نوشتهایم. زیرا در غیر این صورت میکرو توسط IWDG ریست خواهد شد. بعدازآن بهوسیله متغیر i، بهطور تقریبی زمانبندی حدود 1 ثانیه را برای چاپ و افزایش مقدار متغیر count، ایجاد کردهایم. در آخر نیز شرط بازنشانی شمارنده WWDG (یعنی فعال بودن کلید متصل به PA5) چک شده است و در صورت برقراری این شرط، شمارنده WWDG در زمان مناسب و درون پنجره، ریست خواهد شد.
پس از کامپایل و دانلود کد، نتیجه اجرای کد را در ترمینال سریال مشاهده میکنیم:
نتیجه عملکرد WWDG در ترمینال سریال.
در این قسمت از سری آموزش STM32 با توابع HAL، تایمرهای نگهبان مستقل و پنجرهای (IWDG و WWDG) را بررسی کردیم. در قسمت بعدی، در مورد حالت Encoder تایمر و کاربرد آن صحبت خواهیم کرد. با ما همراه باشید.
بسیار عالی بود ممنون که اطلاعاتتون رو در اختیار بقیه قرار میدید
ممنونم دوست عزیز که حمایت میکنید!
سیسوگ رو به دوستانتون معرفی کنید!