آموزش میکروکنترلر AVR – قسمت نهم;
در قسمت هشتم آموزش میکروکنترلر AVR به بررسی خواندن و نوشتن رجیسترهای 16 بیتی و Status Register پرداختیم، در این جلسه از آموزش میکروکنترلر AVR به صحبت راجب به stack یا پشته و مقدمه ای بر تایمرها و کانترها میپردازیم.
در شرایطی در حین اجرای برنامه نیاز است سابروتین ها یا زیر روالهایی احضار شوند و یا وقفه اتفاق بیفتد.
سابروتین ها :گاهی در طول اجرای برنامه بخش هایی هستند که نیاز است چندین بار اجرا شوند، برای صرفه جویی در حافظه فلش بهتر است، قسمت مورد نظر به صورت سابروتین نوشته شود. آنگاه در طول اجرای برنامه هرکجا به سابروتین نیاز باشد به آن مراجعه میشود و بعد از اجرا، به ادامه برنامه برگشت داده میشود.
برای انجام آن لازم است، CPU از آدرس محلی که سابروتین در آن call میشود، اطلاع داشته باشد و زمانی که به انتهای سابروتین رسید، بداند که به کجا برگشت داده شود. بدین منظور در حافظه SRAM، فضایی به نام stack یا پشته اختصاص یافته است.
از کاربردهای این فضا، ذخیره کردن آدرس محل برگشت از سابروتین است که به عنوان stack در فضای SRAM ذخیره میشود.
حال این سوال پیش می آید که محل stack در SRAM کجاست؟
جواب این است که اگر برنامه توسط زبان اسمبلی نوشته میشود، محل باید به وسیله برنامه نویس تعیین شود و اگر به وسیله کامپایلر highlevel نوشته میشود، خود کامپایلر به صورت پیشفرض stack را مشخص میکند.
خاصیت stack در Last in first out) LIFO) بودن آن است. همانطور که از اسم آن مشخص است. در حین بازیابی و فراخوانی، آخرین چیزی که وارد فضای stack میشود ابتدا از آن خوانده شده است
برای مثال تعدادی کتاب روی همدیگر قرار دارند، در هنگام برداشتن و خواندن این کتابها، آخرین کتابی که قرار گرفته است، ابتدا برداشته و خوانده میشود.
در نقطه مقابل first in first out است. برای مثال افراد حاضر در یک صف،کسی که نفر اول وارد صف شده است نفر اول هم از آن صف خارج میشود.
مکان معمول stack در انتهای SRAM تعریف میشود. اگر فضای SRAM را در نظر بگیریم در انتهای SRAM، ابتدای stack تعریف میشود.
اصطلاح top of stack یعنی بالای stack و جایی که قرار است اطلاعات در آنجا ذخیره شود.
در مقدار دهی اولیه اگر stack را در انتهای SRAM فرض کنیم،اطلاعات آن توسط CPU به صورت زیر نوشته و خوانده میشوند.
اگر قرار باشد یک سابروتین اجرا شود، باید آدرس محلی که بعد از اجرای سابروتین به آن بازگشت داده میشود، به صورت خودکار توسط cpu در stack ذخیره شود.
حال اگر چندین سابروتین ، یعنی داخل یک سابروتین، سابروتین بعدی و به همین ترتیب، وجود داشته باشد، به همین روال آدرس آن در stack ذخیره میشود و در هنگام بازگشت آخرین اطلاعاتی که ذخیره شده است، در ابتدا بازیابی میشود.
این مساله برای وقفه ها هم برقرار است. فرض بر این است که یک کد در حافظه flash در حال اجرا است و در حین اجرا وقفه اتفاق میافتد. در این حین روند اجرای برنامه متوقف میشود و به آدرس مشخصی در حافظه flash پرش داده میشود و آن کد اجرا میشود، پس از پایان وقفه به برنامه اصلی برگشت داده میشود.
وقتی وقفه پذیرفته میشود آدرس محل برگشت به صورت خودکار توسط cpu در stack ذخیره میشود. بنابراین در هنگام برگشت از وقفه آن آدرس بازیابی میشود.
برگشت از سابروتین ها با دستور اسمبلی RET و برگشت از وقفه با دستور RETI انجام میگیرد. فرق این دو دستور از نظر بازگشت از وقفه به غیر از بازیابی آدرس بازگشت این است که، با دستور RETI ،فلگ I که در جلسه قبل توضیح داده شد اگر قبل از اجرای دستورالعمل یک باشد مجددا یک میشود، به این معنا که اگر وقفه ها مجوز وقوع داشته باشند زمانی که برنامه به این دستور میرسد علاوه بر اینکه به آدرسی که در stack به صورت خودکار ذخیره شده است برگشت داده میشوند، فلگ I که مجوز وقوع وقفه است یک خواهد شد.
بر حسب مدیریتی که بر روی حافظه انجام میشود ممکن است محل ذخیره سازی STACK توسط کامپایلر به جای انتهای SRAM در نقاط دیگری تعریف شود.
اگر نوع برنامه نویسی به صورت غیر اصولی باشد و سابروتینها بیش از حد معمول به صورت تو در تو تعریف شده باشند حالت STACK OVER FLOW پیش میآید. بدین معنا که اگر سابروتین ها از حد مجاز تجاوز کنند با برنامه اصلی در حافظه تداخل ایجاد میشود و وارد شدن این دو اطلاعات به هم منجر به عدم عملکرد صحیح میشود.
در کامپایلرهای مختلف بسته به تعریف متغییرها نوع فضای اشغال شده در SRAM فرق میکند. ظرفیت SRAM در شمارههای مختلف، متفاوت است بدیت صورت که ممکن است شمارهای از نظر تعداد پایهها ،سختافزارهای داخلی و …کفایت کند ولی از نظر فضای SRAM کافی نباشد، باید شماره دیگری را در نظر گرفت. بنابراین در کاربرد با توجه به نوع برنامه و عملکرد آن فضای SRAM میتواند بسیار مهم باشد.
یک پین علاوه بر وظیفه I/O میتواند نقشهای دیگری اعم از وظیفه ورودی و خروجی اتصالات جانبی به سختافزارهای داخل میکروکنترلر را نیز داشته باشد.
تایمر و کانتر:
در خانواده AVR تایمرها به دو صورت 8 بیتی و 16 بیتی وجود دارند به این معنا که یک تایمر و یا یک کانتر به طول 8 یا 16 بیت تعبیه شده است که میتواند کلاک خود را به صورت داخلی و در شرایط دیگری خارج از میکروکنترلر تأمین کند.
زمانی که کلاک از خارج میکروکنترلر تأمین میشود اصطلاحاً به آن کانتر گفته میشود و اگر با کلاک مشخصی کانتر تغذیه شود به آن تایمر گفته میشود.
اگر میزان کلاک یک شمارنده مشخص و ثابت باشد میتوان از تغییرات آن شمارنده به گذشت زمان پی برد از همین رو نام تایمر به آن اطلاق میشود، اما زمانی که پالسی از بیرون به میکروکنترلر وارد شود به دلیل نامعلوم بودن فاصله زمانی پالسها به آن کانتر یا EVENT COUNTER گفته میشود که اتفاق های بیرون از میکروکنترلر را قرائت میکند.
در خانواده AVR کانتر به صورت ،UP COUNTER عمل میکند، یعنی اصولاً با وارد شدن هر کلاک یک شماره به تایمر اضافه میشود. حداکثر مقداری که یک تایمر 8 بیتی میتواند در خود جای دهد از 0 تا 255 است. (یا به صورت هگزا دسیمال از 0X00 تا 0XFF). در اینجا برای رسیدن تایمر به مقدار 255، تعداد 255 کلاک باید وجود داشته باشد و برای دوباره صفر شدن نیاز به یک کلاک بیشتر یعنی مقدار 256 است.
همچنین این مقدار برای یک تایمر 16 بیتی از 0X0000 تا 0XFFFF یعنی از 0 تا 65535 وجود دارد. برای حرکت از حداکثر مقدار به حداقل مقدار یک کلاک نیاز است.
طبق گفته های جلسات قبل کلاک از منابع مختلفی از جمله کلاک داخل میکروکنترلر یا تقسیم شده های آن و یا منابع بیرونی تامین میشود. در بعضی از شماره ها ممکن است یک کریستال فرکانس پایین با فرکانس 32768 هرتز وجود داشته باشد که تأمین کننده نوسان فرکانس اسیلاتوری است و میتواند مقدار تایمر را تغییر دهد. در موارد خاص که نیاز به زمان بندی دقیق است میتوان از آن استفاده کرد.
تایمرها حالت های متفاوتی دارند و بسته به اینکه از چه نوع حالت یا MODE استفاده میشود، میتوان محدوده تغییرات آن را تغییر داد.
لزوم وجود تایمر در کنار CPU، محول کردن عملیات زمانگیری توسط سخت افزار تایمر است. در طول اجرای برنامه، تایمرها توسط کدهای برنامهنویسی در حالتی که قرار است انجام وظیفه کنند تنظیم میشوند و بعد از آن وظیفه سخت افزاری خود را انجام میدهند، حسن اینکار کمتر شدن بار پردازشی CPU است.
برای مثال لازم است بدانیم هرموقع تایمر 16 بیتی به مقدار حداکثر خود رسید و با یک کلاک صفر شد، نیاز است CPU اطلاع حاصل کند که تایمر OVER FLOW شده است. تا قبل از این مقدار CPU هیچگونه دخالتی در جریان این کار ندارد و به انجام کارهای دیگری میپردازد. پس از رسیدن تایمر به مقدار مشخص فلگ مربوط به فضای I/O یک میشود و اگر مجوز وقوع وقفه وجود داشته باشد وقفه ایجاد میشود و توسط CPU به آدرس مربوطه پرش ایجاد میکند و برنامه مورد نظر اجرا میشود. یا به وسیله روش polling یا مراجعه مکرر CPU به بیت مشخص، از تغییرات آن اطلاع حاصل کند.
در نتیجه پی میبریم که وجود تایمر ها باعث میشود بخشی که مربوط به زمانبندی و یا شمارش باشد به جای انجام در CPU به تایمر ها محول شود و بار پردازشی CPU کمتر شود.
در قسمت دهم آموزش میکروکنترلر AVR به شیوه استفاده از تایمرها و جزئیات آن ها و همچنین وقفه ها میپردازیم. با سیسوگ همراه باشید.
سری مقالات آموزش میکروکنترلر AVR توسط آقای مهندس کینژاد تهیه شده است.
ببخشید اینجا پرسیدم
سلام Zeus عزیز
پیشنهاد می کنید برای خریدش؟Logic analyzer 8CH 24Mhz
مرسی
سلام
من خودم دارم و خیلی هم کارم رو راه انداخته 🙂
خیلی خوب توضیح دادید ممنون
🙂