مشاريع الميكروكونترولر المتقدمة بلغة السى نظام تشغيل الزمن الفعلى (الحقيقى) RTOS والمترجم CCS C :

استعرض الموضوع السابق استعرض الموضوع التالي اذهب الى الأسفل

مشاريع الميكروكونترولر المتقدمة بلغة السى نظام تشغيل الزمن الفعلى (الحقيقى) RTOS والمترجم CCS C :

مُساهمة من طرف Admin في الأحد يونيو 07, 2015 11:48 pm

مشاريع الميكروكونترولر المتقدمة بلغة السى نظام تشغيل الزمن الفعلى (الحقيقى) RTOS والمترجم CCS C :
تعدد المهام وأنظمة تشغيل "الوقت الحقيقى" RTOS :
تقريبا جميع الأنظمة القائمة على الميكروكونترولر تؤدى أكثر من نشاط (مهمة) . على سبيل المثال ، نظام مراقبة درجة الحرارة يتم عمله من خلال ثلاثة مهام والتى عادة ما تتكرر بعد تأخير بسيط ، هذه المهام هى :
• المهمة رقم 1 : قراءة reads درجة الحرارة .
• المهمة رقم 2 : تشكيل formats درجة الحرارة .
• المهمة رقم 3 : عرض displays درجة الحرارة .
الأنظمة الأكثر تعقيد قد يكون بها مهام معقدة كثيرة . فى النظام متعدد المهام ، هذه المهام المتعددة تتطلب وقتا من وحدة المعالجة المركزية ، وحيث أن هناك وحدة معالجة مركزية واحدة ، لذلك ، فإنه يلزم شكلا من أشكال التنظيم والتنسيق بحيث أن يكون لكل مهمة الوقت الذى تحتاجه من وحدة المعالجة المركزية . عمليا ، كل مهمة تأخذ قدر وجيز جدا من الزمن ، لذلك فإنه يبدو كما لو أن جميع المهام يتم تنفيذها على التوازى وفى وقت واحد .
تقريبا كل الأنظمة القائمة على الميكروكونترولر تعمل فى الزمن الحقيقى . نظام الزمن الحقيقى هو نظام سريع (حساس) الاستجابة للزمن وهو يمكن أن يستجيب لبيئته فى أقصر وقت ممكن .
الوقت الحقيقى لا يعنى بالضرورة أن الميكروكونترولر يعمل عند سرعة عالية . المهم فى نظام الزمن الحقيقى هو زمن الاستجابة السريع ، على الرغم من أن السرعة العالية يمكن أن تساعد . على سبيل المثال ، نظام زمن حقيقى قائم على الميكروكونترولر مع مفاتيح خارجية مختلفة من المتوقع (المنتظر) أن يستجيب على الفور عندما يتم تفعيل مفتاح أو بعض وقوع بعض الأحداث الأخرى .
نظام تشغيل الزمن الحقيقى RTOS هو قطعة من الكود (عادة تسمى نواة أو بذرة أو اللب kernel) والتى تسيطر على توزيع المهام عندما يتم تشغيل الميكروكونترولر فى بيئة متعددة المهام . نظام تشغيل الزمن الحقيقى يقرر ، على سبيل المثال ، المهمة التالية next التى يتم تشغيلها ، وكيفية تنسيق أولويات المهمة ، وكيفية تمرير البيانات والرسائل بين المهام .
فى هذا الموضوع سوف يتم استعراض المبادىء الأساسية للأنظمة المدمجة embedded systems مع أمثلة على استخدام نظام تشغيل الزمن الحقيقى فى مشاريع بسيطة .
هناك عدة أنظمة RTOS متاحة تجاريا من أجل الميكروكونترولر PIC . حتى وقت كتابة هذا الموضوع ، ولحد علمى ، لم يوفر المترجم ميكروسى نظام RTOS ، فى حين أن المترجم CCS C PIC يوفر هذا النظام وهو ما سوف نعتمد علية فى هذا الموضوع .
مخطط حالة الماكينة (الجهاز) State Machine :

Admin
Admin

عدد المساهمات : 1003
تاريخ التسجيل : 28/01/2014

معاينة صفحة البيانات الشخصي للعضو http://fathallaabdelaziz.forumarabia.com

الرجوع الى أعلى الصفحة اذهب الى الأسفل

مخطط حالة الماكينة (الجهاز) State Machine :

مُساهمة من طرف Admin في الإثنين يونيو 08, 2015 12:40 am

مخطط حالة الماكينة (الجهاز) State Machine :
مخطط حالات الماكينة هو عبارة عن أبنية بسيطة تستخدم تستخدم لتنفيذ أنشطة متعددة ، عادة تكون فى تسلسل . الكثير من أنظمة الحياة الواقعية يقع ضمن هذه الفئة . على سبيل المثال ، تشغيل غسالة الملابس أو غسالة الأطباق يتم وصفها بسهولة من خلال مخطط بناء حالة الماكينة .
ولعل أبسط طريقة لتنفيذ بناء حالة الماكينة فى لغة السى هو استخدام عبارة switch-case . على سبيل المثال ، نظام مراقبة درجة الحرارة له ثلاث مهام ، تسمى Task 1, Task 2, Task 3 كما هو مبين فى الشكل التالى :




قطعة الكود التالية تبين طريقة تنفيذ حالة الماكينة للثلاث مهام باستخدام عبارة switch-case :



الكود:


for(;;)
{
state = 1;
switch (state)
{
CASE 1:
implement TASK 1
state++;
break;
CASE 2:
implement TASK 2
state++;
break;
CASE 3:
implement TASK 3
state = 1;
break;
}
Delay_ms(n);
}


حالة البدء هى الحالة “1” ، وكل مهمة تقوم بزيادة رقم الحالة بواحد لاختيار الحالة التالية التى سوف يتم تنفيذها . الحالة الأخيرة تختار الحالة “1” ، وهناك تأخير عند نهاية عبارة switch-case . يتم تنفيذ بناء حالة الماكينة بشكل مستمر داخل حلقة for ، لانهاية لها .
فى العديد من التطبيقات ، قد لا نحتاج تنفيذ الحالات فى تسلسل . لذلك ، بدلا من ذلك يتم اختيار الحالة التالية بواسطة الحالة الحالية إما مباشرة أو بناء على شرط ما ، كما هو مبين فيما يلى :




الكود:


for(;;)
{
state = 1;
switch (state)
{
CASE 1:
implement TASK 1
state = 2;
break;
CASE 2:
implement TASK 2
state = 3;
break;
CASE 3:
implement TASK 3
state = 1;
break;
}
Delay_ms(n);
}

على الرغم من أن مخطط حالة الماكينة سهل التنفيذ إلا أنه بدائى واستخدامه محدود . فهو يمكن أن يستخدم فقط فى الأنظمة التى لا تستجيب فعليا ، وحيث أنشطة المهام معرفة جيدا ولم يتم تحيد أولويات المهام .
علاوة على ذلك ، بعض المهام قد تكون أكثر أهمية من غيرها . وقد نرغب فى تشغيل بعض المهام كلما تصبح مؤهلة (مطلوبة) . على سبيل المثال ، فى عملية تصتيع ، المهمة التى تقوم بتشغيل الإنذار عندما تكون درجة الحرارة مرتفعة جدا . هذا النوع من التنفيذ يتطلب نظام متطور مثل نظام تشغيل الزمن الحقيقى RTOS .

نظام تشغيل الزمن الحقيقى (الفعلى) RTOS :

Admin
Admin

عدد المساهمات : 1003
تاريخ التسجيل : 28/01/2014

معاينة صفحة البيانات الشخصي للعضو http://fathallaabdelaziz.forumarabia.com

الرجوع الى أعلى الصفحة اذهب الى الأسفل

نظام تشغيل الزمن الحقيقى (الفعلى) RTOS :

مُساهمة من طرف Admin في الإثنين يونيو 08, 2015 10:55 am

نظام تشغيل الزمن الحقيقى (الفعلى) RTOS :
تبنى أنظمة تشغيل الزمن الحقيقى حول نواة متعددة المهام والتى تسيطر على تخصيص شرائح زمنية للمهام . الشريحة الزمنية هى الفترة الزمنية التى تمتلكها مهمة معينة للتنفيذ قبل أن يتم إيقافها واستبدالها بمهمة أخرى . هذه المهمة ، والتى تعرف أيضا باسم "تبديل السياق أو الحالة" context switching ، تتكرر باستمرار . عندما يحدث تبديل السياق ، يتم إيقاف تنفيذ المهمة ، ويتم حفظ سجلات المعالج فى الذاكرة ، يتم تحميل سجلات المهمة التالية المتاحة إلى وحدة المعالجة المركزية ، ويبدأ تنفيذ المهمة الجديدة . كما يوفر نظام RTOS أيضا مرور الرسائل من مهمة إلى مهمة ، وتزامن المهام ، وتخصيص مشاركة الموارد للمهام .
الأجزاء الأساسية لنظام RTOS هى :
• الجدولة Scheduler .
• خدمات نظام RTOS .
• أدوات التزامن والرسائل .

الجدولة Scheduler :
الجدولة هى قلب كل نظام RTOS ، حيث أنها توفر الخوارزميات (خطوات البرنامج) لاختيار المهام لتنفيذها . الثلاثة خوارزميات الأكثر شيوعا (استخداما) وهى :
• الجدولة التعاونية Cooperative scheduling .
• جدولة الذهاب والإياب Round-robin scheduling .
• الجدولة الوقائية (الاستباقية) Preemptive scheduling .

الجدولة التعاونية :
لعلها تكون أبسط خوارزمية جدولة متاحة . فكل مهمة يتم تشغيلها حتى تكتمل وتتخلى عن وحدة المعالجة المركزية طوعا . الجدولة التعاونية لا يمكن أن تلبى احتياجات نظام ROTS ، حيث لا يمكنها أن تدعم تحديد أولويات المهام حسب الأهمية . أيضا ، فإن مهمة واحدة قد تستخدم وحدة المعالجة المركزية وقتا طويلا وتترك القليل من الوقت للمهام الأخرى . كما أن المجدول لا يوجد لديه السيطرة على زمن تنفيذ مختلف المهام . مخطط الحالة هو نموذج بسيط لتقنية الجدولة التعاونية .

جدولة الذهاب والإياب :
فى جدولة الذهاب والإياب ، لكل مهمة يتم تخصيص (تعيين) حصة متساوية من وقت وحدة المعالجة المركزية ، كما هو مبين بالشكل التالى :



يوجد عداد counter يتتبع شريحة الوقت لكل مهمة . فعند اكتمال شريحة الوقت لمهمة ما ، فإنه يتم مسح (تصفير) العداد ويتم وضع المهمة فى نهاية الدورة . المهام المضافة حديثا يتم وضعها فى نهاية الدورة مع تصفير العدادات الخاصة بها . وهذا يشبه الجدولة التعاونية ، من حيث أنه غير مفيد بشكل جيد فى نظام RTOS ، حيث أنه فى كثير من الأحيان تستغرق بعض المهام عدة ملى ثوانى فى حين أن البعض الآخر يتطلب مئات الملى ثوانى أو أكثر .

الجدولة الاستباقية (الوقائية) :
تعتبر الجدولة الاستباقية هى خوارزمية جدولة الزمن الحقيقى . فهى قائمة على الأولوية ، وكل مهمة تعطى أولوية معينة كما فى الشكل التالى :




المهمة ذات الأولوية الأعلى تحصل على وقت وحدة المعالجة المركزية . بشكل عام ، تدعم أنظمة RTOS مستويات ولوية تتراوح من 0 إلى 255 ، حيث الصفر هو الأعلى أولوية و 255 هو الأدنى أولوية .
فى بعض أنظمة RTOS حيث يمكن أن يكون هناك أكثر من مهمة واحدة على نفس المستوى من الأولوية ، عندئذ يتم مزج الجدولة الاستباقية مع جدولة الذهاب والإياب . فى مثل هذه الحالات ، المهام التى عند مستويات الأولوية الأعلى يتم تشغيلها قبل التى لها مستويات أقل ، والمهام التى عند نفس مستوى الأولوية يتم تشغيلها عن طريق الجدولة ذهابا وإيابا . إذا سبقت مهمة بواسطة مهمة ذات أولوية أعلى ، فإنه يتم حفظ عداد زمن التشغيل وبعد ذلك يتم إستعادته عندما يعود لها اليسطرة على وحدة المعالجة المركزية .
فى بعض النظم يتم تعريف فئة أولوية زمن حقيقى بشكل صارم حيث المهام فوق هذه الفئة قد تعمل لتكتمل ( أو تستمر فى العمل حتى يصبح المورد غير متوفر ) حتى لو كانت هناك مهام أخرى على نفس مستوى الأولوية .
فى نظام الوقت الحقيقى يمكن أن تكون المهمة فى أى من الحالات التالية , كما هو موضح بالشكل أدناه :
• متأهب (مستعد – جاهز) للتشغيل Ready to run .
• تشغيل Running .
• ممنوع (محظور) Blocked .



عند بداية إنشاء المهمة ، فهى عادة ما تكون جاهزة للتشغيل ويتم إدخالها فى قائمة المهام . من هذه الحالة ، ورهنا بخوارزمية الجدولة ، يمكن أن تصبح المهمة ، مهمة قيد التشغيل . ووفقا لشروط الجدولة الاستباقية ، سوف يتم تشغيل المهمة إذا كان لها الأولوية الأعلى فى النظام ولا تنتظر من أجل المورد .

المهمة قيد التشغيل تصبح مهمة محظورة إذا احتاجت مورد غير متوفر . على سبيل المثال ، مهمة قد تحتاج بيانات من محول من تناظرى لرقمى ADC ويتم حجزها (منعها) حتى تتوفر هذه البيانات . بمجرد أن يمكن الوصول للمورد ، تصبح المهمة الممنوعة مهمة قيد التشغيل إذا كانت مهمة الأولوية الأعلى فى النظام ، وإن لم تكن كذلك ، فإنها تنتقل إلى حالة الاستعداد (جاهز) ready . فقط ، يمكن أن يتم منع المهمة قيد التشغيل . لا يمكن منع المهمة فى حالة الاستعداد .
عندما تنتقل مهمة من حالة إلى أخرى ، فإن المعالج يحفظ سياق المهمة قيد التشغيل فى الذاكرة ، ويحمل سياق المهمة الجديدة من الذاكرة ، وبعد ذلك يتم تنفيذ التعليمات الجديدة على النحو المطلوب .
عادة توفر النواة kernel واجهة لمعالجة عمليات المهمة . عمليات المهمة النموذجية هى :
• إنشاء المهمة .
• حذف المهمة .
• تغيير أولوية المهمة .
• تغيير حالة المهمة .


خدمات نظام RTOS :

Admin
Admin

عدد المساهمات : 1003
تاريخ التسجيل : 28/01/2014

معاينة صفحة البيانات الشخصي للعضو http://fathallaabdelaziz.forumarabia.com

الرجوع الى أعلى الصفحة اذهب الى الأسفل

خدمات نظام RTOS : أدوات التزامن والتراسل :

مُساهمة من طرف Admin في الإثنين يونيو 08, 2015 11:34 am

خدمات نظام RTOS :
خدمات نظام RTOS هى الخدمات utilities التى يتم توفيرها عن طريق النواة والتى تساعد المطورين على إنشاء مهام زمن حقيقى بكفاءة . على سبيل المثال ، مهمة يمكن أن تستخدم خدمات الوقت time للحصول على التاريخ والوقت الحالى . بعض هذه الخدمات هى :
• خدمات معالجة (مناولة) المقاطعة .
• خدمات الوقت .
• خدمات إدارة الأجهزة .
• خدمات إدارة الذاكرة .
• خدمات المدخلات والمخرجات .

أدوات التزامن والتراسل :
أدوات التزامن والتراسل هى بنيات النواة التى تساعد المطورين على إنشاء تطبيقات الوقت الحقيقى . بعض هذه الخدمات هى :
• أعمدة الإشارة (السيمافورات) Semaphores .
• أعلام (رايات) الحدث Event flags .
• صناديق البريد Mailboxes .
• الأنابيب Pipes .
• قوائم انتظار الرسائل Message queues .

نظام RTOS والمترجم CCS PIC C :

Admin
Admin

عدد المساهمات : 1003
تاريخ التسجيل : 28/01/2014

معاينة صفحة البيانات الشخصي للعضو http://fathallaabdelaziz.forumarabia.com

الرجوع الى أعلى الصفحة اذهب الى الأسفل

نظام RTOS والمترجم CCS PIC C :

مُساهمة من طرف Admin في الإثنين يونيو 08, 2015 7:18 pm

نظام RTOS والمترجم CCS PIC C :
المترجم CCS PIC C هو واحد من مترجمات لغة السى الواسع الانتشار من أجل السلسلة PIC16 والسلسة PIC18 . بالإضافة إلى كونه مترجم ، فإنه يقدم العديد من الخدمات المفيدة الأخرى . بناء الجملة فى المترجم CCS C يختلف قليلا عن بناء الجملة مع المترجم mikroC ، لكن من لهم دراية بالميكروسى سوف يجدون أن CCS C سهل الاستخدام .
المترجم CCS C يدعم نظام RTOS للسلسلة PIC18 . هذا النظام يسمح للميكروكونترولر بتشغيل المهام بدون استخدام المقاطعات . عندما يتم جدولة المهمة للتشغيل ، فإنه يتم إعطاء السيطرة على المعالج لهذه المهمة . عندما يتم اكتمال المهمة أو لا تحتاج المعالج أكثر من ذلك ، فإن السيطرة تعود للدالة المرسلة ، والتى تعطى السيطرة على المعالج إلى المهمة المجدولة التالية . ولأن نظام RTOS لا يستخدم المقاطعات ولا هو استباقى (وقائى) ، فيجب على المستخدم التأكد من أنه لا يتم تشغيل مهمة إلى الأبد .للمزيد من المعلومات حول نظام RTOS ، يمكن الرجوع إلى دليل المستخدم للمترجم .
يوفر المترجم CCS C دوال نظام RTOS التالية ، بالإضافة إلى دوال لغة السى العادية :

الكود:

rtos_run()
Initiates the operation of RTOS. All task control operations are implemented after calling this function.

rtos_terminate()
Terminates the operation of RTOS. Control returns to the original program without RTOS. In fact, this function is like a return from rtos_run().

rtos_enable()
Receives the name of a task as an argument. The function enables the task so function rtos_run() can call the task when its time is due.

rtos_disable()
Receives the name of a task as an argument. The function disables the task so it can no longer be called by rtos_run() unless it is re-enabled by calling rtos_enable().

rtos_ yield()
When called from within a task, returns control to the dispatcher. All tasks should call this function to release the processor so other tasks can utilize the processor time.

rtos_msg_send()
Receives a task name and a byte as arguments. The function sends the byte to the specified task, where it is placed in the task’s message queue.

rtos_msg_read()
Reads the byte located in the task’s message queue.

rtos_msg_ poll()
Returns true if there is data in the task’s message queue. This function should be called before reading a byte from the task’s message queue.

rtos_signal()
Receives a semaphore name and increments that semaphore.

rtos_wait()
Receives a semaphore name and waits for the resource associated with the semaphore to become available. The semaphore count is then decremented so the task can claim the resource.

rtos_await()
Receives an expression as an argument, and the task waits until the expression evaluates to true.

rtos_overrun()
Receives a task name as an argument, and the function returns true if that task has overrun its allocated time.

rtos_stats()
Returns the specified statistics about a specified task. The statistics can be the minimum and maximum task run times and the total task run time. The task name and the type of statistics are specified as arguments to the function.



التحضير لنظام RTOS :


Admin
Admin

عدد المساهمات : 1003
تاريخ التسجيل : 28/01/2014

معاينة صفحة البيانات الشخصي للعضو http://fathallaabdelaziz.forumarabia.com

الرجوع الى أعلى الصفحة اذهب الى الأسفل

التحضير لنظام RTOS :

مُساهمة من طرف Admin في الإثنين يونيو 08, 2015 7:22 pm

التحضير لنظام RTOS :
بالإضافة إلى الدوال السابقة ، يجب أن يتم تحديد التوجيه #use rtos() فى بداية البرنامج قبل استدعاء أى من دوال نظام RTOS . صيغة هذا التوجيه كما يلى :

الكود:

#use rtos(timer=n, minor_cycle=m)


حيث بارامتر المؤقت timer يكون بين “0” و “4” ويحدد مؤقت المعالج الذى سوف يستخدم بواسطة نظام RTOS ، والبارامتر minor_cycle هو أطول زمن سوف يتم خلاله تشغيل أى مهمة . العدد المدخل هنا يجب أن يكون متبوعا بأى من التميزات التالية s, ms, us, ns ، كما يلى :

الكود:

#use rtos(timer=0,minor_cycle=100ms)
// this tells the compiler that the rtos functionality will be needed, that
// timer0 will be used as the timing device, and that the minor cycle for
// all tasks will be 100 miliseconds
 

بالإضافة إلى ذلك ، فإن خيار الاحصائيات statistics يمكن أن يتم تحديده بعد الخيار minor_cycle ، وفى هذه الحالة فإن المترجم سوف يحافظ على تتبع مسار الحد الأدنى والحد الأقصى لأزمنة المعالج التى تستخدمها المهمة عند كل استدعاء وعلى الزمن الكلى المستخدم .


إعلان المهمة Declaring a Task :

Admin
Admin

عدد المساهمات : 1003
تاريخ التسجيل : 28/01/2014

معاينة صفحة البيانات الشخصي للعضو http://fathallaabdelaziz.forumarabia.com

الرجوع الى أعلى الصفحة اذهب الى الأسفل

إعلان المهمة Declaring a Task :

مُساهمة من طرف Admin في الإثنين يونيو 08, 2015 7:25 pm

إعلان المهمة Declaring a Task :
يتم إعلان المهمة تماما مثل إعلان أى وظيفة أخرى ، لكن المهام فى تطبيق متعدد المهام لا يكون لديه أى وسائط arguments ولا تعيد return أى قيم . قبل أن يتم الإعلان عن المهمة ، هناك حاجة لتوجيه قبل المعالج #task لتحيد خيارات المهمة . صيغة هذا التوجيه كما يلى :

الكود:

#task(rate=n, max=m, queue=p)

حيث “rate” يحدد كيفية استدعاء المهمة / العدد المحدد يجب أن يكون متبوعا بالتمييز s, ms, us, ns . و “max” يحدد كم كم من وقت المعالج سوف تستخدمه المهمة فى تنفيذ المهمة لمرة واحدة . الزمن المحدد هنا يجب أن يكون مساويا أو أقل من الزمن المحدد بواسطة minor_cycle . و “queue” هو اختيارى ، وإذا وجد فإنه يحدد عدد البايتات التى تكون محجوزة للمهمى لتستقبل الرسائل من المهام الأخرى ، القيمة الافتراضية هى الصفر .
فى المثال التالى ، مهمة تسمى my_ticks تكون كل 20ms ومن المتوقع ألا تستخدم أكثر من 100ms من زمن المعالج . هذه المهمة يتم تحديدها مع عدم وجود الخيار queue :

الكود:

#task(rate=20ms, max=100ms)
void my_ticks()
{
...........
...........
}



المشروع الأول : وميض ليدات :

Admin
Admin

عدد المساهمات : 1003
تاريخ التسجيل : 28/01/2014

معاينة صفحة البيانات الشخصي للعضو http://fathallaabdelaziz.forumarabia.com

الرجوع الى أعلى الصفحة اذهب الى الأسفل

المشروع الأول : وميض ليدات :

مُساهمة من طرف Admin في الإثنين يونيو 08, 2015 7:33 pm

المشروع الأول : وميض ليدات :
فى هذا المشروع البسيط القائم على نظام RTOS ، يتم توصيل أربعة ليدات بالبتات الأدنى للمنفذ PORTB للميكروكونترولر PIC18F452 . يتكون البرنامج من أربعة مهام ، حيث كل مهمة تومض ليد عند معدل مختلف :
• المهمة الأولى تسمى  task_B0 ، تومض الليد المتصل بالطرف RB0 بمعدل 250ms .
• المهمة الثانية تسمى task_B1 ، تومض الليد المتصل بالطرف RB1 بمعدل 500ms .
• المهمة الثالثة تسمى task_B2 ، تومض الليد المتصل بالطرف RB2 مرة كل ثانية .
• المهمة الرابعة تسمى task_B3 ، تومض الليد المتصل بالطرف RB3 مرة كل 2 ثانية .
الشكل التالى يبين الدائرة الكهربية للمشروع :



فى هذه الدائرة يتم استخدام كريستال بتردد 4MHz ، وتوصيل الليدات الأربعة خلال مقاومات تحديد التيار إلى الأطراف RB0-RB3 للمنفذ POERB .
البرنامج قائم على المترجم CCS C  ، ويسمى RTOA1.C كما هو مبين أدناه :


الكود:


//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// SIMPLE RTOS EXAMPLE
// This is a simple RTOS example. 4 LEDs are connected to lower half of
// PORTB of a PIC18F452 microcontroller. The program consists of 4
// tasks:
// Task task_B0 flashes the LED connected to port RB0 every 250ms.
// Task task_B1 flashes the LED connected to port RB1 every 500ms.
// Task task_B2 flashes the LED connected to port RB2 every second
// Task task_B3 flashes the LED connected to port RB3 every 2 seconds.
// The microcontroller is operated from a 4MHz crystal
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#include <18F452.h>
#use delay (clock=4000000)
// Define which timer to use and minor_cycle for RTOS
#use rtos(timer=0, minor_cycle=10ms)
//////////////////////////////////////////////////////////////
// Declare TASK 1 - called every 250ms
#task(rate=250ms, max=10ms)
void task_B0()
{
output_toggle(PIN_B0); // Toggle RB0
}
////////////////////////////////////////////////////////
// Declare TASK 2 - called every 500ms
#task(rate=500ms, max=10ms)
void task_B1()
{
output_toggle(PIN_B1); // Toggle RB1
}
//////////////////////////////////////////////////////////////////
// Declare TASK 3 - called every second
//
#task(rate=1s, max=10ms)
void task_B2()
{
output_toggle(PIN_B2); // Toggle RB2
}
///////////////////////////////////////////////////////////////////////
// Declare TASK 4 - called every 2 seconds
//
#task(rate=2s, max=10ms)
void task_B3()
{
output_toggle(PIN_B3); // Toggle RB3
}
/////////////////////////////////////////////////////////////
// Start of MAIN program
//
void main()
{
set_tris_b(0);       // Configure PORTB as outputs
rtos_run();       // Start RTOS
}
////////////////////////////////////////////////////////////////////////////


البرنامج الرئيسى يكون عند نهاية البرنامج ، وداخل البرنامج الرئيسى :
• يتم إعلان أطراف المنفذ PORTB كمخارج ،
• ويتم بدء نظام RTOS عن طريق استدعاء الدالة rtos_run() .


الكود:


// Start of MAIN program
//
void main()
{
set_tris_b(0);       // Configure PORTB as outputs
rtos_run();       // Start RTOS
}
////////////////////////////////////////////////////////////////////////////


رأس (مقدمة) البرنامج :
• الملف الذى يحتوى إعلانات نظام RTOS للمترجم CCS C  يجب أن يتم تضمينه عند بداية البرنامج .
• التوجيه  #use delay يخبر المترجم بأننا نستخدم  ساعة بتردد 4MHz .
• بعد ذلك يتم إعلان مؤقت نظام RTOS على أنه المؤقت Timer 0 ، وإعلان زمن  minor_cycle بالقيمة 10ms وذلك باستخدام التوجيه #use rtos .



الكود:

#include <18F452.h>#use delay (clock=4000000)
// Define which timer to use and minor_cycle for RTOS
#use rtos(timer=0, minor_cycle=10ms)



يتكون البرنامج من أربعة مهام متماثلة :
• المهمة الأولى  task_B0 تومض الليد المتصل بالطرف RB0 بمعدل 250ms . وبالتالى فإن الليد تكون ON لفترة 250ms ، ثم تكون OFF لفترة 250ms . عبارة output_toggle  ، للمترجم CCS C  ، تستخدم لتغيير حالة الليد فى كل مرة يتم فيها استدعاء المهمة . فى المترجم CCS C  تستخدم PIN_B0 للإشارة إلى الطرف RB0 .


الكود:

//////////////////////////////////////////////////////////////
// Declare TASK 1 - called every 250ms
#task(rate=250ms, max=10ms)
void task_B0()
{
output_toggle(PIN_B0); // Toggle RB0
}
////////////////////////////////////////////////////////


لاحظ وجود التوجيه #task يليه مباشرة دالة المهمة المرتبطة بهذا التوجيه .

• المهمة الثانية  task_B1 تومض الليد المتصل بالطرف RB1 بمعدل 500ms بنفس الطريقة السابقة .


الكود:


// Declare TASK 2 – called every 500ms
//
#task(rate=500ms, max=10ms)
void task_B1()
{
output_toggle(PIN_B1); // Toggle RB1
}
//////////////////////////////////////////////////////////////////


• المهمة الثالثة  task_B2 تومض الليد المتصل بالطرف RB2 كل واحد ثانية بنفس الطريقة .


الكود:


// Declare TASK 3 – called every second
//
#task(rate=1s, max=10ms)
void task_B2()
{
output_toggle(PIN_B2); // Toggle RB2
}
///////////////////////////////////////////////////////////////////////


• وأخيرا ، المهمة الرابعة  task_B3  تومض الليد المتصل بالطرف RB3 كل 2 ثانية بنفس الطريقة .


الكود:


// Declare TASK 4 – called every 2 seconds
//
#task(rate=2s, max=10ms)
void task_B3()
{
output_toggle(PIN_B3); // Toggle RB3
}
/////////////////////////////////////////////////////////////



البرنامج المذكور أعلاه هو برنامج متعدد المهام ، حيث وميض الليدات يكون مستقلا عن بعضه البعض وفى وقت واحد (متزامن) .

النتيجة :






Admin
Admin

عدد المساهمات : 1003
تاريخ التسجيل : 28/01/2014

معاينة صفحة البيانات الشخصي للعضو http://fathallaabdelaziz.forumarabia.com

الرجوع الى أعلى الصفحة اذهب الى الأسفل

المشروع الثانى : مولد رقم عشوائى :

مُساهمة من طرف Admin في الإثنين يونيو 08, 2015 10:12 pm

المشروع الثانى : مولد رقم عشوائى :
هذا المشروع أكثر تعقيدا قليلا ، وفيه يتم توليد رقم عشوائى بين 0 و 255 . يتم توصيل 8 ليدات بالمنفذ PORTB للميكروكونترولر PUC18F452 . باإضافة إلى توصيل زر ضاغط إلى الطرف RD0 ، وليد بالطرف RD7 .
فى هذا المشروع يتم استخدام 3 مهام :
• المهمة الأولى Live يتم تشغيلها كل 200 ميكروثانية ، وتقوم بعمل وميض لليد المتصل بالطرف RD7 للإشارة إلى أن النظام يعمل .
• المهمة الثانية Generator ، وتقوم بتزايد متغير من 0 إلى 255 بشكل مستمر واختبار حالة الزر الضاغط . عندما يتم الضغط على الزر الضاغط ، يتم إرسال قيمة العد الحالى إلى مهمة العرض Display باستخدام قائمة انتظار الرسائل .
• المهمة الثالثة Display وتقوم بقراءة الرقم من قائمة انتظار الرسائل وإرسال البايت المستقبل إلى الليدات المتصلة بالمنفذ PORTB . وبالتالى ، فإن الليدات تعرض نموذج عشوائى فى كل مرة يتم فيها الضغط على الزر الضاغط .
الشكل التالى يبين المخطط الصندوقى ، يليه الدائرة الكهربية :







البرنامج :

Admin
Admin

عدد المساهمات : 1003
تاريخ التسجيل : 28/01/2014

معاينة صفحة البيانات الشخصي للعضو http://fathallaabdelaziz.forumarabia.com

الرجوع الى أعلى الصفحة اذهب الى الأسفل

البرنامج :

مُساهمة من طرف Admin في الإثنين يونيو 08, 2015 10:19 pm

البرنامج :

الكود:

//////////////////////////////////////////////////////////////////////////////////////////////////////////////
// SIMPLE RTOS EXAMPLE - RANDOM NUMBER GENERATOR
// This is a simple RTOS example. 8 LEDs are connected to PORTB
// of a PIC18F452 microcontroller. Also, a push-button switch is
// connected to port RC0 of PORTC, and an LED is connected to port
// RC7 of the microcontroller. The push-button switch is normally at logic 1.
// The program consists of 3 tasks called "Generator", "Display", and "Live".
// Task "Generator" runs in a loop and increments a counter from 0 to 255.
// This task also checks the state of the push-button switch. When the
// push-button switch is pressed, the task sends the value of the count to the
// "Display" task using messaging passing mechanism. The “Display” task
// receives the value of count and displays it on the PORTB LEDs.
// Task "Live" flashes the LED connected to port RC7 at a rate of 250ms.
// This task is used to indicate that the system is working and is ready for
// the user to press the push-button.
// The microcontroller is operated from a 4MHz crystal
//////////////////////////////////////////////////////////////////////////////////
#include <18F452.h>
#use delay (clock=4000000)
int count;
///////////////////////////////////////////////
// Define which timer to use and minor_cycle for RTOS
#use rtos(timer=0, minor_cycle=1ms)
/////////////////////////////////////////////////////
// Declare TASK "Live" - called every 200ms
// This task flashes the LED on port RC7
#task(rate=200ms, max=1ms)
void Live()
{
output_toggle(PIN_D7);
}
////////////////////////////////////////////////////////
// Declare TASK "Display" - called every 10ms
#task(rate=10ms, max=1ms, queue=1)
void Display()
{
if(rtos_msg_poll() > 0) // Is there a message ?
{
output_b(rtos_msg_read()); // Send to PORTB
}
}
///////////////////////////////////////////////////////////////////
// Declare TASK "Generator" - called every millisecond
#task(rate=1ms, max=1ms)
void Generator()
{
count++; // Increment count
if(input(PIN_D0) == 0) // Switch pressed ?
{
rtos_msg_send(Display,count); // send a message
}
}
//////////////////////////////////////////////////
// Start of MAIN program
//
void main()
{
set_tris_b(0); // Configure PORTB as outputs
set_tris_d(1); // RD0=input, RD7=output
rtos_run(); // Start RTOS
}
////////////////////////////////////////////////////////////


البرنامج الرئيسى :
يأتى فى نهاية البرنامج ، وفيه يتم أعاداد أطراف المنفذ PORTB كمخارج . أيضا إعداد الطرف RD0 كمدخل وباقى أطراف المنفذ PORTD مخارج .

الكود:


//////////////////////////////////////////////////
// Start of MAIN program
//
void main()
{
set_tris_b(0); // Configure PORTB as outputs
set_tris_d(1); // RD0=input, RD7=output
rtos_run(); // Start RTOS
}
///////////////////////////////////////////////////////////


رأس (مقدمة) البرنامج :
يتم استخدام المؤقت Timer 0 كمؤقت لنظام RTOS ، ويتم تحديد الزمن minor_cycle بواحد ثانية :

الكود:


///////////////////////////////////////////////
// Define which timer to use and minor_cycle for RTOS
#use rtos(timer=0, minor_cycle=1ms)
/////////////////////////////////////////////////////


يتكون البرنامج من 3 مهام :
• المهمة الأولى Live ويتم تشغيلها كل 200 ملى ثانية ، وتقوم بوميض الليد المتصل بالطرف RD0 . هذه الليد تشير إلى أن النظام يعمل :

الكود:


/////////////////////////////////////////////////////
// Declare TASK "Live" - called every 200ms
// This task flashes the LED on port RC7
#task(rate=200ms, max=1ms)
void Live()
{
output_toggle(PIN_D7);
}
////////////////////////////////////////////////////////

• المهمة الثانية Generator ويتم تشغيلها كل ملى ثانية وتقوم بتزايد متغير بايت يسمى count بصفة مستمرة . عندما يتم الضغط على الزر الضاغط فإن الطرف RD0 يذهب للحالة المنخفضة . عند حدوث ذلك فإن قيمة العداد الحالية يتم إرسالها إلى المهمة الثالثة Display باستخدام دالة نظام RTOS المسماه rtos_msg_send(display, count) ، حيث display هو اسم المهمة التى يتم إرسال الرسالة إليها ، و count هو البايت المرسل .

الكود:


///////////////////////////////////////////////////////////////////
// Declare TASK "Generator" - called every millisecond
#task(rate=1ms, max=1ms)
void Generator()
{
count++; // Increment count
if(input(PIN_D0) == 0) // Switch pressed ?
{
rtos_msg_send(Display,count); // send a message
}
}
//////////////////////////////////////////////////


• المهمة الثالثة Display : ويتم تشغيلها كل 10 ملى ثانية . هذه المهمة تقوم باختبار ما إذا كان هناك رسالة فى قائمة انتظار الرسائل . إذا كان هناك رسالة ، يتم استخراج الرسالة باستخدام دالة نظام RTOS المسماة call rtos_msg_read() ، ويتم أرسال البايت الذى تم قراءته إلى الليدات المتصلة بالمنفذ PORTB :

الكود:


////////////////////////////////////////////////////////
// Declare TASK "Display" - called every 10ms
#task(rate=10ms, max=1ms, queue=1)
void Display()
{
if(rtos_msg_poll() > 0) // Is there a message ?
{
output_b(rtos_msg_read()); // Send to PORTB
}
}
///////////////////////////////////////////////////////////////////

وهكذا ، فإن الليدات تعرض القيمة الثنائية للعداد كلما تم الضغط على الزر الضاغط . قائمة انتظار الرسائل يجب التحقق منها بواسطة استخدام الدالة rtos_msg_poll() ، لأن محاولة قراءة قائمة الانتظار بدون وجود أى بايتات فى القائمة قد يجمد البرنامج .
النتيجة :




Admin
Admin

عدد المساهمات : 1003
تاريخ التسجيل : 28/01/2014

معاينة صفحة البيانات الشخصي للعضو http://fathallaabdelaziz.forumarabia.com

الرجوع الى أعلى الصفحة اذهب الى الأسفل

المشروع الثالث : فولتميتر بإخراج على المنفذ التسلسلى RS232 :

مُساهمة من طرف Admin في الثلاثاء يونيو 09, 2015 4:56 pm

المشروع الثالث : فولتميتر بإخراج على المنفذ التسلسلى RS232 :

فى هذا المشروع والذى هو أكثر تعقيدا قليلا عن المشروع السابق ، يتم قراءة الجهد باستخدام المحول A/D ثم بعد ذلك يرسل خلال المنفذ التسلسلى إلى الكمبيوتر .
يتكون هذا المشروع من 3 مهام :
• المهمة الأولى Live ويتم تشغيلها مل 200 ملى ثانية وتقوم بعمل وميض لليد المتصل بالطرف RD7 للإشارة إلى أن النظام يعمل (ينبض بالحياة) .
• المهمة الثانية Get_voltage ، تقوم بقراءة القناة channel 0 للمحول A/D حيث طرف توصيل الجهد المراد قياسه . يتم إعادة تشكيل (صياغة) القيمة التى تم قراءتها ثم تخزينها فى متغير . يتم تشغيل هذه المهمة كل ثانية .
• المهمة الثالثة : To_RS232 وتقوم بقراءة الجهد المشكل وإرساله من خلال منفذ الاتصال RS232 إلى الكمبيوتر كل ثانية .
الشكل التالى يبين المخطط الصندوقى للمشروع :



والشكل التالى يبين الدائرة الكهربية :



فى هذا المشروع يستخدم الميكروكونترولر PIC18F8520 مع ساعة بتردد 10MHz ، ويمكن استخدام أى ميكروكونترولر من السلسلة PIC18F . يتم توصيل الجهد المراد قياسه إلى طرف الدخل التناظرى AN0 للميكروكونترولر . يتم توصيل الخرج RS232 TX من الميكروكونترولر (الطرف RC6) إلى دخل شريحة محول مستوى RS232 من نوع MAX232 ومن خرجها إلى المنفذ التسلسلى للكمبيوتر ، المنفذ COM1 على سبيل المثال ، باستخدام وصلة نوع D 9 طرف . يتم توصيل الطرف RD7 إلى ليد لبيان ما إذا كان المشروع فى حالة تشغيل .

البرنامج :

Admin
Admin

عدد المساهمات : 1003
تاريخ التسجيل : 28/01/2014

معاينة صفحة البيانات الشخصي للعضو http://fathallaabdelaziz.forumarabia.com

الرجوع الى أعلى الصفحة اذهب الى الأسفل

رد: مشاريع الميكروكونترولر المتقدمة بلغة السى نظام تشغيل الزمن الفعلى (الحقيقى) RTOS والمترجم CCS C :

مُساهمة من طرف Admin في الثلاثاء يونيو 09, 2015 5:01 pm

البرنامج :

الكود:

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// SIMPLE RTOS EXAMPLE - VOLTMETER WITH RS232 OUTPUT
// This is a simple RTOS example. Analog voltage to be measured (between 0V
// and +5V) is connected to analog input AN0 of a PIC18F8520 type
// microcontroller. The microcontroller is operated from a 10MHz crystal. In
// addition, an LED is connected to port in RD7 of the microcontroller.
// RS232 serial output of the mirocontroller (RC6) is connected to a MAX232
// type RS232 voltage level converter chip. The output of this chip can be
// connected to the serial input of a PC (e.g., COM1) so that the measured
// voltage can be seen on the PC screen.
// The program consists of 3 tasks called "live", "Get_voltage", and “To_RS232”.
// Task "Live" runs every 200ms and it flashes the LED conencted to port pin
// RD7 of the microcontroller to indicate that the program is running and is
// ready to measure voltages.
// task "Get_voltage" reads analog voltage from port AN0 and then converts
// the voltage into millivolts and stores in a variable called Volts.
// Task "To_RS232" gets the measured voltage, converts it into a character
// array and then sends to the PC over the RS232 serial line. The serial line
// is configured to operate at 2400 Baud (higher Baud rates can also be used if
// desired).
////////////////////////////////////////////////////////////////////////////////////
#include <18F8520.h>
#device adc=10
#use delay (clock=10000000)
#use rs232(baud=2400,xmit=PIN_C6,rcv=PIN_C7)
///////////////////////////////////////////////////////////////////////////////
unsigned int16 adc_value;
unsigned int32 Volts;
///////////////////////////////////////////////////
// Define which timer to use and minor_cycle for RTOS
////////////////////////////////////////////////////
#use rtos(timer=0, minor_cycle=100ms)
///////////////////////////////////////////////////////////////////
// Declare TASK "Live" - called every 200ms
// This task flashes the LED on port RD7
#task(rate=200ms, max=1ms)
void Live()
{
output_toggle(PIN_D7); // Toggle RD7 LED
}
////////////////////////////////////////////////////////////////
// Declare TASK "Get_voltage" - called every 10ms
#task(rate=2s, max=100ms)
void Get_voltage()
{
adc_value = read_adc(); // Read A/D value
Volts = (unsigned int32)adc_value*5000;
Volts = Volts / 1024; // Voltage in mV
}
/////////////////////////////////////////////////////////////////////
// Declare TASK "To_RS232" - called every millisecond
#task(rate=2s, max=100ms)
void To_RS232()
{
printf("Measured Voltage = %LumV\n\r",Volts); // send to RS232
}
/////////////////////////////////////////////////////////////
// Start of MAIN program
//////////////////////////////////////////////////
void main()
{
set_tris_d(0); // PORTD all outputs
output_d(0); // Clear PORTD
set_tris_a(0xFF); // PORTA all inputs
setup_adc_ports(ALL_ANALOG); // A/D ports
//////////////////////////////////////////////////
setup_adc(ADC_CLOCK_DIV_32); // A/D clock
set_adc_channel(0); // Select channel 0 (AN0)
delay_us(10);
/////////////////////////////////////
rtos_run(); // Start RTOS
}
/////////////////////////////////////////////////////////////


Admin
Admin

عدد المساهمات : 1003
تاريخ التسجيل : 28/01/2014

معاينة صفحة البيانات الشخصي للعضو http://fathallaabdelaziz.forumarabia.com

الرجوع الى أعلى الصفحة اذهب الى الأسفل

رد: مشاريع الميكروكونترولر المتقدمة بلغة السى نظام تشغيل الزمن الفعلى (الحقيقى) RTOS والمترجم CCS C :

مُساهمة من طرف Admin في الثلاثاء يونيو 09, 2015 5:07 pm

• فى بداية البرنامج يتم تحديد الميكروكونترولر المستخدم ، وتعريف المحول A/D ليعمل بدقة 10 بت ، وتعريف الساعة للعمل على تردد 10MHz ، وتحديد سرعة الاتصال RS232 لتكون 2400 baud . كما يتم إعلان المتغيرات التى سوف تستخدم فى البرنامج ، وأيضا يتم تعريف مؤقت نظام rtos والزمن minor_cycle باستخدام التوجيه #use rtos :

الكود:


////////////////////////////////////////////////////////////////////////////////////
#include <18F8520.h>
#device adc=10
#use delay (clock=10000000)
#use rs232(baud=2400,xmit=PIN_C6,rcv=PIN_C7)
///////////////////////////////////////////////////////////////////////////////
unsigned int16 adc_value;
unsigned int32 Volts;
///////////////////////////////////////////////////
// Define which timer to use and minor_cycle for RTOS
////////////////////////////////////////////////////
#use rtos(timer=0, minor_cycle=100ms)
///////////////////////////////////////////////////////////////////


فى الدالة الرئيسية يتم إعداد المنفذ PORTD كمخارج مع مسح جميع أطرافه . بعد ذلك يتم إعداد المنفذ PORTA كمداخل (الطرف A0 هو طرف الدخل التناظرى المستخدم) ، بعد ذلك يتم إعداد المحول A/D عن طريق تحديد ساعة المحول ، وتحديد القناة المستخدمة مع المحول channel(0) أى AN0 . ثم بعد ذلك يتم بدء نظام RTOS عن طريق استدعاء الدالة rtos_run() :

الكود:

   
/////////////////////////////////////////////////////////////
// Start of MAIN program
//////////////////////////////////////////////////
void main()
{
set_tris_d(0); // PORTD all outputs
output_d(0); // Clear PORTD
set_tris_a(0xFF); // PORTA all inputs
setup_adc_ports(ALL_ANALOG); // A/D ports
////////////////////////////////////////////////////
setup_adc(ADC_CLOCK_DIV_32); // A/D clock
set_adc_channel(0); // Select channel 0 (AN0)
delay_us(10);
/////////////////////////////////////
rtos_run(); // Start RTOS
}
/////////////////////////////////////////////////////////////


يتكون البرنامج من 3 مهام :
• المهمة الأولى Live يتم تشغيلها كل 200 ملى ثانية ، وتقوم بعمل وميض لليد متصل بالطرف RD7 للميكروكونترولر لبيان أن المشروع يعمل .

الكود:


///////////////////////////////////////////////////////////////////
// Declare TASK "Live" - called every 200ms
// This task flashes the LED on port RD7
#task(rate=200ms, max=1ms)
void Live()
{
output_toggle(PIN_D7); // Toggle RD7 LED
}
////////////////////////////////////////////////////////////////


• المهمة الثانية Get_voltage ، وتقوم بقراءة الجهد التناظرى من القناة channel 0 ( أى الطرف RA0 أو AN0) للميكروكونترولر . بعد ذلك يتم تحول قيمة القراءة الرقمية إلى مللى فولت بالضرب فى 5000 والقسمة على 1024 ، ثم يتم تخزين الجهد فى متغير شامل يسمى Volts .

الكود:


////////////////////////////////////////////////////////////////
// Declare TASK “Get_voltage” – called every 10ms
#task(rate=2s, max=100ms)
void Get_voltage()
{
adc_value = read_adc(); // Read A/D value
Volts = (unsigned int32)adc_value*5000;
Volts = Volts / 1024; // Voltage in Mv
}
/////////////////////////////////////////////////////////////////////


• المهمة الثالثة To_RS232 ، تقوم بقراءة الجهد المقاس من المتغير المشترك Volts وترسله من خلال المنفذ RS232 باستخدام عبارة لغة السى printf . يتم إرسال النتيجة فى الشكل التالى :

الكود:

Measured voltage = nnnn Mv


الكود:


/////////////////////////////////////////////////////////////////////
// Declare TASK "To_RS232" - called every millisecond
#task(rate=2s, max=100ms)
void To_RS232()
{
printf("Measured Voltage = %LumV\n\r",Volts); // send to RS232
}
/////////////////////////////////////////////////////////////

الشكل التالى يبين برنامج HyperTerminal يعمل على الكمبيوتر للحصول على الخرج من البرنامج :



نتيجة المحاكاة ببرنامج Proteus :




Admin
Admin

عدد المساهمات : 1003
تاريخ التسجيل : 28/01/2014

معاينة صفحة البيانات الشخصي للعضو http://fathallaabdelaziz.forumarabia.com

الرجوع الى أعلى الصفحة اذهب الى الأسفل

استعرض الموضوع السابق استعرض الموضوع التالي الرجوع الى أعلى الصفحة


 
صلاحيات هذا المنتدى:
لاتستطيع الرد على المواضيع في هذا المنتدى