في هذه المرحلة سوف نتعرف على كيفية استخدام هذه المكتبة مع معالجات SAM التي هي معالجات 32 بت من نوع ARM Cortex-M0 . من إنتاج شركة Microchip .
تعرفنا في السابق على كيفية إنشاء مشروع جديد باستخدام المكتبة Syra uF . والتي هي نظام غير متزامن تعتمد على مبدأ الأحداث . وهي مصممة لبناء تطبيقات قابلة للتوسع للمعالجات التحكمية.
سنختار عائلة المعالجات SAMD20 لهذه الدورة . ويمكن تحميل نسخة من هذه المكتبة من الرابط التالي :
Syra uF ARM SAMD20 Release v1.4.0
وللإطلاع على الأجزاء السابقة من هذه الدورة , نجدها في الروابط التالية :
المكتبة Syra uF للمعالجات التحكمية – المقدمة
المكتبة Syra uF للمعالجات التحكمية – الأساسيات
في هذا الجزء سوف نتعلم كيفية كتابة المهام الجديدة . وإضافتها للمشروع . وتسجيلها في النظام .
سنأخذ مثالاً عن كتابة مهمتين لتشغيل أضواء LED موصولة مع أطراف المعالج .
لنفرض الضوء الأخضر موصول مع الطرف الأول PA00 من البوابة A .
والضوء الأحمر موصول مع الطرف الثاني PA01 من البوابة A .
أولا نقوم بإنشاء مشروع جديد في بيئة البرمجة ATMEL Studio . وهذا ما تم شرحه سابقاً في الأجزاء السابقة من هذه الدورة .
ولنفرض أننا اخترنا الاسم SuF_Example للمشروع . وتختار نوع المعالج ATSAMD20E17A على سبيل المثال .
إضافة المهام للمشروع :
أولا نقوم بإضافة ملف جديد للمشروع لنكتب فيه الكود الخاص بهذه المهام وذلك كما يلي :
- من نافذة Solution Explorer نضع المؤشر على اسم المشروع ونضغط بالزر اليمين .
- تظهر قائمة نختار منها Add لإضافة عنصر جديد ، فتظهر قائمة جديدة صغيرة .
- نختار منها New Item كما في الشكل اتالي :
بعدها تظهر نافذة جديدة نختار فيها نوع الملف الذي نريد إضافته ، ونكتب اسم الملف الذي نريده .
في مثالنا هذا نختار نوع الملف C File لاننا نريد إضافة ملف لكتابة كود بلغة C .
ونكتب اسم الملف tasks.c لأننا سنكتب فيه جميع المهام ، وهذا لسهولة الشرح .
لكن بشكل عام يفضل كتابة كل مهمة في ملف منفصل وذلك لتمييز الملفات في المشروع عن بعضها .
ثم نضغط على Add لإضافة الملف للمشروع .
- نعيد الخطوات السابقة وذلك لإضافة ملف ثاني من نوع Include File ، وهذا من متطلبات لغة البرمجة C .
أيضا نختار الاسم نفسه للملف الجديد tasks.h ، ثم نضغط Add .
هكذا يصبح لدينا ملفين جديدين في المشروع كما في الشكل :
في البداية هذه الملفات فارغة ، لذلك نفتح الملف tasks.c لكتابة المهمة الأولى .
قلنا أن المهمة الأولى وضيفتها تشغيل وإطفاء الضوء الأخضر بشكل متكرر . مرة كل ثانية .
قلنا أن الضوء الذي لونه أخضر موصول مع الطرف الأول PA00 من البوابة A .
أولا يجب أن نحدد هذا الطرف على أنه خرج ، وهذا يكون مرة واحدة عند بداية البرنامج ، أي في مرحلة الاقلاع .
لذلك نكتب الأوامر التي نريدها أن تعمل مرة واحدة عند الإقلاع بشكل منفصل ضمن تابع خاص . نعتبره تابع التهيئة للمهمة .
وهنا لدينا مهمتبين . سنكتفي بتابع تهيئة واحد للمهمتين .
مثلا نكتب التابع التالي ونعطيه اسم اختياري وليكن tasks_Setup
ونكتب بداخله أوامر تعريف الطرف المطلوب على انه خرج كما يلي :
void tasks_Setup() { // تحديد الطرف الموصول مع الضوءالأخضر على أنه خرج REG_PORT_DIRSET0 = PORT_PA00; // قد نحتاج تحديد قيمة أولية للطرف // هنا مثلا نختار أن يكون الضوء منطفئ REG_PORT_OUTCLR0 = PORT_PA00; // تحديد الطرف الموصول مع الضوءالأحمر على أنه خرج REG_PORT_DIRSET0 = PORT_PA01; // قد نحتاج تحديد قيمة أولية للطرف // هنا مثلا نختار أن يكون الضوء منطفئ REG_PORT_OUTCLR0 = PORT_PA01; }
طبعا بالتأكيد يمكن ان نكتب جميع الأوامر التي نريدها أن تنفذ عند الإقلاع ضمن هذا التابع .
ثانيا نكتب تابع جديد ليكون هو المهمة التي نريد كتابة الجزء الرئيسي من الكود بداخلها .
ونختار إسم للتابع أو للمهمة وليكن Green_Task
ونكتب بداخل هذا التابع الجزء الخاص بتشغيل و إطفاء الضوء الأخضر ، لأن هذا هو الكود الذي نريد ان يتم تنفيذه بشكل متكرر .
وفي حالتنا هذه نحتاج الأمر التالي الذي يقوم بتغيير حالة الطرف PA00 :
REG_PORT_OUTTGL0 = PORT_PA00 ;
ثم الانتظار لمدة ثانية او 1000 ميلي ثانية ، من خلال الامر التالي :
TaskWait(1000);
فيصبح التابع بالشكل :
// مهمة الضوء الأخضر void Green_Task() { // هذا الأمر لتغيير حالة الطرف الموصول مع الضوء الأخضر REG_PORT_OUTTGL0 = PORT_PA00; // هذا الأمر لتحديد زمن الانتظار قبل إعادة تنفيذ المهمة TaskWait(1000); }
نكرر نفس العملية السابقة لإضافة مهمة ثانية خاصة بالضوء الأحمر ، مع مراعاة أن الضوء الأحمر موصول مع الطرف الثاني من البوابة PORTA . وأن هذه المهمة سيتم تنفيذها كل 500 ميلي ثانية.
وهنا تصبح المهمة بالشكل التالي :
// مهمة الضوء الأحمر void Red_Task() { // هذا الأمر لتغيير حالة الطرف الموصول مع الضوء الأحمر REG_PORT_OUTTGL0 = PORT_PA01; // هذا الأمر لتحديد زمن الانتظار قبل إعادة تنفيذ المهمة TaskWait(500); }
هكذا نكون قد انتهينا من كتابة توابع المهام المطلوبة ، وكذلك تابع التهيئة .
لكن حتى يفهم النظام أن هذا التابع هو مهمة يجب عليه تنفيذها ، لابد من تسجيلها في النظام .
وأن تابع التهيئة هو من الاوامر التي يجب أن تعمل مرة واحدة عند الاقلاع يجب تعريف ذلك في النظام ليعمل البرنامج بالشكل الصحيح .
تسجيل المهام في النظام :
أولا بحسب قواعد البرمجة بلغة C . يجب إضافة تعريف التوابع التي كتبناها سابقة جميعها في الملف tasks.h , وذلك لتصبح مرئية لباقي أجزاء المشروع.
/* * tasks.h الملف */ void tasks_Setup(); void Green_Task(); void Red_Task();
ثانيا نضيف تعريف للملف tasks.h في الملف inc.h الذي قلنا أنه وسيلة الربط بين أجزائ المشروع.
فيكون محتوى الملف inc.h كما في الشكل :
/* // inc.h */ #include "SMF/core.h" #include "main.h" //-------------------------- // في هذا المكان نضيف التعريف #include "tasks.h"
ثم ننتقل للجزء الأهم وهو تسجيل المهام في النظام .
يوجد قسم خاص لكتابة الأوامر التي نريدها أن تنفذ في مرحلة الإقلاع . وذلك ضمن التابع OnBoot في الملف main.c .
نقوم أولا باستدعاء تابع التهيئة في هذا القسم , ومن ثم تسجيل المهام .
بالنسبة لاستدعاء تابع التهيئة ، الموضوع بسيط جدا ، فقط نكتب اسم اتابع .
أما إنشاء المهمة فيتم بالاستعانة بالأمر Sys_CreateTask وهو من الاوامر الخاصة بالمكتبة لإنشاء المهام .
حيث نستدعي هذا الأمر . ونمرر إسم المهمة لهذا التابع . مع الانتباه لعدم كتابة اسم المهمة مع الأقواس .
لأننا نريد تمرير اسم المهمة للتابع . وليس استدعاء المهمة . الشكل التالي يوضح ذلك :
/* // main.c */ void OnBoot() { // استدعاء تابع التهيئة للمهام tasks_Setup(); // تسجيل المهمة الأولى في النظام Sys_CreateTask(Green_Task); // تسجيل المهمة الثانية في النظام Sys_CreateTask(Red_Task); // الآن كل شيئ جاهز للعمل }
هكذا نكون قد انتهينا من كتابة المهام المطلوبة ، وتابع التهيئة ، وقمنا بتسجيل جميع المهام في النظام بشكل جيد .
نقوم ببناء المشروع من خلال الأمر Build في بيئة البرمجة .
وبعدها ننقل الملف التنفيذي الناتج للمعالج عبر المبرمجة للتجريب العملي .
وهكذا نكون قد انتهينا من كتابة برنامج للمعالج التحكمي يحتوي أكثر من مهمة . بالاعتماد على المكتبة Syra uF .