في هذه المرحلة سوف نتعرف على كيفية استخدام هذه المكتبة مع معالجات 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 .







