تایمرهای میکروکنترلر LPC1768، اگر جلسات قبلی آموزش میکروکنترلرهای ARM LPC1768 را در وبسایت دنبال کرده باشید میدونید که در جلسات قبل با چند مورد از امکانات جانبی LPC1768 آشنا شدیم و نحوه راه اندازی و برنامه نویسی آنها را یاد گرفتیم در این جلسه میخواهیم تایمرهای LPC1768 که جز موارد خیلی مهم و کاربردی میکروکنترلرها هستن را کار میکنیم.
تایمر برای سنجش زمان از روی کلاک میکروکنترلر و کانترها برای شمارش کلاکهای خارجی استفاده میشوند و نکته جالبشون اینه که میتونید در مقادیر خاص شمارش/سنجش وقفه تولید کنند تا از روی این وقفه عملیات دیگر مناسبی انجام بشود مثلا هر یک ثانیه یکبار خروجیها معکوس بشوند و…
روی میکروکنترلر LPC1768 چهار عدد تایمر عادی وجود داره که برای زمان سنچی رویدادها استفاده میشوند ، همچنین این واحدها دارای حالت Capture نیز هستن که میتوانند بعنوان دمودلاتور استفاده بشوند و…روی میکروکنترلر تایمر RIT و واحد مجزای PWM وجود دارد که در جلسات آینده برسی میکنیم. جلسات قبلی و ادامه آموزشها را از ایجا بخوانید.
ویژگیهای تایمرهای LPC1768
- تایمر/کانتر 32 بیتی
- دارای عملکرد تایمر یا کانتر
- دو کانال Capture ، 32 بیتی برای هر تایمر
- چهار رجیستر مقایسه 32 بیتی
- چهار خروجی بر ای حالتهای مقایسه و تطابق
چهار رجیستر مقایسه دارای کاربردها یا عملکردهای زیر هستن:
- ادامه کار تایمر بهمراه تولید وقفه
- توقف وقفه بهمراه تولید وقفه
- ریست شدن وقفه بهمراه تولید وقفه
چهار خروجی تایمر برای حالتهای مقایسه و تطابق نیز دارای حالتهای زیر هستند:
- مقدار صفر یا سطح پایین در صورت تطابق
- مقدار یک یا سطح بالا در صورت تطابق
- حالت معکوس یا Toggle
- بدون تغییر حالت
پینهای تایمرهای LPC1768
دو دسته پین روی میکروکنترلر برای تایمرها وجود داره دسته اول برای خروجیهای مقایسه هستن و دسته دوم پینهای ورودی Capture هستند.
MAT0[0:1], MAT1[0:1], MAT2[0:3], MAT3[0:1] CAP0[0:1], CAP1[0:1], CAP2[0:1], CAP3[0:1]
پیکربندی تایمرهای LPC1768
- تغذیه : تایمر صفر بوطر پیش فرض روشن هست ولی تایمرهای یک، دو، سه را باید از رجیستر PCONP فعال کنیم.
- تنظیم کلاک: از طریق رجیسترهای PCLKSEL0,1 کلاک را برای تایمرها تنظیم میکنیم.
- انتخاب عملکرد پینهای تایمر با رجیسترهای PINSEL
- وقفه: برای حالتهای مختلف تایمر میتوانیم وقففه تنظیم کنیم.
- تنظیم دسترسی مستقیم به حافظه یا DMA که در مطالب پیشرفته برسی میکنیم.
نکته مهم : در تایمرهای lpc1768 یک حالت Prescale وجود داره که کمک میکنه زمانهای خیلی بزرگ را نیز باهاش درست کنیم. در این حالت مثلا Prescale را تنظیم کردیم روی 10 ، تایمر باید 10 کلاک بزنه تا به شمارنده اصلی تایمر یک واحد اضافه بشه. همچنین یک تابع خیلی جالب هم برای cmsis نوشتن که زمان را بر حسب میکروثانیه به Prescale میدهیم و خودش تبدیل به کلاک میکنه…
برنامه نویسی تایمرهای LPC1768
ساختارها برای تنظیمات اولیه تایمر، در جلسه قبلی با ساختار یا استراکچر آشنا شدیم و گفتیم که برای اینکه کلیه تنظیمات مربوط به یک بخش را در داخل یک متغیر داشته باشیم از این استراکچر در این قسمتها استفاده میکنیم که البته ساختارها در برنامه نویسی از اهمیت بالایی برخوردار هستن خب به مثال و نحوه استفاده آنها دقت کنید بهتر یاد میگیرید.
ساختار TIM_TIMERCFG_Type
این ساختار برای تنظیمات حالت تایمر استفاده میشود و دارای اجزای زیر هستش، این ساختار به عنوان ورودی اکثر توابع هستش که در ادامه برسی میکنیم.
- متغیر اول ساختار PrescaleOption هستش که برای تنظیم Prescale تایمر هستش که میتونه TIM_PRESCALE_TICKVAL یا TIM_PRESCALE_USVAL را داشته باشه که در حالت اول مقدار را بصورت مطلق و در حالت دوم مقدار را بصورت میکروثانیه در متغیر بعدی که معرفی میکنیم وارد میکنیم.
- متغیر دوم ساختار PrescaleValue یا مقدار Prescale هست که در سطر بالا توضیح دادیم چطوری هستش.
ساختار TIM_COUNTERCFG_Type
این ساختار برای پیکر بندی وضعیت حالت کانتر هستش
ساختار TIM_MATCHCFG_Type
- متغیر اول این ساختار MatchChannel که شماره کانال مقایسه هستش و میتونه 0-3 باشه
- متغیر دوم این ساختار IntOnMatch که وضعیت وقفه در حالت تطابق را فعال یا غیر فعال میکنه و ENABLE و یا DISABLE را میگیره.
- متغیر سومش StopOnMatch که توقف در حالت تطابق هست که میتونه ENABLE و یا DISABLE را میگیره.
- متغیر چهارمش ResetOnMatch هستش که ریست در حالت تطابق هست و ENABLE و یا DISABLE را میگیره.
- متغیر پنجم ساختار ExtMatchOutputType هست که میتونه حالتهای مقدار صفر یا سطح پایین در صورت تطابق، مقدار یک یا سطح بالا در صورت تطابق، حالت معکوس یا Toggle، بدون تغییر حالت را داشته باشه.
[su_note note_color="#848ada" radius="5"]TIM_EXTMATCH_NOTHING TIM_EXTMATCH_LOW TIM_EXTMATCH_HIGH: TIM_EXTMATCH_TOGGLE[/su_note]
- متغیر آخر این ساختار MatchValue هستش که مقدار مقایسه را در خودش نگه میداره.
ساختار TIM_CAPTURECFG_Type
این ساختار برای تنظیم حالت کپچر هستش
- متغیر اول آن CaptureChannel هست که کانال کچپر را انتخاب میکنه
- متغیر دومش RisingEdge کپشن برای لبه بالا روندهکه با ENABLE فعال و با DISABLE غیر فعال میشه.
- متغیر سوم FallingEdge کپشن برای لبه پایین رونده که با ENABLE فعال و با DISABLE غیر فعال میشه.
- متغیر چهارم IntOnCaption وقفه کپشن که با ENABLE فعال و با DISABLE غیر فعال میشه.
توابع CMSIS برای کاربا تایمرهای LPC1768
تابع TIM_Init
void TIM_Init(LPC_TIM_TypeDef *TIMx, TIM_MODE_OPT TimerCounterMode, void *TIM_ConfigStruct);
تنظیم اولیه تایمر/کانتر بر عهده این تابع میباشد ، این تاب دارای سه ورودی است که در زیر یکی یکی برسی میکنیم.
- ورودی اول آن اشاره گر به تایمر مورد نظر که میتونه یکی از مقادیر LPC_TIM3, LPC_TIM2, LPC_TIM1,LPC_TIM0 باشه
- ورودی دوم تابع(که یک enum هست) برای انتخاب مد کاری تایمر/کانتر هستش که میتونه یکی از مقادیر زیر را داشته باشه.
TIM_TIMER_MODE // حالت تایمر TIM_COUNTER_RISING_MODE /*کانتر در لبه بالا رونده */ TIM_COUNTER_FALLING_MODE /*کانتر در بله پایین رونده */ TIM_COUNTER_ANY_MODE /*!< کانتر در هر دو لبه */
ورودی سوم تابع اشاره گر از نوع ساختار هستش! در بالا ساختارها را توضیح دادیم و جزئیات دقیق این اشاره گر را برسی کردیم که حاوی اطلاعات پیکربند ی تایمر هستش. به مثال یا توضیحات بالا نگاه کنید متوجه میشید.
تابع TIM_DeInit
void TIM_DeInit(LPC_TIM_TypeDef *TIMx);
این تابع برای غیرفعال کردن تایمر/کانتر مورد نظر استفاده میشود که ورودی آن نام تابع مورد نظر است که میتونه یکی از مقادیر LPC_TIM3, LPC_TIM2, LPC_TIM1,LPC_TIM0 باشه.
تابع TIM_ClearIntPending
void TIM_ClearIntPending(LPC_TIM_TypeDef *TIMx, TIM_INT_TYPE IntFlag);
وقفه در حال انتظار مورد نظر را پاک میکنه .
- ورودی اول تابع تایمر مورد نظر
- ورودی دوم تابع میتونه یکی از موارد زیر باشه
[su_note] TIM_MR0_INT =0, TIM_MR1_INT =1, TIM_MR2_INT =2, TIM_MR3_INT =3, TIM_CR0_INT =4, TIM_CR1_INT =5[/su_note]
تابع TIM_ClearIntCapturePending
void TIM_ClearIntCapturePending(LPC_TIM_TypeDef *TIMx, TIM_INT_TYPE IntFlag);
این تابع برای پاک کردن وضعیت وقفه در حال انتظار وقفه Capture استفاده میشه
- ورودی اول تایمر مورد نظر
- ورودی دوم آن هم میتونه یکی از موارد زیر باشه
TIM_MR1_INT =1, TIM_MR2_INT =2, TIM_MR3_INT =3, TIM_CR0_INT =4, TIM_CR1_INT =5
تابع TIM_GetIntStatus
FlagStatus TIM_GetIntStatus(LPC_TIM_TypeDef *TIMx, TIM_INT_TYPE IntFlag);
این تابع وضعیت وقفه را اعلام میکنه و ورودیهای آن اگر دقت کنید مثل تابع بالا هستش
- خروجی تابع هم اگر وقفه وجود داشته باشه SET و اگر وجود نداشته باشه RESET هستش
تابع TIM_GetIntCaptureStatus
FlagStatus TIM_GetIntCaptureStatus(LPC_TIM_TypeDef *TIMx, TIM_INT_TYPE IntFlag);
این تابع هم مثل تابع بالا هستش که وضعیت وقفههای کپچر را اعلام میکنه
- ورودی های تابع مثل ClearIntCapturePending هستش
- خروجی تابع هم اگر وقفه وجود داشته باشه SET و اگر وجود نداشته باشه RESET هستش
تابع TIM_ConfigStructInit
void TIM_ConfigStructInit(TIM_MODE_OPT TimerCounterMode, void *TIM_ConfigStruct);
پیکربندی اولیه کارکرد تایمر
- ورودی اول TimerCounterMode هستش که میتونه یکی از حالتهای زیر را داشته باشه
TIM_TIMER_MODE // حالت تایمر TIM_COUNTER_RISING_MODE /*کانتر در لبه بالا رونده */ TIM_COUNTER_FALLING_MODE /*کانتر در بله پایین رونده */ TIM_COUNTER_ANY_MODE /*!< کانتر در هر دو لبه */
ورودی دوم آن هم ساختار TIM_ConfigStruct که در بالا توضیح دادیم و در مثال بیشتر متوجه نحوه مقدار دهی و بقیه مواردش میشید.
تابع TIM_ConfigMatch
void TIM_ConfigMatch(LPC_TIM_TypeDef *TIMx, TIM_MATCHCFG_Type *TIM_MatchConfigStruct);
این تابع رجیسترهای تطابق یا مقایسه را پیکربندی میکنه
- ورودی اول آن تایمر مورد نظر هست که میتونه LPC_TIM3, LPC_TIM2, LPC_TIM1,LPC_TIM0 باشه
- ورودی دوم آن ساختار مربوط به تطابق هست که در بالا قسمت ساختارها اجزای آن را برسی کردیم. اول این مقادیر ساختار مقداردهی بعد به این تابع پاس داده میشه.
تابع TIM_UpdateMatchValue
void TIM_UpdateMatchValue(LPC_TIM_TypeDef *TIMx,uint8_t MatchChannel, uint32_t MatchValue);
- ورودی اول تابع تایمر مورد نظر هست که بالا در همه توابع یکسان هست
- ورودی دوم کانال تطابق مورد نظر هست که میتونه از 0 تا 3 باشه
- ورودی سوم هم مقدار جدید تطابق هست
تابع TIM_SetMatchExt
void TIM_SetMatchExt(LPC_TIM_TypeDef *TIMx,TIM_EXTMATCH_OPT ext_match );
این تابع وضعیت پینهای تطابق در هنگام تطابق مشخص میکنه
- ورودی اول تابع شماره تایمر مورد نظر
- ورودی دوم تابع میتونه یکی از حالتهای زیر باشه
TIM_EXTMATCH_NOTHING /*!< Do nothing for external output pin if match */ TIM_EXTMATCH_LOW /*!< Force external output pin to low if match */ TIM_EXTMATCH_HIGH /*!< Force external output pin to high if match */ TIM_EXTMATCH_TOGGLE /*!< Toggle external output pin if match */
تابع TIM_ConfigCapture
void TIM_ConfigCapture(LPC_TIM_TypeDef *TIMx, TIM_CAPTURECFG_Type *TIM_CaptureConfigStruct);
- ورودی اول تابع تایمر مورد نظر هست
- ورودی دوم ساختار TIM_CaptureConfigStruct هست که در بالا اجزای آن را برسی کردیم اول اجزا را مقدار دهی و بعد به این تابه پاس میدیم.
تابع TIM_Cmd
void TIM_Cmd(LPC_TIM_TypeDef *TIMx, FunctionalState NewState);
تابع شروع/توقف تایمر مورد نظر
- ورودی اول تابع تایمر مورد نظر هست
- ورودی دوم آن هم برای ENABLE شروع و DISABLE برای غیر توقف
مثال
#include "CMSIS/lpc17xx_timer.h" #include "CMSIS/lpc17xx_pinsel.h" #include "CMSIS/lpc17xx_gpio.h" TIM_TIMERCFG_Type TIM_ConfigStruct; TIM_MATCHCFG_Type TIM_MatchConfigStruct ; void TIMER0_IRQHandler(void) { if (TIM_GetIntStatus(LPC_TIM0, TIM_MR0_INT)== SET) { // go and check Melec.ir site :) or do what do you whan } TIM_ClearIntPending(LPC_TIM0, TIM_MR0_INT); } int main (void) { PINSEL_CFG_Type PinCfg; // Conifg P1.28 as MAT0.0 PinCfg.Funcnum = 3; PinCfg.OpenDrain = 0; PinCfg.Pinmode = 0; PinCfg.Portnum = 1; PinCfg.Pinnum = 28; PINSEL_ConfigPin(&PinCfg); // Initialize timer 0, prescale count time 100us TIM_ConfigStruct.PrescaleOption = TIM_PRESCALE_USVAL; TIM_ConfigStruct.PrescaleValue = 100; // 100us // use channel 0, MR0 TIM_MatchConfigStruct.MatchChannel = 0; // Enable interrupt when MR0 matches the value in TC register TIM_MatchConfigStruct.IntOnMatch = TRUE; //Enable reset on MR0: TIMER will reset if MR0 matches it TIM_MatchConfigStruct.ResetOnMatch =TRUE ; //Stop on MR0 if MR0 matches it TIM_MatchConfigStruct.StopOnMatch =FALSE; //Toggle MR0.0 pin if MR0 matches it TIM_MatchConfigStruct.ExtMatchOutputType =TIM_EXTMATCH_TOGGLE; // Set Match value, count value of 10000 (10000 * 100uS = 1000000us = 1s --> 1 Hz) TIM_MatchConfigStruct.MatchValue = 10000; // Set configuration for Tim_config and Tim_MatchConfig TIM_Init(LPC_TIM0, TIM_TIMER_MODE,&TIM_ConfigStruct); TIM_ConfigMatch(LPC_TIM0,&TIM_MatchConfigStruct); /* preemption = 1, sub-priority = 1 */ NVIC_SetPriority(TIMER0_IRQn, ((0x01<<3)|0x01)); /* Enable interrupt for timer 0 */ NVIC_EnableIRQ(TIMER0_IRQn); // To start timer 0 TIM_Cmd(LPC_TIM0,ENABLE); while (1); return 1; }
دوستان به پایان این جلسه رسیدیم امیدوارم که براتون مفید بوده باشه.
منبع: میکرودیزاینرالکترونیک