اگر جلسات قبلی آموزش میکروکنترلرهای 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; }
تمرین: مثال را برسی کنید و چیزهایی که ازش درک کردین را در قسمت نظرات همین نوشته بنویسید.
آموزشهای مرتبط
دوستان به پایان جلسه یازدم رسیدیم امیدوارم که براتون مفید بوده باشه و ما را نیز دعا کنید.
اگر این نوشته برایتان مفید بود لطفا کامنت بنویسید.
بسیار ممنون و متشکرم آقای جهاندیده
واقعا مفید و ارزنده است کارتون.
ممنون از زحماتتون