في هذه المرحلة سوف نتعرف على كيفية استخدام هذه المكتبة مع معالجات XMEGA التي هي معالجات 8 بت من نوع AVR . من إنتاج شركة ATMEL سابقاً والتي أصبحت ملكاً لشركة Microchip .
تعرفنا في السابق على كيفية إنشاء مشروع جديد باستخدام المكتبة Syra uF . والتي هي نظام غير متزامن تعتمد على مبدأ الأحداث . وهي مصممة لبناء تطبيقات قابلة للتوسع للمعالجات التحكمية.
سنختار عائلة المعالجات XMega لهذه الدورة . ويمكن تحميل نسخة من هذه المكتبة من الرابط التالي :
Syra uF AVR XMega Release v1.4.0
وللإطلاع على الأجزاء السابقة من هذه الدورة , نجدها في الروابط التالية :
المكتبة Syra uF للمعالجات التحكمية – المقدمة
المكتبة Syra uF للمعالجات التحكمية – الأساسيات
في هذا الجزء سوف نتعلم كيفية كتابة المهام الجديدة . وإضافتها للمشروع . وتسجيلها في النظام .
سنأخذ مثالاً عن كتابة مهمتين لتشغيل أضواء LED موصولة مع أطراف المعالج .
سنكمل المثال الذي بدأناه في الجزء السابق . الذي تم إنشائه لمعالح من نوع XMega . ويمكن للمبرمج أن يطبق نفس الخطوات مع أي نوع من المعالجات التي تدعمها هذه المكتبة .
لنفرض أننا نريد كتابة مهمتين منفصلتين عن بعض . تقوم كل واحدة منها بتشغيل ضوء مرة كل فترة زمنية معينة.
لنأخذ المخطط التالي لتوصيل الأضواء مع أطراف المعالج :
إضافة المهام للمشروع :
أولا نقوم بإضافة ملف جديد للمشروع لنكتب فيه الكود الخاص بهذه المهام وذلك كما يلي :
- من نافذة Solution Explorer نضع المؤشر على إسم المشروع ونضغط بالزر اليمين .
- تظهر قائمة نختار منها Add لإضافة عنصر جديد ، فتظهر قائمة جديدة صغيرة .
- نختار منها New Item كما في الشكل التالي :
بعدها تظهر نافذة جديدة نختار فيها نوع الملف الذي نريد إضافته ، ونكتب اسم الملف الذي نريده .
في مثالنا هذا نختار نوع الملف C File لاننا نريد إضافة ملف لكتابة كود بلغة C .
ونكتب اسم الملف tasks.c لأننا سنكتب فيه جميع المهام ، وهذا لسهولة الشرح .
لكن بشكل عام يفضل كتابة كل مهمة في ملف منفصل وذلك لتمييز الملفات في المشروع عن بعضها .
ثم نضغط على Add لإضافة الملف للمشروع .
- نعيد الخطوات السابقة وذلك لإضافة ملف ثاني من نوع Include File ، وهذا من متطلبات لغة البرمجة C .
أيضا نختار الاسم نفسه للملف الجديد tasks.h ، ثم نضغط Add .
هكذا يصبح لدينا ملفين جديدين في المشروع كما في الشكل :
في البداية تكون الملفات الجديدة فارغة . وقبل البدء بكتابة الأوامر لدينا قاعدة هامة :
كل ملف ينتهي باللاحقة c مثل الملف tasks.c وأي ملف نضيفه للمشروع يجب أن نكتب في بدايته تعليمة تضمين الملف inc.h :
#include “inc.h”
وكذلك كل ملف ينتهي باللاحقة h مثل tasks.h يجب أن يتم تضمينه في ملف الربط inc.h . وذلك لتصبح هذه الملفات متوافقة مع نظام عمل المكتبة . فيصبح محتوى الملف inc.h بالشكل التالي :
/* // inc.h ملف الربط */ #include "SMF/core.h" #include "main.h" //-------------------------- // في هذا المكان نضيف التعريف #include "tasks.h"
والآن نفتح الملف tasks.c لكتابة المهمة الأولى . حيث قلنا أن المهمة وظيفتها تشغيل وإطفاء ضوء بشكل متكرر .
بفرض الضوء الذي لونه أخضر موصول مع الطرف PIN0 من البوابة A .
أولا يجب أن نحدد هذا الطرف على أنه خرج ، وهذا يكون مرة واحدة عند بداية البرنامج ، أي في مرحلة الاقلاع .
لذلك نكتب الأوامر التي نريدها أن تعمل مرة واحدة عند الاقلاع بشكل منفصل ضمن تابع خاص . نعتبره تابع التهيئة للمهمة .
وهنا لدينا مهمتبين . سنكتفي بتابع تهيئة واحد للمهمتين .
مثلا نكتب التابع التالي ونعطيه إسم اختياري وليكن tasks_Setup
ونكتب بداخله أوامر تعريف الطرف المطلوب على أنه خرج كما يلي :
void tasks_Setup() { // تحديد الطرف الموصول مع الضوءالأخضر على أنه خرج PORTA_DIRSET = PIN0_bm; // قد نحتاج تحديد قيمة أولية للطرف // هنا مثلا نختار أن يكون الضوء منطفئ PORTA_OUTCLR = PIN0_bm; // تحديد الطرف الموصول مع الضوءالأحمر على أنه خرج PORTA_DIRSET = PIN1_bm; // أيضا يمكن تحديد قيمة أولية للطرف // وأيضا نختار أن يكون الضوء منطفئ PORTA_OUTCLR = PIN1_bm; }
طبعا بالتأكيد يمكن ان نكتب جميع الأوامر التي نريدها أن تنفذ في البداية ضمن هذا التابع .
ثانيا نكتب تابع جديد ليكون هو المهمة التي نريد كتابة الجزء الرئيسي من الكود بداخله .
ونختار إسم للتابع أو للمهمة وليكن Green_Task
ونكتب بداخل هذا التابع الجزء الخاص بتشغيل و إطفاء الضوء الأخضر ، لأن هذا هو الكود الذي نريد أن يتم تنفيذه بشكل متكرر .
وفي حالتنا هذه نحتاج الأمر التالي الذي يقوم بتغيير حالة الطرف PIN0 :
PORTA_OUTTGL = PIN0_bm ;
ثم الانتظار لمدة ثانية او 1000 ميلي ثانية ، من خلال الأمر التالي :
TaskWait(1000);
فيصبح التابع بالشكل :
// مهمة الضوء الأخضر void Green_Task() { // هذا الأمر لتغيير حالة الطرف الموصول مع الضوء الأخضر PORTA_OUTTGL = PIN0_bm; // هذا الأمر لتحديد زمن الانتظار قبل إعادة تنفيذ المهمة TaskWait(1000); }
نكرر نفس العملية السابقة لإضافة مهمة ثانية خاصة بالضوء الأحمر ، مع مراعاة أن الضوء الأحمر موصول مع الطرف الثاني من البوابة PORTA . وأن هذه المهمة سيتم تنفيذها كل 500 ميلي ثانية.
وهنا تصبح المهمة بالشكل التالي :
// مهمة الضوء الأحمر void Red_Task() { // هذا الأمر لتغيير حالة الطرف الموصول مع الضوء الأحمر PORTA_OUTTGL = PIN1_bm; // هذا الأمر لتحديد زمن الانتظار قبل إعادة تنفيذ المهمة TaskWait(500); }
هكذا نكون قد انتهينا من كتابة توابع المهام المطلوبة ، وكذلك تابع التهيئة .
وبذلك يصبح محتوى الملف tasks.c بالكامل كالتالي :
/* // tasks.c محتوى الملف */ // تضمين ملف الربط مع النظام #include "inc.h" //////////////////////////// // تابع التهيئة للمهام void tasks_Setup() { // تحديد الطرف الموصول مع الضوءالأخضر على أنه خرج PORTA_DIRSET = PIN0_bm; // قد نحتاج تحديد قيمة أولية للطرف // هنا مثلا نختار أن يكون الضوء منطفئ PORTA_OUTCLR = PIN0_bm; // تحديد الطرف الموصول مع الضوءالأحمر على أنه خرج PORTA_DIRSET = PIN1_bm; // أيضا يمكن تحديد قيمة أولية للطرف // وأيضا نختار أن يكون الضوء منطفئ PORTA_OUTCLR = PIN1_bm; } //////////////////////////// // مهمة الضوء الأخضر void Green_Task() { // هذا الأمر لتغيير حالة الطرف الموصول مع الضوء الأخضر PORTA_OUTTGL = PIN0_bm; // هذا الأمر لتحديد زمن الانتظار قبل إعادة تنفيذ المهمة TaskWait(1000); } //////////////////////////// // مهمة الضوء الأحمر void Red_Task() { // هذا الأمر لتغيير حالة الطرف الموصول مع الضوء الأحمر PORTA_OUTTGL = PIN1_bm; // هذا الأمر لتحديد زمن الانتظار قبل إعادة تنفيذ المهمة TaskWait(500); }
لكن حتى يفهم النظام أن هذه التوابع هي مهام يجب عليه تنفيذها في حلقة المهام ، لابد من تسجيلها في النظام .
وأن تابع التهيئة هو من الأوامر التي يجب أن تعمل مرة واحدة عند الإقلاع يجب تعريف ذلك في النظام ليعمل البرنامج بالشكل الصحيح .
تسجيل المهام في النظام :
أولا بحسب قواعد البرمجة بلغة C . يجب إضافة تعريف التوابع التي كتبناها سابقة جميعها في الملف tasks.h , وذلك لتصبح مرئية لباقي أجزاء المشروع.
/* * tasks.h الملف */ void tasks_Setup(); void Green_Task(); void Red_Task();
ثم ننتقل للجزء الأهم وهو تسجيل المهام في النظام .
قلنا أن التابع OnBoot الموجود في الملف main.c . خاص لكتابة الأوامر التي نريد تنفيذها في مرحلة الإقلاع .
لذلك نقوم باستدعاء تابع التهيئة في هذا القسم , ومن ثم تسجيل المهام .
بالنسبة لاستدعاء تابع التهيئة ، الموضوع بسيط جدا ، فقط نكتب إسم التابع .
أما تسجيل المهمة فيتم بالاستعانة بالأمر Sys_CreateTask وهو من الاوامر الخاصة بالمكتبة لتسجيل المهام .
حيث نستدعي هذا الأمر . ونمرر إسم المهمة لهذا التابع . مع الإنتباه لعدم كتابة إسم المهمة مع الأقواس .
لأننا نريد تمرير إسم المهمة . وليس استدعاء المهمة . الشكل التالي يوضح ذلك :
/* // main.c */ void OnBoot() { // استدعاء تابع التهيئة للمهام tasks_Setup(); // تسجيل المهمة الأولى في النظام Sys_CreateTask(Green_Task); // تسجيل المهمة الثانية في النظام Sys_CreateTask(Red_Task); // الآن كل شيئ جاهز للعمل }
هكذا نكون قد انتهينا من كتابة المهام المطلوبة ، وتابع التهيئة ، وقمنا بتسجيل جميع المهام في النظام بشكل جيد .
نقوم ببناء المشروع من خلال الأمر Build في بيئة البرمجة .
وبعدها ننقل الملف التنفيذي الناتج للمعالج عبر المبرمجة للتجريب العملي .
وهكذا نكون قد انتهينا من كتابة برنامج للمعالج التحكمي يحتوي أكثر من مهمة . بالاعتماد على المكتبة Syra uF .