قسم الميكروكنترولر والروبوت ودوائر الاتصال بالحاسب الالي قسم المتحكمات الـ microcontroller و المعالجات microprocessor و التحكم الرقمي بالكمبيوتر CNC والانظمة الآلية والروبوت Robots

   

ماجد عباس محمد
:: نائب المشرف العام
::
تاريخ التسجيل: Jun 2009
الدولة: القاهرة - مصر
المشاركات: 11,652
نشاط [ ماجد عباس محمد ]
قوة السمعة:
قديم 02-07-2018, 09:02 AM المشاركة 57   
افتراضي اعتبارات عملية فى تنفيذ مثل هذه ألبوردات




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

رجاء للفحص و الدراسة وليس التطبيق حاول تصفح مرسل إذاعة FM ، ستجد كم المشاكل حول أنه لم يعمل كثيرة رغم أننى نفذت أكثر من واحد – المشكلة فقط "أنه كان متاحا لى راسم ذبذبات يرسم و يحسب هذا التردد" و من ثم علمت كم هو بعيد عن التردد المطلوب.
الآن ماذا يهمك و أنت تدرس متحكم؟ رجاء راجع حجم الملف المستخدم ستجده ثلاث إلى 5 لفات على قلم رصاص رفيع أى طول السلك لا يزيد عن10 سم. كم هو طول خطوط التغذية لديك؟؟
تغليظ المسارات يقلل من الأثر لكنه ليس بالقدر المطلوب، وفى هذا المجال

التوصيل على اليسار أكثر أمنا و أقل تأثيرا عن التوصيل على اليمين وهذا يعنى أن مسارات تغذية الريلايات من المنبع تكون منفصلة تماما عن باقى المكونات الإلكترونية ولا تجعل الرجوع مشتركا إلا فى نقطة البدء
أيضا وضع مكثف بجوار كل ريلاى أو فى مدخل تغذيتهم سيجعل نبضات الريلاى مأخوذة منه ولا تعبره لباقى الدوائر
لو تستخدم وسائل خارجية مثل الموتورات و السولينويدات أى صمامات المياه الكهربية فكلها قد تعمل من220 متردد و الريلاى سيتحكم فيها. حسنا ضوضاء هذه المعدات ستشكل مشكلة أيضا لذا عادة ما تفصل مساراتها عن مسارات وحدة التغذية.
استخدام وحدات تغذية مثبتة الجهد و تقطيعية تقلل كثيرا من أثر هذه الضوضاء لأنها تعتمد التقطيع ثم التخلص من أثره. و استخدام مرشح دخول للبوردة يقلل كثيرا من أثر هذه التداخلات.
استخدام مرشح تغذية يفيد جدا فى التخلص من أثر هذه التداخلات Line Filter و ممكن أن يكون على البوردة لو تغذى من مصدر متردد سواء 220 أو 12 فولت أو يكون قبل محول الدخول.

أيضا يجب الاهتمام جيدا بتغذية المتحكم ذاته حتى لا تدخل له نبضات من طرفى التغذية. كما أن الكثير لا يعبأ بطرف MCLR أو RESET فإما تلغيه و تهيء الطرف كمدخل / مخرج وتعتمد على الريسيت الذاتى مع انخفاض الفولت و تضع على طرفى التغذية مكثفات كافية أو تجعله طرف بدء تشغيل و توصله بالمقاومة و المكثف المناسبين
أيضا لا تنسى أن وضعك مكثف 100 ميكروفاراد لا يغنى عن واحد 0.1 ميكرو على ألتوازى معه و الأفضل أن يكون قرص سيراميك لأن لف طبقات المكثف يخلق ملف داخلى يعوق الاستجابة للترددات العالية.

قبل البدء قى تحويل البرنامج باللغات العالية سنبدأ فى المرة القادمة فهم ما هى اللغات العالية وهو موضوعنا القادم إن شاء الله

اعلانات

ماجد عباس محمد
:: نائب المشرف العام
::
تاريخ التسجيل: Jun 2009
الدولة: القاهرة - مصر
المشاركات: 11,652
نشاط [ ماجد عباس محمد ]
قوة السمعة:
قديم 03-07-2018, 09:01 AM المشاركة 58   
افتراضي هيكل اللغات العالية و تكونها



هيكل اللغات العالية و مم تتكون:
اللغات العالية تشترك فى مجموعة من الصفات مع اختلافات فى نص كتابتها و قد تتعجب أنها تتكون من 10 أوامر فقط تنقسم لثلاثة أقسام هى الشروط Conditions و الدورات Iteration ثم القفز أو الانتقال Jump
قبل دراسة تفاصيلها ندرس الهيكل العام لأى برنامج
الهيكل العام:
تبدأ بالتسميات حيث تعطى لأى مكون اسم مريح من واقع الدائرة لتذكرك ما دور كل اسم سواء كان منفذ كامل أو طرف من منفذ أو مكون داخلى كمسجل أو علم Flag أو قيمة ثابتة أو متغيرة الخ. التسميات لا تأخذ أى ذاكرة لأنها تنتهى عند بدء الترجمة حيث يستبدل المترجم كل اسم بما يساويه سواء أكان مكون أو حتى معادلة رياضيه (كثير من المترجمات تسمح بهذا وليست الكل) . هذه التسميات تكون بالتعليمه Alias أو Symbol حسب المترجم باسكوم أو ميكروإلكترونيكا و يفضل غالبا و يحتم أحيانا كثيرة أن يكون فى أول البرنامج لحاجة المترجم لها لترجمة باقى الأسطر .
يلى ذلك التعريفات حيث تعرف المتغيرات و الثوابت اسم كل منها و حجمه (كم بايت) وهل هو موجب فقط أم موجب و سالب كما سبق الشرح و هل هى رقم عشرى Float
يلى ذلك تعريف ألدوال و الوظائف حيث يمكن تعريفها وكتابة الكود اللازم لها أو نكتفى بالتعريف فقط و نضع الكود لها لاحقا.
فى اللغات العالية يتكون البرنامج من مجموعة من الوظائف و قد تحتاج ألدوال أيضا و الوظيفة هى ببساطة مجموعة أوامر متتابعة تؤدى مهمة معينه. مثلا اكتب على الشاشة كذا الخ ولا ناتج لها سوى العمل المطلوب. أما ألدوال فهى مشابهة إلا أنها تعطى نتيجة مثلا جيب الزاوية فهى دالة أعطيها 30 تعطينى نصف لأن جا 30 = 0.5
هذه الأسماء عامة أى تشمل البرنامج كاملا بكافة أقسامه. أغلب المترجمات تسمح بالتعريف داخل الدالة أو الوظيفة و يكون ظهور هذه القيمة داخل الدالة فقط مثلا لو عرفت دالة باسم "Send" و عرفت داخلها قيمة "Count" فقيمة Count هذه لا تستطيع أى تعليمه فى البرنامج خارج "Send" أن تصل إليها و تتعامل معها.
تعريف الوظيفة:
هى مجموعة تعليمات بين بداية و نهاية يحددان ما يخص هذه الوظيفة ففى البيزك نجد باسكوم تستخدم فى قسم التعريفات
كود:
Declare Sub InitLCD 
Declare Sub Testvar(b As Byte , I As Integer , W As Word )
و الكلمة الأولى هى Declare وتعنى إشهار أو إعلان ثم كلمة Sub اختصار Subroutine للدلالة أنها لا تعطى نتيجة حسابية ثم يلى ذلك اسمها وهو InitLCD وهى تهيئه الشاشة LCD و يمكن أن تضيف () قوسين لتذكرك أنها لا تقبل بيانات أو بالصورة فى السطر التالى وهى باسم Testvar لاختبار متغيرات مثلا ثم تضع بين قوسين أسماء لهذه المتغيرات غير الأسماء التى سبق لك استخدامها فى التعريفات مع كلمة As و حجم أو نوع كل منها ولو أكثر من واحد تفصل بينهم بفاصلة)
لاحقا فى البرنامج و حيث تريد لهذه الوظيفة أن توضع فى الذاكرة بين باقى البرنامج تكتب ما يلى
كود:
Sub InitLCD
.
.
End Sub

Sub Testvar(b As Byte , I As Integer , W As Word )
.
.
.
End Sub
هذه الطريقة تتيح لك أن تقسم الذاكرة حسب ما تريد و تضع كل وظيفة أو دالة بالضبط حيت ترى ، أما طريقة ميكروإلكترونيكا فيجب أن تعلنها و تضعها قبل استخدامها هكذا أو تكتب كلمة Forward كما سيلى
كود:
SUB PROCEDURE DoThisThing ()
	.
	.
	.
End Sub
البداية هى كلمة Sub اختصار Subroutine ثم كلمة PROCEDURE للدلالة أنها لا تعطى نتيجة حسابية (لا معنى لتكرار الأمر هنا ولكنها ليست قياسية فى أى نظام بيزك) ثم يلى ذلك اسمها وهو ما عبرت عنه بكلمة DoThisThing ثم قوسين () لتبيان أننا لا نحتاج أى شيء لهذه الوظيفة أما لو مثل وظيفة الكتابة على الشاشة مثلا تكون
كود:
SUB PROCEDURE  WriteLCD (Line2Print as string)
	.كود
	.
	.
End Sub
فتضع بين القوسين Line2Print as string وهى Line2Print مجرد اسم ليذكرك لاحقا ماذا تحتاج لأن تضع بدلا منه ثم as string تعريف أنها نص
و لكى تستخدم أى منهم نتبع الصيغة البسيطة كأى تعليمه أخرى مثلا
كود:
InitLCD
Testvar(5 , 20 , 1245 )
DoThisThing
WriteLCD (“ Hello World “)
تعريف الدالة
أما الدالة فتكون بطريقة باسكوم
Declare Function Myfunction(byval I As Integer , S As String) As Integer
و نغير كلمة Sub بكلمة Function للدلاله على أنها وظيفة تعيد نتيجة إما رقم أو نصوص أو ما تحدد لها
لاحقا وحيث تريد أن تضعها تكتب الكود لها هكذا
كود:
Function Myfunction(byval I As Integer , S As String) As Integer	.
	.كود
	.كود
	MyFunction = 2*I/y
End Function
السطر MyFunction = ….. هو نتيجة هذه الدالة التى سترد بها وهى تقابل مثلا فى الدالة الشهيرة لجيب الزوايا القيمة 0.5 لدالة جا30 ولا يشترط أن تكون آخر سطر بل يمكنك أن تجعلها مشروطة مثلا لو Length بكذا MyFunction = 1 ولو بكذا MyFunction = 2 الخ أى يمكم أن تتكرر بحسب الشروط.

و تطلبها كما تطلب أى دالة عادية فستحتاج مثلا أن تعرف بعض المتغيرات منها CurrentVal مثلا و تريد أن تضع فيه جا 30 ستكتب ببساطة
كود:
CurrentVal =  Sin(30)
CurrentVal =   Myfunction(5,”Day”)
والسطر التالى لو ستطلب ألداله Myfunction بدلا منها

أما بطريقة ميكروإلكترونيكا فيمكن تعريفها مسبقا بكتابة
sub function First(dim a as word, dim b as word) as word forward

البداية هى كلمة Sub اختصار Subroutine ثم كلمة function للدلالة على أنها تعيد نتيجة ثم يلى ذلك اسمها وهو ما عبرت عنه بكلمة First ثم قوسين () بينهما الأسماء و أحجامها و بعد ذلك كلمتى as word لتفيد أنها ستعيد قيمة بحجم Word و أخيرا كلمة forward للدلالة على أن الكود سيأتى لاحقا
لاحقا تضع الكود كما يلى

كود:
SUB  function First(dim a as word, dim b as word) as word
	.كود
	.كود
	.Result = 5*a/b
End Sub
و القيمة التى تعاد هى Result=... و نفس الشروط السابقة و طلبها كما فى المثال السابق أيضا.
ذكرنا سابقا أن التعريفات ذات مدى عام أو شامل تغطى كل الوظائف و ألدوال أى يمكن لأى منها أن تقرأ هذه التعريفات أو تغيرها بصرف النظر عن كونها دالة أو وظيفة لكن لو فى داخل أى دالة أو وظيفة أعلنت متغير جديد سيكون مجاله محليا فقط أى بداخل الدالة أو الوظيفة ولا يمكن التعامل معه خارجها.
لاحظ أن كل البرنامج مجموعة من الوظائف لذا على الأقل سيحتوى على وظيفة واحدة فقط و تسمى Main ولا تعلن بأى من الوظائف السابقة Declare , SUB و لذلك تنتهى بكلمة END فقط بدون أى إضافات .

فى لغة C نجد الأمر مختلف قليلا فلا يوجد وظيفة أو دالة ولكن كلها subroutine فإن أعاد شيئا فهو دالة وإلا فيكون وظيفة و الإعلان عنها كما يلى
كود:
int max(int x, int y) {
  return (x>=y) ? x : y;
}
أول كلمة int تعنى أن العائد من حجم Integer ، إذن هى دالة و ليست وظيفة و اسمها max و بين القوسين القيمتين المطلوب المفاضلة بينهما و حجم كل منهما ثم القوس المعوج الشهير أما إن كانت void فتعنى خلاء او لا شيء فلا تعيد شيئا ومن ثم هى وظيفة.
القيمة التى سترد بها هى بعد return و طبعا نفس الشروط السابقة و هى هنا تقول ما بين القوسين x أكبر من أو تساوى y . أما بعدها نجد ؟ وهذه تعنى "هل ما بين القوسين صحيح؟ لو نعم صحيح أعد أو قيمة تالية وهى هنا X و إن لم تكن أعد القيمة التى تليها أى Y . عبقرية لكن حاول أن تتذكرها عندما تحتاجها أو تستنتجها ما لم أكن ذكرتها لك ولو خطأ ما فى النص حاول اكتشافه ، شخصيا أفضل كثيرا الصيغة
IF X>=Y THEN RESULT=X ELSE RESULT =Y
بسيطة و مفهومة بلا شرح و منطقية. - و أخيرا القوس المعوج الغالق .
هواة هذه اللغة يعيبون على لغة البيزك كلمة مثل End Sub , End Function.
حسنا كل الأوامر العشرة و كل وظيفة تنتهى بذات القوس “{” و المترجم يربطه بأقرب واحد مفتوح “}” ونادرا ما تكون دالة أو وظيفة لا تحتوى عدد من الأوامر المتداخلة
فعندما ترى { لا تعلم أى شيء يخص هذا القوس و تبذل جهدا كبيرا لتتبع الأقواس عبر الصفحات
أما لو وجدت END IF فقد علمت أنك أغلقت دورة IF ولم تغلق غيرها ولن تذهب END IF لأقرب شيء مفتوح مثل دورة For لأنه لا يخصها، لذلك أستطيع أن اركز اهتمامى على البرمجة و منطقها عوضا عن فوازير الأقواس التى لا تربح جوائز - معذرة هذا رأيى المتواضع و لكل رأى يسعد به
أخيرا لاحظنا كلمة ByVal ولم نقل عنها شيئا، هى اختصار By Value و مقابلها ByRef أى By Reference. لو لدينا متغير ما مثل Angle و لديك وظيفة باسم ChK_A فيها ستختبر قيمة Angle و بناء عليها تفعل خيار من خيارات كثيرة قد تحتاج لتعليمه مثل If sin(Angle) =.5 Then فماذا سيفعل المترجم؟؟
سابقا هو خصص مثلا الخانة 10 من الذاكرة لحفظ قيمة Angle و فى هذه اللحظة Angle=45 و الآن تطلب منه استخدام دالة من داخل دالتك ChK_A لحساب جيب الزاوية، إذن هل سيرسل للدالة قيمة 10 حيث تقبع قيمة Angle أم يرسل المحتوى 45؟ و ما الفرق !! كلاهما واحد!!
كلا الفرق شاسع فلو أرسل القيمة By_Val فالتغيير داخل الدالة سيكون على القيمة 45 فقط أما لو أرسلتها By_ref فالتغيير سيكون على محتوى الخانة. وهذا هو الوضع الافتراضى أى أن أى تغيير داخل الدالة سيطال المتغير الأصلى.
مهلا سبق أن قلت أن الدالة لا تعيد شيئا وهنا تقول أنها تغير من قيمة المتغيرات أى أنها تعيد شيئا!! أجل وهذه ميزة يمكنك استخدامها و تسمى الأثر الجانبى أو الغير مباشر Side Effect

المرة القادمة إن شاء الله نتكلم عن الأوامر أو الأكواد التى تستخدم لبناء البرنامج

اعلانات اضافية ( قم بتسجيل الدخول لاخفائها )

ماجد عباس محمد
:: نائب المشرف العام
::
تاريخ التسجيل: Jun 2009
الدولة: القاهرة - مصر
المشاركات: 11,652
نشاط [ ماجد عباس محمد ]
قوة السمعة:
قديم 04-07-2018, 09:39 AM المشاركة 59   
افتراضي الأكواد العشرة



الأكواد العشرة
تنقسم الأكواد العشر لثلاث مجموعات هى الشروط و الدورات و الانتقال
الشروط:
الأمر IF

الأول هو ما سبق شرحه IF و نعيد شرحه هنا أولا بالأسيمبلى كان فى صورة JB أو JNB وهما القفز لو بت =1 أو = صفر ولكن عموما تحتاج مقارنة رقمين لذا نستخدم معها الأمر CJNE وهو اختصار Compare and Jump if Not Equal وهى تقارن بين المراكم A و قيمة مباشرة أو محتوى ذاكرة مع المراكم أو محتوى مسجل مع المراكم أو باعتبار مسجل من R0,R1 حامل عنوان فيقارن المراكم بالذاكرة التى يشير إليها هذا المسجل أو مسجل مع قيمة مباشرة مثلا سنقارن محتوى المسجل R7 بالقيمة المباشرة 60 هيكسا و ننتقل لو مختلفين إلى Not_Eq. ما يحدث حقا هو طرح القيمة 60 هيكسا من محتوى R7 و بالتالى لو 60 أكبر ستسبب Carry =1 و إلا سيكون Carry = Zero و يمكن التحقق بالأمر JC أى قفز لو Carry =1

كود:
		CJNE R7, # 60H, NOT_EQ        ; . . .  . . . . .  ;R7 = 60H.
			Code if equal
			sjmp Finish
NOT_EQ: 	JC  REQ_LOW 		       ;	IF R7 < 60H.
		    Some Code	for R7 > 60H.	       ; . . . . . . . .  ;R7 > 60H.
		    sjmp Finish
REQ_LOW:    code for R7 < 60H.

Finish:

لو تريد أن تقارن شيء آخر ستضع قيمة فى R7 و الثانية فى الأمر المباشر و هكذا أى ستحتاج لأوامر MOV لتعديل القيم
نفس الشيء بالبيزك و مثال للمقارنة على التساوى فقط فى التالى أو يمكنك التعديل بلا يساوى أو اكبر من أو أصغر من أو ما تشاء من شروط متعددة

كود:
If Sw1 = 1  then
	Goto SW2test
Else
	LEDs = 254
End If

كما يمكنك أن تجعلها متداخلة Nested أى أكثر من أمر داخل بعض هكذا

كود:
If PORT1 = 1  then  		; Level 1
	Goto SW2test
Else  IF PORT2 = 1 THEN	; Level 2
	LEDs = 254
         ELSE            		; Level 2
	LEDs= 255
Else				; Level 1
         LEDs=255	
End If

لاحظ هنا نقطة مهمة IF الأولى استفسرت عن شيء ما وهو PORT1 بينما Else IF التالية استفسرت عن شيء آخر تماما وهو PORT2 وهذه قيمة هذا الأمر ولو عدنا للغة الأسيمبلى سنجد أن هذا الأمر سيضع PORT1 أولا فى المراكم A ثم يقارنها بالقيمة 1 و بعد ذلك يضع القيمة PORT2 فى المراكم ليقارنها بالقيمة الجديدة (و إن تساوت ظاهريا) 1 وفى كل مرة نستخدم أمر MOV قبل الاختبار
نقطة هامة أخرى، أين تضع End If يعتمد على المترجم فالمترجم باسكوم يعتمد Elseif و يعتبرها امتداد للأولى (وهذا من سمات لغة البيزك المرئى الأصلية للحاسبات) و من ثم تفاضل بين عديد من الخيارات و متى تحقق أحدها خرجت من الدورة ولذا تحتاج End if واحدة فقط فى آخرها و يمكنك وضع IF أخرى متداخلة حيث تشاء لتتمكن من فحص خيارات أخرى متى شئت و هذا يصعب فى ميكروإلكترونيكا فمثلا

كود:
If a = b then		'…...1
   Led0 = 1
elseif c=d then		'…....2
   Led1=1
elseif porta = 5 then     '…......3
 	if a= 8 then
	      Print Porta = 5 and a=8
	elseif  g=7 then
	      Motor1 = 1
	else
	      Motor 1 =0
	end if
else if Portc =0 	'….....4
    Led3=1
else			' ….....5
    Led4 = 0
end if

سنلاحظ هنا أن الشروط 1،2،3،4،5 تبادلية فإن تحقق 1 ينفذ الأمر Led0 = 1 ثم تخرج و إلا يفحص 2 و هكذا، بهذا فالشروط باللون الأحمر لن تفحص إلا لو لم تتحقق الشروط السابقة أولا ثم تحقق الشرط porta = 5 و عندها نتحقق كما لو ان كل أمر من الأحمر تعنى لو porta = 5 مع a= 8 و قد تكتب هكذا
(a= 8) AND (porta = 5)
إلا أننا وفرنا تنفيذ أمر AND فى كل تساؤل.
ميكروإلكترونيكا لا تعتمد elseif و تعتمد بدلا عنه else if بمسافة تفصل بينهما فتعتبر if التالية جديدة و تتطلب End If خاصة نفس فكرة أقواس السى وهذا يجعل الأمور معقدة و مربكة .
مما سبق أيضا نستنتج أن ترتيب الأوامر يعطى أولوية الاختبار فقد يسبب تساؤل عن أمر ما أقل أهمية فى عدم فحص أمر آخر أكثر أهمية .


و لنكتبه بلغة C

كود:
if (PORT1=1) {
	goto SW2test ;
		}
else  if (PORT2) {
	LEDs = 254 ; 
		}
	else {
LEDs=255;
}
الآن علمنا أن هناك MOV زائدة فى كل أمر حتى لو كان المتغير لم يتغير لكن تريد مقارنته بعدة قيم ولا داعى لنقله كل مرة للمراكم A لنقارنه ، فهذا سيوفر خانة ذاكرة فى كل اختبار و يزيد سرعة الاستجابة ، لذا كان الأمر الثانى.

الأمر Select case أو switch
وهو الثانى ، فكما رأينا الحاجة أم الاختراع فقد وضع هذا الأمر لمقارنة قيمة واحدة مقابل عدد كبير من الاحتمالات، لذا فهذا الأمر بالأسيمبلى سيكون ذات التعليمات السابقة و ستكرر الأمر CJNE عدة مرات كل مرة بقيمة اختبار أخرى و لكن لن تستخدم JC إلا لو احتجت لها و ستضع القيمة التى تختبرها مرة واحدة فقط فى المراكم وهى فى المثال التالى قيمة reg و بعد ذلك تكرر CJNE حسب ما تريد، أى ستوفر أمر MOV مع كل مقارنة.
و فى البيزك / باسكوم

كود:
select case reg
  case 0
           opmode = 0
  case 1,2,6
           opmode = 1
  case 5 TO 7
           opmode = 2
    Case  >  9   :   Print “Too High”
     Case else   :   PRINT “NOT Valid”
end select


السطر الأول نجد هو المتغير تحت الاختبار و من ثم يوضع أول الأمر فى المراكم ثم يقارن عدة مرات بعد ذلك. قد يكون أى متغير مثل PORT0 أو أى شيء تسميه أو حتى معادلة يجب حلها أولا مثل select case x*y/z
المهم أنها رقم صحيح (قيد بسبب الميكرو لكن فى الحاسبات الشخصية تكون أى شيء) أو قد يكون نصا أو حرف.
هذا المترجم يسمح من لغة البيزك الأصلية بكلمة TO لتحديد مدى "من إلى" كما يسمح بتعدد القيم 1,2,6 و بالعلاقات النسبية أكبر من أو أصغر من أو اكبر من و يساوى أو أصغر من و يساوى
لاحظ أنه لو تطابق المتغير مع أول شرط ستنفذ الأوامر المرتبطة به بكاملها (واحد أو أكثر) ثم يخرج آليا من الشرط ولا تختبر باقى الحالات. لو لم يتطابق فسيقارن التالى وهكذا

ميكروإلكترونيكا تستخدم الصيغة ذاتها مع تعديل طفيف

كود:
select case reg
     case 0
          opmode = 0
     case 1,2,3,4
          opmode = 1
     case 5,6,7
           opmode = 2
end select


وهو أنها لم تتبنى كلمة TO باعتبار أن القيم المتعددة قد تغنى لكن لن تكون مثلا مثل من 100 إلى 200 و لم تتبنى المقارنات > < >= <= أيضا.

بلغة السى نجدها

كود:
switch (phase) {
  case 0: Lo();  break;
  case 1: Mid(); break;
  case 2: Hi();  break;
  default: Message("Invalid state!");
}

حيث phase هى المتغير تحت المقارنة ثم تلى القيمة الأولى وهى صفر فينفذ الأمر لو متطابق ولا ينفذه لو غير مطابق و فى كلتا الحالتين سينتقل لاختبار القيمة التالية،(لماذا؟؟) لذا وجب وضع الأمر break حتى يخرج من الدورة عند تحقق الشرط !!!
لاحظ أيضا أنك لا تستطيع استخدام مدى من .. إلى .. ولا أكثر من قيمة 1,2,3,4 ولا نسب أكبر و أصغر الخ. رقم و فقط و بسبب ذلك قد تضطر لاستخدام أمر IF بدلا منها !!!!! أو تفضل البيزك مثلى
المرة القادمة إن شاء الله ندرس الدورات


ماجد عباس محمد
:: نائب المشرف العام
::
تاريخ التسجيل: Jun 2009
الدولة: القاهرة - مصر
المشاركات: 11,652
نشاط [ ماجد عباس محمد ]
قوة السمعة:
قديم 05-07-2018, 08:09 AM المشاركة 60   
افتراضي



الدورات Iteration
For Loop

الثالث و اشهرها إطلاقا هى دورة For أى بينما المتغير "ص" من كذا إلى كذا افعل هذا ثم عدل قيمة "ص" وهى بالأسيمبلى تكون هكذا
كود:
	MOV	R7,#50
Loop5:
	DoThis
	DJNZ	R7,Loop5
المتغير ص نريده = 50 لذا سنضع مثلا فى الذاكرة أو للأسرع فى المسجل R7 هذه القيمة بالأمر الأول. يليه عنوان بداية الدورة ثم مجموعة التعليمات المرغوب تنفيذها مشار إليها بكلمة DoThis و أخيرا الأمر DJNZ وهو اختصار Decrement and Jump if Not Zero و يليه ما يحتوى الرقم المطلوب إنقاصه ثم العنوان ألذى ينتقل إليه و هذا العنوان يجب أن يكون فى نطاق بايت واحدة أى 255 +128 إلى -127

هذا الأمر بالبيزك لكلا المترجمين
تأخذ الصورة For المتغير = البداية TO النهاية بخطوة عدد موجب أو سالب
كود:
 Dim A As Byte , B1 As Byte , C As Integer

For A = 1 To 10 Step 2
	Print "This is A " 			; A
Next A
 
Print "Now lets count down"
For C = 10 To -5 Step -1
	Print "This is C " 			; C
Next
نلاحظ هنا أن Step ليست ضرورة لو كانت = موجب 1. هذه الدورة تظل تنفذ التعليمات فى جسم الدورة حتى يزيد المتغير عن الحد الأقصى بعد كلمة To وهنا تتوقف الدورة. لاحظ أن الدورة تنتهى بكلمة NEXT وهى فى الدورات المتداخلة تتيح لك التذكر هذه تخص من فمثلا
كود:
For c = 1 To 10
	…
	For D = 2 to 8
		…
	Next D
	….	
	….
Next c
رغم أنك لا تحتاج كتابة الحرف و تكتفى بكلمة Next إلا أنها توضح لك أين يبدأ هذا و أين ينتهى ذاك . فى ميكروإلكترونيكا يجب كتابة المتغير وإن كان هذا ليس قياسيا فى لغة البيزك و يلوم البعض كلمة Next إلا أنها واضحة و تخص For ولن تخص دالة أخرى ولا تكملها أو تغلقها كما لو كانت كلها } و ممكن قوس For يغلق قوس IF خاصة حيت تكثر الأكواد عبر الصفحات.

أما بلغة C فلأمر كما هو معروف مختلف حيث تكون
كود:
for ( i = 0; i < n; i++ ) s += a[i] * b[i];
i = 0 هى حد البداية ثم فاصلة منقوطة ";” ثم i < n حد النهاية ولاحظ هنا أنه أقل من و ليست تساوى فلو كانت تساوى و العد زاد لن تنتهى الدورة كما يحدث فى البيزك لذا لو تريد مثلا 10 يجب أن تكتب أقل من 11 للتسهيل و البساطة و الوضوح. أخيرا i++ تعنى اضف واحد و بالمناسبة ++ على يمين المتغير تختلف عن على يساره حيث أحدهما تعنى أعد القيمة قبل الزيادة و الأخرى تعنى أعد القيمة بعد الزيادة ثم نغلق القوسين و نكتب ما نريد تنفيذه ثم نختم بالمقدسة ";”
لو لديك أكثر من أمر للتنفيذ عندها تضعهم بين قوسين معوجين {…..} و كل سطر ينتهى بالمقدسة ";”
هذه اللغة تتيح لك استخدام أكثر من متغير معا

Do Loop
الرابع و بذات كود الأسيمبلى السابق يمكنك أن تهئ هذه الدورة، يمكنك تحقيقها بالأمر DJNZ أو CJNE السابقين
أما بالبيزك فالصيغة المشتركة هى

كود:
A = 1                                                        'assign a var
Do                                                        	'begin a do..loop
	Print A                                        'print var
	Incr A                                          'increase by one
Loop Until A = 10                                    'do until a=10
فى السطر الأول تضع قيمة ما فى متغير ما تستخدمه حكم لإنهاء الدورة ، ثم تكتب " افعل Do " لتحدد بداية المطلوب و يلى ذلك مجموعة الأوامر حسب حاجتك و يجب أن تحتوى وسيله لتعديل هذا المتغير سواء بالبرنامج أو قد تكون خارجية حيث هذا المتغير مثلا قيمة المنفذ PORT0 أو قد يكون حالة طرف PORT0.3 و آخر سطر سيكون Loop Until A = 10 وهو يعنى كرر حتى يصل المتغير لهذه القيمة
كما لاحظت أننا نقول دوما ذات الكود، فعلا هى دورة تكرارية تنتهى بمقارنة ثم القفز للبداية أو القفز خارجها فلم نتوقع كود مختلف؟ هى فقط تعبيرات مختلفة لتسهيل الوصول للهدف
لو حذفت جملة Until A = 10 ستتحول إلى دورة غير منتهية فلا شرط ينهيها و هى بذلك تتحول إلى أمر GOTO وهى مطابقة للأمر AJMP أو LJMP بالأسيمبلى.
نلاحظ هنا أن الشرط Until A = 10 أو ما يسمى بالاختبار يكون فى آخر الدورة مما يضمن تنفيذها مرة واحدة على الأقل لذا سيكون لدينا أمر آخر لضمان عدم التنفيذ.
أما بلغة C
كود:
do {
 	 s += a[i] * b[i];
 	 i++;
} while ( i < n );
كلمة do ثم القوس المعوج لتحدد التعليمات المطلوب تكرارها ثم الأوامر المطلوب تكرارها مع مراعاة الشروط السابقة لتعديل قيمة المتغير الحاكم لإنهاء الدورة ثم تضع كلمة while و الشرط المطلوب تحقيقه بين قوسين و تنهى بالمقدسة

كما ذكرنا لو نريد عدم التنفيذ إطلاقا لو الشرط غير محقق نلجأ للأمر الخامس

While / While-WEND
الاختلاف الوحيد فى الأمر الخامس هو وضع الشرط و اختباره فى البداية و لهذا فإن لم يتحقق لا تنفذ باقى الأوامر و بالأسيمبلى فغنى عن التعريف أنها مسألة إعادة تنسيق للأوامر فقط
بالبيزك تكون

كود:
A = 1                                                       'assign var
While A < 10                                          'test expression
      Print A                                              'print var
      Incr A                                                'increase by one
Wend                                                      'continue loop
كما سبق الشرح سنضع فى متغير ما قيمة ما وهو حاكم الدورة ثم نضع الشرط ألذي بتحققه ننفذ ما يلى من تعليمات أما لو لم يتحقق نخرج و يجب ضمان تغير قيمة الحاكم حتى يصل بالشرط للخروج من الدورة و كما ذكرنا هذا المتغير قد يكون منفذ أو طرف من منفذ أو أى متغير آخر. و أيضا يمكن عمل دورة لا منتهية باستبدال الشرط بالرقم 1 أو البعض يسمح بكلمة TRUE و أخيرا تنتهى بكلمة Wend اختصار While End لكى ترى بوضوح أين تنتهى الأمور

بلغة C
كود:
while (i < n) {
	 s += a[i] * b[i]; i++;
 }
المرة القادمة إن شاء الله نتحدث عن المجموعة الأخيرة وهى الانتقال أو التفرع


ayam
:: مهندس جيد ::
تاريخ التسجيل: Dec 2005
المشاركات: 287
نشاط [ ayam ]
قوة السمعة:
قديم 06-07-2018, 02:00 AM المشاركة 61   
افتراضي


كلنا صامتين , نتابع و حفظك الله


ماجد عباس محمد
:: نائب المشرف العام
::
تاريخ التسجيل: Jun 2009
الدولة: القاهرة - مصر
المشاركات: 11,652
نشاط [ ماجد عباس محمد ]
قوة السمعة:
قديم 06-07-2018, 08:38 AM المشاركة 62   
افتراضي


كلنا صامتين , نتابع و حفظك الله
شكرا أخى الكريم ولكن لو لديك أسئلة رجاء عدم ابقاؤها حتى لا تتراكم التساؤلات

فى النهاية إن شاء الله سيوضع الشرح كاملا فى ملف PDF و يرفع


ماجد عباس محمد
:: نائب المشرف العام
::
تاريخ التسجيل: Jun 2009
الدولة: القاهرة - مصر
المشاركات: 11,652
نشاط [ ماجد عباس محمد ]
قوة السمعة:
قديم 06-07-2018, 08:44 AM المشاركة 63   
افتراضي الانتقال أو التفرع Branching



الانتقال أو التفرع Branching
الحقيقة هنا بعض الأوامر مختلفة بين اللغات لذلك فالعدد هنا يعتمد على اللغة لكن أشهرها و اعمها هى الأمر السادس
GOTO
و صيغته ببساطة Goto ثم العنوان المراد الانتقال إليه وهو غير مشروط ولا خلاف عليه فى اللغات وهو يسبب الانتقال المباشر من مكان هذا الأمر للعنوان المذكور بدون قيد أو شرط

ماذا يحدث لو دخلت فى دورة مثل For و تأكد لك أنها انتهت مبكرا لتحقق شرط ما أو اصبح الاستمرار فيها يسبب مشكلة ما؟
حسنا توافر لك الأمر السابع وهو Exit
Exit Break Continue
الأمر السابع هو أمر للخروج الطارئ وفى باسكوم لديك أربعة صور هى حيث Exit Sub و Exit Function هما ذات الشيء
EXIT FOR
EXIT DO
EXIT WHILE
EXIT SUB
EXIT FUNCTION
و تكتب كما هى أى لا تكتفى بكلمة Exit ولكن تتبعها بالدالة وهى للخروج الطارئ عند حدوث خطأ ما أو جدت أنه لا داعى للاستمرار . و سبب ضرورة ذكر اسم الدالة لا يخفى على أحد فغالبا ما تكون مثلا دورة For داخل وظيفة Function أو داخل دورة أخرى مثل Do لذا وجب تحديد مما تخرج بالضبط.
فى ميكروإلكترونيكا و فى كلا المترجمين البيزك و C قصرت على SUB أو Function وتكتب وحدها فقط أى لو لديك وظيفة أو دالة ثم فى خطوة ما وجدت أنه لا داعى للاستمرار أوحدث خطأ ما و يجب الخروج تكتبها فتعود لاستكمال الكود الأصلى.
أما باقى ألدوال For,DO,WHILE فقد استخدمت كلمة Break للخروج و نذكر أننا تعرضنا لها فى أمر Switch السابق و أضافت أمر آخر هو Continue لتفويت أو تخطى هذه الدورة فقط دون الخروج و استكمال باقى الدورات

الأمر الثامن هو العودة Return
Return
قبل مناقشته يجب أن نعود للأسيمبلى للارتباط الوثيق بينهما. كلنا نعلم ما هو Subroutine و لمن لا يعلم هو قطعة من الكود ستتكرر كثيرا فى البرنامج ولو أعدنا كتابتها قد لا نجد ذاكرة تكفى، تخيل أنك لو كل مرة تريد كتابة رقم أو حرف على شاشة ستكتب لها كود، كم مليون مرة ستحتاج لكل تحديث للمعروض ؟ ، لذا يكتب هذا الكود فى عنوان فى مكان ما من الذاكرة أى يبدأ بهذا العنوان وهذا الكود يسمى Subroutine أى إجراء فرعى وهو فى اللغات العالية تحول إلى دالة أو وظيفة أما كونه يعيد قيمة ما فببساطة يضعها فى خانات من الذاكرة محددة ليستغلها الكود الطالب لاحقا.
حسنا كيف ستنهيه إذن لتكمل باقى البرنامج أو حتى تكتب كود Subroutine آخر؟ أجل الأمر GOTO لكن مهلا نذهب لأين و أنا أصلا لا أعلم من أين استدعيت؟
حسنا يجب إذن أن نضيف لها أمر نهاية خاص بكود مختلف وهو أمر RET اختصار Return و أمر الانتقال إليه لا يكون بالأمر GOTO ولكن أيضا بأمر مختلف GOSUB
إذن المتحكم عندما يجد الأمر GOSUB متبوعا بعنوان ، يعلم أنه عائد للخطوة التالية لذا سيحفظ عنوان العودة (عنوان الخطوة التالية) فى الرصة Stack و يذهب لعنوان Subroutine المذكور فى الأمر و ينفذه و عندما ينتهى سيجد الأمر RET وهذا يجعله يستعيد العنوان من الرصة ليستأنف العمل حيث كان قبل طلب Subroutine
حسنا هذا جميل لكن مهلا هناك موضوع آخر على قدر كبير من الأهمية وهو المقاطعة ، عندما تحدث سيفعل المتحكم ذات الشيء من حفظ الخطوة التالية ثم الانتقال لعنوان خدمة المقاطعة و يوقف كافة المقاطعات التالية و يجب عندما يعود من خدمه المقاطعة أن يتيح المقاطعة أيضا إضافة لاسترجاع العنوان ، لذا فكود المقاطعة ينتهى بأمر مختلف هو RETI اختصار Return from Interrupt أى أن كلاهما سيعيد المتحكم للعنوان الصحيح لكن المقاطعة ستختلف و الخطأ فى استخدامها قد يسبب أن المتحكم يستجيب لأول مقاطعة ثم يمتنع بعد ذلك وقد تظن أنه لا يستجيب إطلاقا لو كانت أول مقاطعة من مصدر سريع مثل 50 هرتز الخ. هذا فضلا عن أن فى كثير من المتحكمات يتم حفظ بعض المسجلات آليا و استعادتها آليا لضرورة ما بها من بيانات و أهميتها.
هذا التمهيد يتيح لنا فهم الخلافات ففى ميكروإلكترونيكا جعلت الأمر Return واحدا وهو العودة للخطوة الطالبة أى ستولد RET أما لو كان الأمر يخص مقاطعة فإعلان كود المقاطعة هو ألذى سيحدد أن العودة ستكون RETI .
أما فى باسكوم فالأمر مختلف ، لو فى داخل شرط ستعطى RET ولو بدون شرط فأول واحدة فقط تعطى RETI وهذا فى رأى المتواضع تعقيد لا جدوى منه و سيفرض استخدام الأمر GOTO لتذهب حيث الأمر ألذى يعطى RETI

الأمر التاسع هو GOSUB
GOSUB هو أمر للانتقال إلى Subroutine سواء فى الكود أو داخل وظيفة أو دالة
قد ترى أن الأمر مكرر ولا جدوى من هذا الأمر لكن معذرة أخى الكريم فللضرورة أحكام و السبب ببساطة أنك لا تستطيع أن تعلن عن وظيفة أو دالة من داخل أخرى لذا فإن احتجت لتكرار كود داخل دالة فإما تجعله فى دالة منفصلة و هذا يزيد عددهم بلا داعى أو لو هذا التكرار لا يطلب إلا فى هذه الدالة أو وظيفة فقط فلتسهيل تتبع الكود يمكنك أن تجعلها داخلية بهذا الأمر وهى ستطال كافة المتغيرات أى لا حاجة لتفريقها كدالة أو وظيفة فهى فقط Subroutine
الأمر بسيط وهو GOSUB متبوعا بالعنوان وهو فى البيزك لكلا المترجمين لكن للأسف C لا يدعمه

الأمر العاشر و الأخير هو
On Value
استخدمت باسكوم أمرا من أوامر البيزك المرئى للحاسب مع المتحكمات و هو أن تكتب ON متبوعة بمتغير ثم تختار GOTO أو GOSUB ثم مجموعة من العناوين
كود:
ON var [GOTO] [GOSUB] label1 [, label2 ] [,CHECK]
لو المتغير = صفر سينتقل لأول عنوان أو لو = 1 سينتقل للثانى و هكذا ولو كان الرقم أكبر من عدد العناوين ستتلف الرصة لذا يمكنك إضافة الكلمة الأخيرة CHECK فلو حدث هذا لا يتم أى انتقال و ينفذ السطر التالى مباشرة

إذن ما هذه الضجة حول اللغات العالية و المترجمات؟
هى يا عزيزى تسمى المكتبات وهى مجموعة أوامر إضافية تتبناها كل شركة لخدمة عملائها مثل كتابة الشاشة LCD و قراءة أزرار Keypad و التعامل مع المنفذ التسلسلى أو I2C الخ. لذا فهى تختلف من مترجم لآخر و ليست من لغة لأخرى فقط. ولا حل أمامنا سوى ملفات المساعدة

المرة القادمة إن شاء الله نعيد البرنامج بالبيزك ثم إن شاء الله بعده بلغة C


ماجد عباس محمد
:: نائب المشرف العام
::
تاريخ التسجيل: Jun 2009
الدولة: القاهرة - مصر
المشاركات: 11,652
نشاط [ ماجد عباس محمد ]
قوة السمعة:
قديم 07-07-2018, 08:45 AM المشاركة 64   
افتراضي الغسالة باستخدام C51 و لغة البيزك




الغسالة باستخدام C51 و لغة البيزك:
من الأفضل أن نعيد هنا ذات الدائرة حتى نرجع إليها


كما فعلنا سابقا نشرح المطلوب.
نهيء المتحكم ونجهز المقاطعات ثم نفحص الأزرار و نضئ ألليد المناظر. إن كان زر التشغيل مع الباب مغلق إذن
لو دورة بارد ننتقل للتشغيل و إلا
نشغل السخان و إن كان مطلوب دافئ ننتظر حساس دافئ و إلا ننتظر الساخن
نحدد الزمن طبقا للدورة ثم نبدأ الفترة الأولى ثم نفتح الصرف و نغلقه و نعيد ملئ الخزان و نشغل دورة شطف ثم نكرر الشطف ثم أخيرا دورة عصر ثم توقف
بيزك باسكوم
و نبدأ بالبيزك ، باسكوم ثم سنستخدم ميكروإلكترونيكا لتبيان الفرق ثم C . عند بدء مشروع جديد سيفتح لك صفحة خالية و من القائمة Option\Compiler\chip تحدد اسم المتحكم و تردد الكريستال الخ. ثم تنقر زر Add Code ثم تعود للصفحة و إن شئت تكتب فى أول سطر تعليق أنها تعريفات Definition فلا بأس يلى ذلك التعريفات السابق استخدامها. بما أننا نستخدم ذات الدائرة فللتسهيل يمكنك نسخ الكود بالأسيمبلى كاملا من بروتس و لصقه هنا ثم من قائمة Edit اختار Replace أو انقر CTRL+R و اكتب فى الخانة الأولى كلمة EQU و فى التالى كلمة Alias واختار Replace all و بهذا انتهت أول خطوة
إن شئت يمكنك تجميع كل ثلاثة أوامر فى سطر واحد باستخدام ":” و إن شئت فلا ولكنى سأفعلها حتى لا تكون الصفحة طويلة خاصة فى المنتديات- لاحظ أن وجود كود الأسيمبلى لن يضير المترجم و ستصبح هكذا
التعريفات
كود:
' DEFINITIONS 
Leds Alias P0 : Relays Alias P1 : Switches Alias P2 : Controls Alias P3
Fullled Alias Leds.0 : Halfled Alias Leds.1 : Smallled Alias Leds.2
Hotled Alias Leds.3 : Mildled Alias Leds.4 : Coldled Alias Leds.5
Wateron Alias Relays.0 : Drainon Alias Relays.1 : Heateron Alias Relays.2
Motoron Alias Relays.3 : Run_nspin Alias Relays.4 : Waterfull Alias Relays.5
Waterempty Alias Relays.6 : Dooropen Alias Relays.7 : Midtemp Alias Switches.0
Hitemp Alias Switches.1 : Cold Alias Switches.2 : Mild Alias Switches.3
Hot Alias Switches.4 : Small Alias Switches.5 : Half Alias Switches.6
Full Alias Switches.7 : Run Alias Controls.1

' VARIABLES
Dim Runtime As Word
Jobpending Alias PSW.5

Emergency:
      Goto Begin
Counttime:
     Decr Runtime
     If Runtime = 0 Then
        Reset Jobpending
         Stop Timer0
     End If
     Return


هنا نلاحظ أننا وضعنا تعريفا بأن التالى متغيرات فقط لتذكيرك لكن المترجم لا يقرأه بل سيتعرف على ذلك من كلمة Dim السابق شرحها و نختار اسم Runtime وهو الزمن الإجمالى ثم As Word أى من صفر حتى 65535 و بذلك أكبر زمن هو 1092 دقيقة و نغير كلمة F0 بالمكافئ لها وهو PSW.5 لأن المترجم لا يعرفها وهذا قصور فيه ، ثم من شريط الأدوات ستجد زر عليه علامة صح فقط – انقر عليه سيتوقف على أول سطر org 0000h و ذلك لأنه لا يدعمها و نحن عادة لا نحتاجها إلا للمقاطعة وهذا المترجم يتعامل معها بطريقة خاصة فكما علمنا أن هذه المهام ليست من اللغات العالية ولكنها إضافات بحسب المترجم. حسنا احذف هذا السطر و التالى sjmp Start فلم نعد بحاجة إليه فهو سيتولى ذلك عنا.

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

ثم بعد ذلك سنجد عنوان INT0 (IE0)Emergency وهو خانة 3 فى الذاكرة ولكن المترجم سيتولى ذلك فكيف نعرفه ما نريد أى أن هذا الكود لمقاطعة و أيها هى؟
حسنا نضع عنوان فى أى مكان و ليكن Emergency: و نكتب تحته ما فعلناه فى البرنامج السابق و كان sjmp Start لكن بمجرد كتابة الكلمة Start ستظهر بجوار مؤشر الكتابة مربع به ثلاث خيارات للمؤقتات الثلاثة ، إذن كلمة Start من الكلمات المحجوزة لتشغيل و إيقاف المؤقتات و لن تصلح كعنوان فنستبدله بكلمة Begin و التى لا تسبب شيء فنضع بعدها مباشرة ":” لتصبح عنوان ولا تكتب شيء بعده على السطر . لاحظ أنك تفصل بين الأوامر بالحرف " : “ و الفارق هو مسافة قبله و بعده لذا لو وضعتها ستحصل على رسالة خطأ أن الأمر Emergency غير معروف فى السطر رقم كذا ، الآن sjmp Start ستصبح Goto Begin وهذا فقط ما يفعله لكن لم يعلم بعد أنه لمقاطعة
سنكتب عنوان جديد للمقاطعة الثانية الخاصة بالتايمر صفر وكان لحساب الزمن فكنا ننقص الثوانى و من ثم الدقائق فإن أصبحت صفرا نوقف العداد و ننزل العلم أى نصفر F0 و هنا دمجناهما معا فى متغير واحد اسمه Runtime و لذا ننقصه ثم نختبره بالأمر IF فإن تحقق نستخدم الأمر RESET لجعل أى بت = صفر أى أنه صالح لبت من منفذ أو من متغير بأى حجم و عكسها Set و تكتب RESET x حيث x اسم البت أو RESET y.x حيث y هو المتغير و x رقم البت فيه وبذلك جعلنا العلم = صفر و الأمر Stop Timer0 لإيقاف التايمر و أخيرا أمر العودة من المقاطعة Return و أيضا هذا هو كود المقاطعة لكنه لم يعلم بعد أنها كذلك
هنا ستسأل، لماذا لم تكتب فى الأولى أيضا Return ؟
معك حق لكنها لن تنفذ لأن قبلها أمر انتقال للبداية وهناك يجب أن نتأكد أن كل الأمور مهيأة على الوجه الكامل.
أرجو أن تمحو كل الأوامر بالأسيمبلى التى استبدلناها بالبيزك. ألآن سيكون لدينا البداية Begin و أول سطر كان
كود:
    MOV IE,#10000011b  ' Enable T0 & INT0 external 
                  MOV   TMOD,#00000110b			; T0 8bit counter auto reload  
لم نعد بحاجة إليه ولا للسطر الخاص TMOD   فسنستخدم  بدلا منهما الأمر 
CONFIG  TIMERx = COUNTER/TIMER , GATE=INTERNAL/EXTERNAL , MODE=0/3
CONFIG من ما سميناه المكتبات وهى بعضها داخلية أى فى بناء المترجم مثل هذا الأمر و بعضها مضاف أى مكتبة يضاف كود منها عند اللزوم و توجد فى مجلد خاص بالمترجم وكلاهما تجد شرحه فى ملفات المساعدة و بعضها مضافة من مصدر ثالث وهذا الأمر اختصار CONFIGure أى نسّق أو هيأ أو أضبط التالى على الصورة التالية ، ثم اسم المطلوب تهيئته وهو TIMER0
مجرد أن تكتب CONFIG ستظهر قائمة تختار منها بالأسهم أول بند هو TIMER0 ثم اضغط مسافة أو Enter أو إدخال فتضاف للكود ثم تكتب علامة = فيظهر خيارين COUNTER و TIMER و بالأسهم اختار COUNTER ثم مسافة أو Enter أو إدخال ثم تكتب فاصلة , فتظهر لك أربع خيارات MODE=x و تختار منها 2= MODE و اضغط مسافة و فاصلة لتختار بين INTERNAL/EXTERNAL و طبعا EXTERNAL لأنه سيعد نبضات من الخارج و بعد ذلك نضيف القيم 205 بالأمر = بدلا من الأمر mov ثم قيمة TCON لتجعل INT0 قدح بالحافة .
التهيئة تجهز العداد لكن يبقى متوقف لذا نكتب Enable فتفتح قائمة نختار آخرها كلمة Interrupts لإتاحة الكل ثم نكرر ونختار Int0 لإتاحة المقاطعة. الأمر MOV SP أيضا سيتولاه المترجم ولم نعد بحاجة إليه
هنا نلحظ فرق بين الأسيمبلى و اللغة العالية أننا فى الأسيمبلى بأمر واحد وضعنا فى IE إتاحة ما تشاء من المقاطعات بينمت هنا خطوة لكل شيء تتيحه. طبعا يمكنك استخدام الأمر IE=xx كما سبق لكن ستشرح ما هو المتاح و الغير متاح لتتذكره لاحقا مقابل الاختصار. المترجم الذكى يدرك سلسلة الأوامر المتتالية للإتاحة و يجمعها فى أمر واحد أيضا.
كود:
Begin:
	Config Timer0 = Counter , Mode = 2 , Gate = Exteral	   	
	TH0 = 205			; Auto reload
    	TL0 =  205	
	TCON = 1			; Clr All interrupts, Set INT0 Edge trigger
	Enable Interrupts
    	Enable Int0
    	Leds  = 11011011b                      ' Reset All PORTS! select Small cold cycle
    	Relays  = 255
   	Switches  = 255
  	Controls  = 255	
             On Int0 Emergency , Nosave
             On Timer0 CountTime 
	Bitwait Run , Set                                         ' Run button release
LoopAgain:
ثم تحدد القيم الابتدائية للمنافذ عند بدء التشغيل بالأوامر الأربعة التالية وسطر انتظار زرار Run عند الطوارئ و استخدمنا لهاjnb RUN,$ وهى سنستبدلها بالأمر BitWait أى انتظر البت ثم الاسم و القيمة Set تعنى 1 وهذا يعنى انتظر البت اسمها RUN حتى تصبح 1 ثم اكمل. و أخيرا السطرين
On Int0 Emergency , Nosave
On Timer0 CountTime
والأول يعنى "عند حدوث مقاطعة من" Int0 انتقل للعنوان Emergency ولا تحفظ أى من قيم المسجلات فى الرصة
و الثانى يعنى "عند حدوث مقاطعة من" Timer0 انتقل للعنوان CountTime مع حفظ أى من قيم المسجلات فى الرصة
القيمة الفرضية عندما لا تكتب كلمة "Nosave” أن يحفظ البرنامج المسجلات التى تستخدم فى خطوات برنامج خدمة المقاطعة وهو أسلم بالطبع وبهاتين الخطوتين عرفنا المتحكم ماذا يفعل عند كل مقاطعة . و أخيرا كلمة Loop من كلمات اللغة لذا نستبدلها بكلمة LoopAgain و هكذا انهينا ألتهيئة ولو راجعتها الآن ستجدها أسهل من الأسيمبلى فأمر يغنيك عن كثير لكن أحيانا تجد أنك أقل حرية من الأسيمبلى. المرة القادمة إن شاء الله نكتب باقى البرنامج.


التعديل الأخير تم بواسطة : ماجد عباس محمد بتاريخ 07-07-2018 الساعة 09:02 AM


الساعة معتمدة بتوقيت جرينتش +3 الساعة الآن: 04:29 PM
موقع القرية الالكترونية غير مسؤول عن أي اتفاق تجاري أو تعاوني بين الأعضاء
فعلى كل شخص تحمل مسئولية نفسه إتجاه مايقوم به من بيع وشراء وإتفاق وأعطاء معلومات موقعه
التعليقات المنشورة لا تعبر عن رأي موقع القرية الالكترونية ولايتحمل الموقع أي مسؤولية قانونية حيال ذلك (ويتحمل كاتبها مسؤولية النشر)