سیستم های نهفته برخی از فعالیت ها را بر اساس زمان انجام می دهند. برای تاخیرهای بسیار ساده و غیر دقیق، یک حلقه می تواند این کار را انجام دهد، اما استفاده از هسته CPU برای انجام فعالیت های مربوط به زمان هرگز راه حل هوشمندانه ای نیست. به همین دلیل، همه میکروکنترلرها تجهیزات جانبی سخت افزاری اختصاصی به نام تایمر را ارائه می دهند. تایمرها نه تنها مولد زمان هستند، بلکه چندین ویژگی اضافی را نیز برای تعامل با هسته Cortex-M و سایر تجهیزات جانبی، داخلی و خارجی MCU ارائه می دهند.
بسته به خانواده و پکیج مورد استفاده، میکروکنترلرهای STM32 دارای تعداد متغیری از تایمرها می باشند که هر کدام دارای ویژگی های خاصی هستند. برخی می توانند تا 14 تایمر مستقل را ارائه دهند. تایمرها تقریباً در تمام سری های STM32 به صورت یکسان پیاده سازی و در 9 دسته مجزا گروه بندی می شوند. مرتبط ترین آنها عبارتند از: تایمرهای پایه، عمومی و پیشرفته.
تایمر در میکروهای STM32 یک واحد جانبی پیشرفته است که طیف گستردهای از قابلیت ها را ارائه میدهد. میکروکنترلر STM32F303CC دارای 11 تایمر است.
معرفی تایمر
تایمر یک شمارنده با فرکانس شمارش کسری از منبع کلاک خود است. سرعت شمارش را می توان با استفاده از یک prescaler اختصاصی برای هر تایمر کاهش داد. بسته به نوع تایمر، می توان آن را با استفاده از کلاک داخلی (که از گذرگاهی که به آن متصل است گرفته شده است)، توسط یک منبع کلاک خارجی یا توسط تایمر دیگری که به عنوان “master” استفاده می شود، کلاک کرد.
معمولاً یک تایمر از صفر تا یک مقدار داده شده را می شمارد که نمی تواند از حداکثر مقدار بدون علامت آن بیشتر باشد (مثلاً یک تایمر 16 بیتی وقتی شمارنده به 65535 می رسد سرریز می شود) اما می تواند برعکس نیز شمارش کند.
پیشرفته ترین تایمرها در میکروکنترلر STM32 چندین ویژگی دارند:
- می توان از آنها به عنوان مولد پایه زمانی استفاده کرد (که ویژگی مشترک تمام تایمرهای STM32 است).
- می توان از آنها برای اندازه گیری فرکانس یک رویداد خارجی (input capture mode) استفاده کرد.
- می توان از آنها برای کنترل شکل موج خروجی، یا نشان دادن زمان سپری شده یک دوره زمانی (حالت مقایسه خروجی). استفاده کرد.
- حالت یک پالس (OPM) One pulse mode مورد خاصی از حالت input capture mode and output compare mode است که اجازه می دهد تا شمارنده در پاسخ به یک محرک راه اندازی شود و پس از یک تاخیر قابل برنامه ریزی، پالسی با طول قابل برنامه ریزی تولید کند.
- می توان از آنها برای تولید سیگنال های PWM در حالت edge-aligned یا حالت center-aligned به طور مستقل در هر کانال (حالت PWM). استفاده کرد.
در برخی از MCU های STM32 (به ویژه از STM32F3 و سری های اخیر STM32L4)، برخی تایمرها می توانند سیگنال های PWM center-aligned را با یک تاخیر قابل برنامه ریزی و تغییر فاز تولید کنند.
بسته به نوع تایمر، تایمر میتواند وقفه ها یا درخواست های DMA را در موارد زیر ایجاد کند:
- رویدادهای به روزرسانی
–سرریز/زیر جریان شمارنده
– مقداردهی شمارنده
– دیگر….
- تریگر یا تحریک
–شروع/توقف شمارش
– مقداردهی شمارنده
– دیگر….
- مقایسه ورودی/خروجی
معرفی دسته بندی تایمر در میکروکنترلر STM32
تایمرهای STM32 عمدتاً می توانند در 9 دسته گروه بندی شوند. نگاهی کوتاه به هر یک از آنها خواهیم داشت:
- Basic timers: تایمرهای این دسته ساده ترین شکل تایمرها در MCU های STM32 هستند. تایمرهای 16 بیتی ای که به عنوان مولد پایه زمانی استفاده می شوند و پایه های خروجی/ورودی ندارند. تایمرهای پایه برای تغذیه واحد جانبی DAC نیز استفاده میشوند، زیرا رویداد بهروزرسانی update event آنها میتواند درخواستهای DMA را برای DAC راهاندازی کند (به همین دلیل معمولاً در میکرو های STM32 ای موجود هستند که حداقل یک DAC را ارائه میدهند). تایمرهای پایه را می توان به عنوان “master” برای تایمرهای دیگر نیز استفاده کرد.
- General purpose timers : تایمرهای 16/32 بیتی (بسته به سری STM32) که ویژگی های کلاسیکی که از یک میکروکنترلر مدرن انتظار می رود اجرا کند را ، ارائه می دهند. آنها در هر کاربردی برای output compare (تولید زمان و تأخیر)، حالت تک پالس One-Pulse ، گرفتن ورودی input capture (برای اندازه گیری فرکانس سیگنال خارجی)، رابط سنسور (encoder, hall سنسور) و غیره استفاده می شوند. بدیهی است که یک تایمر عمومی می تواند مانند یک تایمر پایه Basic timer به عنوان مولد پایه زمانی نیز، استفاده شود. تایمرهای این دسته، کانال های ورودی/خروجی چهارگانه قابل برنامه ریزی ای را ارائه می دهند.
– 1 کانال / 2 کانال: آنها دو زیر گروه از تایمرهای عمومی هستند که فقط یک / دو کانال ورودی / خروجی را ارائه می دهند.
– 1 کانال / 2 کانال با یک خروجی: مانند نوع قبلی بوده ، اما دارای یک مولد زمان مرده dead time در یک کانال خود می باشد. این امر باعث می شود تا سیگنال های مکمل با یک پایه زمانی مستقل از تایمرهای پیشرفته داشته باشید.
- تایمرهای پیشرفته: این تایمرها کاملترین تایمرهای میکروکنترلر STM32 هستند. علاوه بر ویژگیهای موجود در یک تایمر عمومی، آنها شامل چندین ویژگی مرتبط با کنترل موتور و کاربردهای تبدیل توان دیجیتال هستند: سه سیگنال مکمل با درج زمان مرده dead time و خاموش شدن اضطراری ورودی.
- تایمر با وضوح بالا: تایمر با وضوح بالا (HRTIM1) تایمر ویژه ای است که توسط برخی میکروکنترلرهای سری STM32F3 (سری اختصاص داده شده به کنترل موتور و تبدیل توان) ارائه می شود.با استفاده از این تایمر، امکان تولید سیگنال های دیجیتال با زمان بندی دقت بالا، مانند PWM یا پالس های phase-shifted فراهم می شود. این تایمر شامل 6 تایمر فرعی، 1 Master و 5 slave، مجموعا 10 خروجی با وضوح بالا است که هر جفت از آنها با درج زمان مرده dead time می توانند با هم کوپل شوند. همچنین دارای 5 ورودی خطا برای اهداف حفاظتی و 10 ورودی برای رسیدگی به رویدادهای خارجی مانند محدودیت جریان، سوئیچینگ ولتاژ صفر یا جریان صفر است.
تایمر HRTIM1 از یک هسته کرنل با کلاک 144 مگاهرتز و خطوط تاخیر ساخته شده است. خطوط تاخیری با کنترل حلقه بسته رزولوشن 217ps را فارغ از ولتاژ، دما یا انحراف فرآیند تولید تراشه به تراشه، تضمین میکنند. وضوح بالا در 10 خروجی در همه حالتهای عملیاتی موجود است: duty cycle متغیر، فرکانس متغیر و زمان روشن ثابت.
- تایمرهای کم مصرف: تایمرهای این گروه مخصوصاً برای کاربردهای کم مصرف طراحی شده اند. به لطف تنوع منابع کلاک، این تایمرها می توانند در تمام حالت های power modes (به جز حالت Standby) به کار خود ادامه دهند. با توجه به این قابلیت حتی بدون منبع کلاک داخلی نیز، تایمرهای کم مصرف را می توان به عنوان یک “پالس شمار” استفاده کرد که می تواند در برخی از کاربرد ها مفید باشد. همچنین این قابلیت را دارند که سیستم را از حالت های کم مصرف low-power بیدار کنند.

تایمر های پایه (Basic Timers)
تایمرهای پایه TIM6، TIM7 و TIM18 ساده ترین تایمرهای موجود در میکروکنترلرهای STM32 هستند. حتی اگر آنها توسط همه MCU های STM32 ارائه نشده باشند. دوباره تاکید می کنیم که تایمرهای STM32 به گونه ای طراحی شده اند که تایمرهای پیشرفته تر همان قابلیت های تایمرهای ساده تر و ضعیف تر را (به همان روش) اجرا می کنند. در واقع استفاده از یک تایمر general purpose به همان شیوه تایمر basic اولیه کاملاً ممکن است.کتابخانه CubeHAL تمامی پیاده سازی سخت افزاری را انجام می دهد. عملیات های پایه ، ساده و ابتدایی در تمام تایمرها با استفاده از توابع HAL_TIM_Base_XXX انجام می شود.

یک تایمر تکی با استفاده از نمونه ای از ساختار C به نام TIM_HandleTypeDef ارجاع داده شده که به شکل زیر تعریف می شود:
console.log( 'Code is Poetry' );
حال میخواهیم مهمترین بخش های این ساختار را عمیق تر بررسی کنیم:
Instance: اشاره گری به توصیفگر TIM است که قرار است از آن استفاده کنیم. برای مثال، TIM6 یکی از تایمرهای اساسی موجود در اکثر میکروکنترلرهای STM32 است.
Init: نمونه ای از ساختار C به نام TIM_Base_InitTypeDef است که برای پیکربندی عملکردهای پایه تایمر استفاده می شود.
Channel: تعداد کانال های فعال در تایمرها را نشان می دهد که یک یا چند کانال ورودی/خروجی را ارائه می دهند (این مورد در تایمرهای basic نیست). در واقع می تواند یک یا چند مقدار را از enum HAL_TIM_ActiveChannel داشته باشد.
*hdma[7]: آرایه ای است که شامل اشاره گرهایی به توصیفگر DMA_HandleTypeDef برای درخواست های DMA مرتبط با تایمر است. همانطور که بعداً خواهیم دید، یک تایمر می تواند تا هفت درخواست DMA را ایجاد کند که برای هدایت ویژگی های آن استفاده می شود.
State: این بخش به صورت داخلی توسط HAL برای پیگیری وضعیت تایمر استفاده می شود.
console.log( 'Code is Poetry' );
Prescaler: کلاک تایمر را بر ضریبی از 1 تا 65535 تقسیم می کند (به این معنی که رجیستر prescaler دارای 16 بیت وضوح است). برای مثال، اگر گذرگاهی که تایمر به آن وصل است با فرکانس 48 مگاهرتز کار کند، مقدار prescaler برابر با 48 فرکانس شمارش را به 1 مگاهرتز کاهش می دهد.
CounterMode: جهت شمارش تایمر را مشخص می کند و می تواند یکی از مقادیر جدول زیر را در بر بگیرد. برخی از حالت های شمارش فقط در تایمرهای عمومی general purpose و پیشرفته advanced در دسترس هستند. برای تایمرهای basic اولیه، فقط TIM_COUNTERMODE_UP تعریف شده است.

Period: حداکثر مقدار را برای شمارنده تایمر ، قبل از شروع مجدد شمارش، تنظیم می کند. این فیلد می تواند مقداری از x1 تا xFFFF (65535) برای تایمرهای 16 بیتی و از x1 تا xFFFF FFFF برای تایمرهای TIM2 و TIM5 در میکروهایی که آنها را به عنوان تایمرهای 32 بیتی پیاده سازی می کنند، در بر بگیرد. اگر Period روی x0 تنظیم شده باشد، تایمر شروع نمی شود.
ClockDivision: این bit-field نسبت تقسیم بین فرکانس کلاک داخلی تایمر و کلاک نمونه برداری که توسط فیلترهای دیجیتال روی پین های ETRx و TIx استفاده می شود را نشان می دهد و می تواند یک مقدار را از جدول زیر در بر بگیرد و فقط در تایمرهای عمومی و پیشرفته در دسترس است. در ادامه ، فیلترهای دیجیتال روی پایه های ورودی یک تایمر را مطالعه خواهیم کرد. این فیلد توسط مولد dead time زمان مرده نیز استفاده می شود .

RepetitionCounter: هر تایمر دارای یک رجیستر به روز رسانی update register خاص است که وضعیت overflow/underflow تایمر را پیگیری می کند. همانطور که در ادامه خواهیم دید، می تواند یک IRQ خاص نیز ایجاد کند. RepetitionCounter میگوید که چند بار تایمر قبل از SET شدن رجیستر بهروزرسانی، overflow/underflow داشته باشد و رویداد event مربوطه (در صورت فعال بودن) انجام میشود. RepetitionCounter فقط در تایمرهای پیشرفته موجود است.
تنظیمات پروژه تایمر
در این قسمت قصد داریم 2 تایمر را به ترتیب با 250 میلی ثانیه و 1 ثانیه راه اندازی کرده و با هر کدام یک متغیر را بشماریم. راهاندازی تایمرهای دیگر نیز به همین روال است. برای این منظور مطابق شکل زیر، در قسمت تایمرها و بخش TIM1، منبع کلاک به عنوان کلاک داخلی تنظیم شده است. در قسمت تنظیمات پارامتر، Prescaler را روی 7999 و Counter Period را روی 249 قرار میدهیم. سپس از قسمت تنظیمات NVIC، وقفه آپدیت TIM1 را فعال میکنیم.


برای فعالسازی TIM6 آیکون مربوطه را انتخاب میکنیم. در قسمت تنظیمات پارامتر، Prescaler را روی 7999 و Counter Period را روی 999 قرار میدهیم. سپس از قسمت تنظیمات NVIC، وقفه سراسری TIM6 را همانطور که در شکل زیر نشان داده شده است؛ فعال میکنیم.


همانطور که در شکل زیر نشان داده شده است، فرکانسهای APB1 (TIM6) و تایمر APB2 (TIM1) 8 مگاهرتز انتخاب شدهاند. برای تولید وقفههای TIM1 در هر 250 میلی ثانیه، مقدار Prescaler برابر با 7999 را انتخاب کنید تا فرکانس 8 مگاهرتز TIM1 را به 8000 (از 0 تا 7999) تقسیم کنید تا فرکانس 1 کیلوهرتز با دوره 1 میلی ثانیه تولید شود. برای Counter Period ،249 (از 0 تا 249) را برای تولید 250 میلی ثانیه انتخاب کنید. به طور مشابه، برای تولید وقفه های TIM6 در هر 1 ثانیه، مقدار Prescaler را برابر با 7999 انتخاب کنید تا فرکانس 8 مگاهرتز TIM6 را به 8000 (از 0 تا 7999) تقسیم کنید تا فرکانس 1 کیلوهرتز با دوره 1 میلی ثانیه تولید شود. همچنین، برای Counter Period، 999 (از 0 تا 999) را برای تولید 1s انتخاب کنید. همانطور که در شکل زیر نشان داده شده است، برای تعیین اولویت وقفه از قسمت پیکربندی NVIC، 1 را برای TIM1 و 2 را برای TIM6 Preemption Priority انتخاب کنید.


پس از وارد کردن تنظیمات بالا، از تب مدیریت پروژه، کد پروژه را تولید کنید:

پس از ایجاد پروژه و باز کردن فایل مربوطه بدنه تایمرهای 1 و 6 در داخل فایل stm32f1xx_hal_tim.c هستند که در شکل زیر نشان داده شده است:

تایمر 2:

توابع سرویس به وقفههای تایمر نیز در داخل stm32f1xx_it.c می باشند:


همانطور که قبلاً ذکر شد، ما در نظر داریم دو تایمر (TIM1 و TIM6) را راهاندازی کنیم و با TIM1 یک وقفه 250 میلی ثانیه و با TIM6 یک وقفه 1 ثانیه ایجاد میکنیم و سپس با هر تایمر یک متغیر را بشماریم. همچنین با تعریف یک متغیر و تغییر آن در وقفه 250 میلی ثانیه، LED_USER را در متن برنامه تغییر وضعیت دهیم. برای این منظور ابتدا متغیرهای TIMER1_COUNTER ,TIMER6_COUNTER , LED_TOGGLEرا تعریف میکنیم:

سپس با استفاده از تابع HAL_TIM_Base_Start_IT تایمرها را راه اندازی میکنیم:

در فایل stm32f3xx_it.c مجددا متغیرها را تعریف کرده و با استفاده از تابع HAL_TIM_PeriodElapsedCallback تغییرات مورد نظر در وقفه را به هر یک از متغیرها اعمال میکنیم:

در انتها با تغییرات مقادیر متغیر LED_TOGGLE در تابع وقفه و متن برنامه، وضعیت LED_USER هر 250 میلی ثانیه تغییر پیدا میکند.

تنظیمات پروژه کانتر
تایمرها شمارندههایی هستند که پالسهای منظم یک نوسانساز را میشمارند. تایمرها همچنین میتوانند پالس هایی را که به صورت خارجی به یک پین اعمال میشوند، بشمارند. در این حالت تایمر را شمارنده (کانتر) مینامند. ما میخواهیم واحد TIM15 را بهعنوان شمارنده پالسهای خارجی فعال کنیم و با دکمه USER_BUTTON که به پین PA3 وصل شده با پالسهای لبهای پایین رونده آن را تحریک کرده و آنها را با یک متغیر مرتبط با شمارنده شمارش کنیم. برای این منظور مطابق شکل زیر از قسمت Pinout & Configuration و بخش TIM15، حالت Slave را روی External Clock Mode 1 و Trigger Source را به صورت TI1FP2 تنظیم میکنیم. از بخش کانفیگ پارامترها، تنظیماتی مانند Prescaler (0)، Counter Mode (بالا)، Counter Period (65535 برای مقدار 16 بیت)، Trigger Polarity (Rising Edge) و Trigger Filter (15) را انجام میدهیم. در بخش System Core و زیربخش TIM، حالت Alternate Function Open Drain را برای حالت GPIO تنظیم کنید (با توجه به مدار بسته شده روی پین PA3). از بخش System Core و زیربخش NVIC، وقفه بهروزرسانی TIM15 را فعال کنید. هنگامی که مقدار شمارنده به مقدار Counter Period میرسد، وقفه 5TIM1 فعال میشود.