قسمت چهاردهم : تایمر نگهبان (IWDG)

0
131
تایمر نگهبان (IWDG)
تایمر نگهبان (IWDG)

در قسمت سیزدهم از آموزش میکروکنترلر STM8 به ویژگی کاربردی تایمر نگهبان آنالوگ (Analog Watchdog) پرداختیم. در این قسمت از مجموعه مقالات آموزش میکروکنترلر STM8 قصد داریم تایمر نگهبانی را که در اکثر میکروکنترلرها وجود دارد به شما آموزش دهیم. با ما همراه باشید تا تایمر نگهبان (IWDG) را فرا گیرید.

تایمر نگهبان (IWDG)

IWDG یک تایمر نگهبان معمولی است که در اکثر میکروکنترلرهای مدرن دیده می‌شود. هدف این تایمر این است که از میکروکنترلر درمقابل رویدادهای غیرمنتظره که به‌دلایل غیرمتعارف رخ می‌دهد محافظت‌کند. همان‌طورکه از نام آن مشخص است، این تایمر چیزی را با سخت‌افزارهای جانبی داخلی به اشتراک نمی‌گذارد و تنها با فرکانس (LSI (128KHz کار می‌کند. بنابراین، با کلاک‌های اصلی (HSE یا HSI) کار نمی‌کند.

سخت‌افزارهای جانبی داخلی
سخت‌افزارهای جانبی داخلی
کلاک‌های اصلی (HSE یا HSI)
کلاک‌های اصلی (HSE یا HSI)

 

IWDG به‌صورت شمارش معکوس کار می‌کند. هنگامی‌که شمارنده به صفر برسد، فرمان ریست صادر می‌شود. معمولاً ما می‌خواهیم که فرمان ریست هرگز اتفاق‌نیفتد بنابراین شمارنده به‌صورت دوره‌ای به‌‌روز می‌شود. اگر به‌هردلیلی، شمارنده به‌روز نشود، ریست اتفاق می‌افتد و MCU را از یک وضعیت فاجعه بار! نجات می‌دهد.

پیکربندی IWDG با SPL بسیارساده است. مراحل‌خاصی برای پیگیری وجود دارد، اما SPI آن‌ها را به‌صورت داخلی مدیریت می‌کند. نیازداریم که IWDG را پیکربندی کنیم و قبل‌از اتمام‌زمان آن‌را مجدداً بارگیری کنیم.

فرمول موردنیاز برای محاسبه وقفه در زیر داده‌شده‌است:

فرمول محاسبه وقفه
فرمول محاسبه وقفه

 

مقادیر معمول از زمان وقفه در زیر نشان‌داده شده‌است:

مقادیر زمان وقفه
مقادیر زمان وقفه

 

اتصالات سخت‌افزاری

اتصالات سخت‌افزاری
اتصالات سخت‌افزاری

 

نمونه‌کد IWDG

#include "STM8S.h"


void clock_setup(void);
void GPIO_setup(void);
void IWDG_setup(void);


void main(void)
{
unsigned int t = 0;

clock_setup();
GPIO_setup();

GPIO_WriteLow(GPIOD, GPIO_PIN_3);
for(t = 0; t < 60000; t++);

IWDG_setup();

while(TRUE)
{
GPIO_WriteReverse(GPIOD, GPIO_PIN_3);
for(t = 0; t < 1000; t++)
{
if(GPIO_ReadInputPin(GPIOB, GPIO_PIN_5) == FALSE)
{
IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable);
IWDG_ReloadCounter();
IWDG_WriteAccessCmd(IWDG_WriteAccess_Disable);
}
}
};
}


void clock_setup(void)
{
CLK_DeInit();

CLK_HSECmd(DISABLE);
CLK_LSICmd(ENABLE);
while(CLK_GetFlagStatus(CLK_FLAG_LSIRDY) == FALSE);
CLK_HSICmd(ENABLE);
while(CLK_GetFlagStatus(CLK_FLAG_HSIRDY) == FALSE);

CLK_ClockSwitchCmd(ENABLE);
CLK_HSIPrescalerConfig(CLK_PRESCALER_HSIDIV8);
CLK_SYSCLKConfig(CLK_PRESCALER_CPUDIV4);

CLK_ClockSwitchConfig(CLK_SWITCHMODE_AUTO, CLK_SOURCE_HSI, 
DISABLE, CLK_CURRENTCLOCKSTATE_ENABLE);

CLK_PeripheralClockConfig(CLK_PERIPHERAL_SPI, DISABLE);
CLK_PeripheralClockConfig(CLK_PERIPHERAL_I2C, DISABLE);
CLK_PeripheralClockConfig(CLK_PERIPHERAL_ADC, DISABLE);
CLK_PeripheralClockConfig(CLK_PERIPHERAL_AWU, DISABLE);
CLK_PeripheralClockConfig(CLK_PERIPHERAL_UART1, DISABLE);
CLK_PeripheralClockConfig(CLK_PERIPHERAL_TIMER1, DISABLE);
CLK_PeripheralClockConfig(CLK_PERIPHERAL_TIMER2, DISABLE);
CLK_PeripheralClockConfig(CLK_PERIPHERAL_TIMER4, DISABLE);
}


void GPIO_setup(void)
{
GPIO_DeInit(GPIOB);
GPIO_DeInit(GPIOD);

GPIO_Init(GPIOB, GPIO_PIN_5, GPIO_MODE_IN_PU_NO_IT);
GPIO_Init(GPIOD, GPIO_PIN_3, GPIO_MODE_OUT_PP_LOW_FAST);
}


void IWDG_setup(void)
{
IWDG_Enable();
IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable);
IWDG_SetPrescaler(IWDG_Prescaler_128);
IWDG_SetReload(0x99);
IWDG_WriteAccessCmd(IWDG_WriteAccess_Disable);
}

 

توضیحات

در این مثال، به کلاک خارجی و کلاک CPU کاری نداریم چراکه IWDG به آن‌ها وابسته نیست. می‌توانیم ببینیم که CPU با کلاک ۵۰۰کیلوهرتز کار می‌کند، درحالی‌که کلاک خارجی ۲مگاهرتز است.

CLK_HSIPrescalerConfig(CLK_PRESCALER_HSIDIV8);
CLK_SYSCLKConfig(CLK_PRESCALER_CPUDIV4);

 

برای راه‌اندازی IWDG ابتدا باید آن‌را فعال‌کرد و سپس Write Access Protection را اعمال‌نمود(0x55). فقط باید مقدار precaler و مقدار شمارنده را تنظیم‌کنیم. شمارنده معکوس از این شماره شروع می‌کند و تا صفر می‌شمارد، مگراینکه در این بین رفرش شود. در این مثال، precaler روی مقدار ۱۲۸ تنظیم‌شده و مقدار بارگذاری مجدد روی ۱۵۳ (0x99) تنظیم شده‌است. بنابراین، ما زمانی حدود ۳۰۰ms را دریافت می‌کنیم. پس‌از اینکه این مقادیر را وارد کردیم باید از تغییرات تصادفی در سیستم‌عامل جلوگیری کرد و بنابراین باید دسترسی‌به نوشتن غیرفعال شود.

void IWDG_setup(void)
{
IWDG_Enable();
IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable);
IWDG_SetPrescaler(IWDG_Prescaler_128);
IWDG_SetReload(0x99);
IWDG_WriteAccessCmd(IWDG_WriteAccess_Disable);
}

 

در ابتدا قبل‌از اینکه IWDG پیکربندی شود، LED روشن می‌شود که نشان‌دهنده شروع‌به‌کار سیستم‌عامل است. در حلقه اصلی، با یک تأخیر زمانی در حلقه “for” تغییر وضعیت می‌دهد. در داخل حلقه، وضعیت کلید نیز موردنظر است. اگر کلید پایین نگه‌داشته شود به‌معنای حالت منطقی پایین خواهد بود و IWDG مجدداً بارگذاری می‌شود. اگر وضعیت به حالت منطقی بالا تغییر کند و 300ms سپری شود، ریست اتفاق می‌افتد.

GPIO_WriteReverse(GPIOD, GPIO_PIN_0);
for(t = 0; t < 1000; t++)
{
if(GPIO_ReadInputPin(GPIOB, GPIO_PIN_7) == FALSE)
{
IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable);
IWDG_ReloadCounter();
IWDG_WriteAccessCmd(IWDG_WriteAccess_Disable);
}
}

 

توجه‌داشته‌باشید که ممکن‌است LSI کالیبراسیون شود. البته این اتفاق به‌ندرت پیش می‌آید.

خروجی نهایی
خروجی نهایی

 

در قسمت پانزدهم آموزش میکروکنترلر STM8 قصد داریم تایمر نگهبان محدوده‌ای(WWDG) را آموزش دهیم. با ما همراه باشید.

 

 

منبع: سیسوگ

برای این مقاله نظر بگذارید:

لطفا دیدگاه خود را بنویسید
لطفا نام خود را وارد کنید