منتديات الالكترونيات العصرية  
yoursite.com page title .

استرجاع كلمة المرور طلب كود تفعيل العضوية تفعيل العضوية
العودة   منتديات الالكترونيات العصرية > منتدى الحاكمات الدقيقة Microcontroller > منتدى المتحكمات ميكرو بلغة الاسمبلي

  #31  
قديم 07-02-2018, 08:51 AM
ماجد عباس محمد ماجد عباس محمد غير متواجد حالياً
استاذ
ومشرف الكترونيات
 
تاريخ التسجيل: Jun 2011
الدولة: القاهرة - مصر
المشاركات: 1,395
معدل تقييم المستوى: 26
ماجد عباس محمد has a brilliant futureماجد عباس محمد has a brilliant futureماجد عباس محمد has a brilliant futureماجد عباس محمد has a brilliant futureماجد عباس محمد has a brilliant futureماجد عباس محمد has a brilliant futureماجد عباس محمد has a brilliant futureماجد عباس محمد has a brilliant futureماجد عباس محمد has a brilliant futureماجد عباس محمد has a brilliant futureماجد عباس محمد has a brilliant future
افتراضي اعتبارات عملية فى تنفيذ مثل هذه ألبوردات

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

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

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

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

قبل البدء قى تحويل البرنامج باللغات العالية سنبدأ فى المرة القادمة فهم ما هى اللغات العالية وهو موضوعنا القادم إن شاء الله
الصور المرفقة
نوع الملف: jpg LineFilter.jpg‏ (17.8 كيلوبايت, المشاهدات 12)
نوع الملف: jpg PCB Wireing.jpg‏ (18.3 كيلوبايت, المشاهدات 13)
رد مع اقتباس
  #32  
قديم 07-03-2018, 09:45 AM
ماجد عباس محمد ماجد عباس محمد غير متواجد حالياً
استاذ
ومشرف الكترونيات
 
تاريخ التسجيل: Jun 2011
الدولة: القاهرة - مصر
المشاركات: 1,395
معدل تقييم المستوى: 26
ماجد عباس محمد has a brilliant futureماجد عباس محمد has a brilliant futureماجد عباس محمد has a brilliant futureماجد عباس محمد has a brilliant futureماجد عباس محمد has a brilliant futureماجد عباس محمد has a brilliant futureماجد عباس محمد has a brilliant futureماجد عباس محمد has a brilliant futureماجد عباس محمد has a brilliant futureماجد عباس محمد has a brilliant futureماجد عباس محمد has a brilliant future
افتراضي هيكل اللغات العالية و تكونها

هيكل اللغات العالية و مم تتكون:
اللغات العالية تشترك فى مجموعة من الصفات مع اختلافات فى نص كتابتها و قد تتعجب أنها تتكون من 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

المرة القادمة إن شاء الله نتكلم عن الأوامر أو الأكواد التى تستخدم لبناء البرنامج
رد مع اقتباس
  #33  
قديم 07-04-2018, 09:56 AM
ماجد عباس محمد ماجد عباس محمد غير متواجد حالياً
استاذ
ومشرف الكترونيات
 
تاريخ التسجيل: Jun 2011
الدولة: القاهرة - مصر
المشاركات: 1,395
معدل تقييم المستوى: 26
ماجد عباس محمد has a brilliant futureماجد عباس محمد has a brilliant futureماجد عباس محمد has a brilliant futureماجد عباس محمد has a brilliant futureماجد عباس محمد has a brilliant futureماجد عباس محمد has a brilliant futureماجد عباس محمد has a brilliant futureماجد عباس محمد has a brilliant futureماجد عباس محمد has a brilliant futureماجد عباس محمد has a brilliant futureماجد عباس محمد has a brilliant future
افتراضي الأكواد العشرة

الأكواد العشرة
تنقسم الأكواد العشر لثلاث مجموعات هى الشروط و الدورات و الانتقال
الشروط:
الأمر 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 بدلا منها !!!!! أو تفضل البيزك مثلى
المرة القادمة إن شاء الله ندرس الدورات
رد مع اقتباس
  #34  
قديم 07-05-2018, 08:41 AM
ماجد عباس محمد ماجد عباس محمد غير متواجد حالياً
استاذ
ومشرف الكترونيات
 
تاريخ التسجيل: Jun 2011
الدولة: القاهرة - مصر
المشاركات: 1,395
معدل تقييم المستوى: 26
ماجد عباس محمد has a brilliant futureماجد عباس محمد has a brilliant futureماجد عباس محمد has a brilliant futureماجد عباس محمد has a brilliant futureماجد عباس محمد has a brilliant futureماجد عباس محمد has a brilliant futureماجد عباس محمد has a brilliant futureماجد عباس محمد has a brilliant futureماجد عباس محمد has a brilliant futureماجد عباس محمد has a brilliant futureماجد عباس محمد has a brilliant future
افتراضي الدورات Iteration

الدورات 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++;
 }
المرة القادمة إن شاء الله نتحدث عن المجموعة الأخيرة وهى الانتقال أو التفرع
رد مع اقتباس
  #35  
قديم 07-06-2018, 08:46 AM
ماجد عباس محمد ماجد عباس محمد غير متواجد حالياً
استاذ
ومشرف الكترونيات
 
تاريخ التسجيل: Jun 2011
الدولة: القاهرة - مصر
المشاركات: 1,395
معدل تقييم المستوى: 26
ماجد عباس محمد has a brilliant futureماجد عباس محمد has a brilliant futureماجد عباس محمد has a brilliant futureماجد عباس محمد has a brilliant futureماجد عباس محمد has a brilliant futureماجد عباس محمد has a brilliant futureماجد عباس محمد has a brilliant futureماجد عباس محمد has a brilliant futureماجد عباس محمد has a brilliant futureماجد عباس محمد has a brilliant futureماجد عباس محمد has a brilliant future
افتراضي الانتقال أو التفرع 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
رد مع اقتباس
  #36  
قديم 07-07-2018, 09:19 AM
ماجد عباس محمد ماجد عباس محمد غير متواجد حالياً
استاذ
ومشرف الكترونيات
 
تاريخ التسجيل: Jun 2011
الدولة: القاهرة - مصر
المشاركات: 1,395
معدل تقييم المستوى: 26
ماجد عباس محمد has a brilliant futureماجد عباس محمد has a brilliant futureماجد عباس محمد has a brilliant futureماجد عباس محمد has a brilliant futureماجد عباس محمد has a brilliant futureماجد عباس محمد has a brilliant futureماجد عباس محمد has a brilliant futureماجد عباس محمد has a brilliant futureماجد عباس محمد has a brilliant futureماجد عباس محمد has a brilliant futureماجد عباس محمد has a brilliant future
افتراضي الغسالة باستخدام 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 و هكذا انهينا ألتهيئة ولو راجعتها الآن ستجدها أسهل من الأسيمبلى فأمر يغنيك عن كثير لكن أحيانا تجد أنك أقل حرية من الأسيمبلى. المرة القادمة إن شاء الله نكتب باقى البرنامج.
رد مع اقتباس
  #37  
قديم 07-08-2018, 10:27 AM
ماجد عباس محمد ماجد عباس محمد غير متواجد حالياً
استاذ
ومشرف الكترونيات
 
تاريخ التسجيل: Jun 2011
الدولة: القاهرة - مصر
المشاركات: 1,395
معدل تقييم المستوى: 26
ماجد عباس محمد has a brilliant futureماجد عباس محمد has a brilliant futureماجد عباس محمد has a brilliant futureماجد عباس محمد has a brilliant futureماجد عباس محمد has a brilliant futureماجد عباس محمد has a brilliant futureماجد عباس محمد has a brilliant futureماجد عباس محمد has a brilliant futureماجد عباس محمد has a brilliant futureماجد عباس محمد has a brilliant futureماجد عباس محمد has a brilliant future
افتراضي أول البرنامج

أول البرنامج
بعد التهيئة السابقة وصلنا لأول البرنامج حيث العنوان التكرارىLoopAgain بعد ذلك الاختبار If Full = 0 Then أى لو زرار Full مضغوط إذن نفعل السابق وهو ORL ثم LEDs,#00000111b ، الوظيفة "أو" OR وهى بالأسيمبلى ORL وفى البيزك OR لأنه هنا لا يعتمد النوع الآخر Boolean من OR و تتحول الوظيفة لهذه الصيغة Leds = Leds Or &B00000111
أى أن اجعل LEDs تساوى = LEDs OR 00000111 و هنا الرمز &B ليعنى أن الرقم بالنظام ألثنائى Binary
قبل أن نترك هذه الخطوة نعلم أن هناك أربعة وظائف هى OR,AND,NOT, EXOR وهى أو – مع – عاكس – أو المطلقة وهى كما هى هكذا لا تحتاج لتفكير ولا تذكر ولا تستخدم رموز أو إشارات – لغة انجليزية بسيطة و مفهومة
كان من الممكن أن نكمل بطريقتين، الأولى

كود:
  If Full=0 Then
  	Leds = Leds Or &B00000111 : Reset FulLed  
  End if
If  Half = 0 Then
              Leds = Leds Or &B00000111 : Reset HalfLed
End If
if Small = 0 Then
            Leds = Leds Or &B00000111 : Reset SmallLed
 End If
لكن كما ذكرنا أن الاختبار الأول لو نجح فمضيعة للوقت إجراء الثانى و الثالث لذلك فاستخدام الطريقة الثانية Elseif يجعل الاختبار الأول عند نجاحه سنخرج من المجموعة الأولى ذات الخيارات المتبادلة أى لا يمكن أن يختار 2 منها معا ، واحد وواحد فقط فى كل مرة ، و نفس الشيء فى المجموعة الثانية واحد من ثلاث فقط لذا سنكرر الهيكلية معهم
البرنامج أصبح

كود:
 LoopAgain:	
    
    If Full = 0 Then
         Leds = Leds Or &B00000111 : Reset FulLed
         Elseif Half = 0 Then
              Leds = Leds Or &B00000111 : Reset HalfLed
         Elseif Small = 0 Then
            Leds = Leds Or &B00000111 : Reset SmallLed
      End If

      If Hot = 0 Then
         Leds = Leds Or &B00111000 : Reset Hotled
         Elseif Mild = 0 Then
              Leds = Leds Or &B00111000 : Reset Mildled
         Elseif Cold = 0 Then
              Leds = Leds Or &B00111000 : Reset Coldled
         End If

        If Run = 1 Then Goto Loop                        ' Wait Run Press
        Bitwait	 Dooropen , Reset                       ' Wait Door to close
        Reset	 Wateron                                     ' Fill with water
        Bitwait 	Waterfull , Reset                        ' Wait full Tank
        Set 	Wateron                                      ' Close water Valve
أصبح استبدال أوامر الأسيمبلى بالبيزك تكراريا و مفهوما
فى الأمر التالى استخدمنا فى الأسيمبلى الأمر
JNB ColdLED,SetCycle ; Cold cycle No Heat needed
لنختبر إذا زرار البارد قد اختير ننتقل و إلا نشغل السخان و تترجم
كود:
	 If Coldled = 1 Then Reset Heateron                           ' No Cold then Heater On
ثم نختبر إذا زرار الوسط قد اختير ننتقل لنرقب حساس الدافئ و إلا نرقب حساس الحار

كود:
	JNB	MildLED,HOTTemp
		jb	HiTemp,$	; wait mild sensor
		sjmp	SetCycle	
HOTTemp:	
	jb	MidTemp,$		; wait HOT sensor
 و تترجم هكذا
  If Coldled = 1 Then                                          ' not Cold then
         Reset    Heateron                                         ' Heater on
              If Mildled = 0 Then Bitwait Midtemp , Reset Else Bitwait Hitemp , Reset
         Set Heateron                                          ' Turn off heater
 End If                                                                 ' Now Start Washing
تذكر أن تعليمه If فى سطر واحد لا تحتاج End If فى آخره، ثم يلى ذلك نفس الهيكلية لاختيار زمن التشغيل نختبر ليد Full أو حمولة كاملة أو small أى حمولة صغيرة ونحدد الزمن هكذا
كود:
SetCycle:				; Now Start Washing
	JNB	FullLED,HalfCycle
	MOV	Minutes,#20
	sjmp	RunMotor
HalfCycle:	JNB	HalfLED,SmallCycle
		MOV	Minutes,#8
    sjmp	RunMotor
SmallCycle:
	MOV	Minutes,#5
RunMotor:
	
و تترجم هكذا
 If   Fullled  =  0    Then
     	  Runtime  =  20 * 60
     Elseif Halfled  =  0     Then
   	  Runtime  =  480
     Else
               Runtime  =  300
   End If
تعمدت أن اذكرك أننا سنكتب عدد الثوانى مرة واحدة و يمكنك كتابته بصورة رياضية للتذكر و سيحلها المترجم قبل التكويد أى الترجمة أى لن تضيف للناتج أى خطوات فبالنسبة للمترجم 20*60 هى ذاتها 1200 و بهذا لسنا فى حاجة لوضع 59 ثانية. الآن نشغل الموتور دورة الغسيل

باقى الدورات موضوعنا القادم بإذن الله
رد مع اقتباس
  #38  
قديم 07-09-2018, 09:43 AM
ماجد عباس محمد ماجد عباس محمد غير متواجد حالياً
استاذ
ومشرف الكترونيات
 
تاريخ التسجيل: Jun 2011
الدولة: القاهرة - مصر
المشاركات: 1,395
معدل تقييم المستوى: 26
ماجد عباس محمد has a brilliant futureماجد عباس محمد has a brilliant futureماجد عباس محمد has a brilliant futureماجد عباس محمد has a brilliant futureماجد عباس محمد has a brilliant futureماجد عباس محمد has a brilliant futureماجد عباس محمد has a brilliant futureماجد عباس محمد has a brilliant futureماجد عباس محمد has a brilliant futureماجد عباس محمد has a brilliant futureماجد عباس محمد has a brilliant future
افتراضي باقى الدورات

باقى الدورات
ألان ندير الموتور الفترة الزمنية المحددة ، ولكى نعرف الزمن يجب أن نقيم JobPending أى نجعله = 1 و ندير الموتور و ننتظر JobPending أن يحدد نهاية المدة و كانت هكذا

كود:
RunMotor:
	MOV		Seconds,#59
	SETB	JobPending
	CLR		MotorOn
	SETB	TR0			; Start Timer/Counter
		JB	JobPending,$	          ; Wait to Finish
	SETB	MotorON		; stop motor
لا خانة للثوانى الآن فلا تترجم والعنوانRunmotor لا حاجة له ثم جعل دليل الوقت Jobpending=1 ثم تشغيل الموتور و انتظار نهاية الوقت ثم إيقاف الموتور .

كود:
    Set          Jobpending                                        ' Timing flag
    Reset      Motoron                                             ' Start Motor
    Start      Timer0                                                ' Start Timer/Counter
    Bitwait  Jobpending , Reset                             ' Wait to Finish
    Set          Motoron
ألان نحتاج لدورتين للشطف و من المتوقع أن يكونا متطابقتين، لذا لونت إحداهما بلون مختلف ليمكنك متابعة خطوة بمثيلتها للتحقق من ذلك. فتح الصرف و انتظار حساس " فارغ" ثم غلق الصرف ثم فتح المياه و انتظار تمام ألملو ثم تشغيل الموتور و انتظار الوقت ثم إيقاف الموتور . حسنا هل كان من الممكن كتابة كود واحد و تكراره مرتين، نعم فقط سنضيف فى قسم التعريف بالأعلى التعريف Rinse Equ 20 أى أن متغيرا باسم Rinse فى خانة الذاكرة رقم 20 (أو أى خانى فارغة تريد) و هذا يتيح لنا أن نأتى فى أول الدورة و نكتب ما يلى بالأسيمبلى

كود:
	CLR	DrainON			; Open Drain
	JB	WaterEmpty,$			;Wait Drain
	Setb	DrainON			; Close Drain
	CLR	WaterON			; Fill again
	JB	WaterFull,$
	SETB	WaterON			; Close Water
	MOV	Minutes,#5			; 1St Rinse
	MOV	Seconds,#59
	SETB	JobPending
	CLR	MotorOn			; Start Rinse
	SETB	TR0				; Start Timer
	JB	JobPending,$			; Wait to Finish
	Setb	MotorOn			; Stop Rinse

	CLR	DrainON			; Open Drain second cycle
	JB	WaterEmpty,$			;Wait Drain
	Setb	DrainON			; Close Drain	
	CLR	WaterON			; Fill again
	JB	WaterFull,$
	SETB	WaterON			; Close Water
	MOV	Minutes,#5			; 2nd Rinse
	MOV	Seconds,#59
	SETB	JobPending
	SETB	TR0				; Start Timer/Counter
	CLR	MotorOn			; Start Rinse
	SETB	TR0				; Start Timer
	JB	JobPending,$			; Wait to Finish
	Setb	MotorOn			; Stop Rinse	
هكذا نستخدم نظام الدورات لاحظ أن السطر الأول تمهيدى و قد أضيف لتحديد عدد الدورات بدورتين . أيضا السطر الأخير تكملة له أما باقى التعليمات فهى ملونة لتقارنها بالملون السابق و ستجدها نسخة مكررة.

كود:
	Mov	Rinse,#2
RinseLoop:
	CLR	DrainON			; Open Drain
	JB	WaterEmpty,$			;Wait Drain
	Setb	DrainON			; Close Drain
	CLR	WaterON			; Fill again
	JB	WaterFull,$
	SETB	WaterON			; Close Water
	MOV	Minutes,#5			; 1St Rinse
	MOV	Seconds,#59
	SETB	JobPending
	CLR	MotorOn			; Start Rinse
	SETB	TR0				; Start Timer
	JB	JobPending,$			; Wait to Finish
	Setb	MotorOn			; Stop Rinse
	Djnz	Rinse, RinseLoop
وهكذا نوفر كتابة الكود مرتين و نضيف فقط زمن الاختبار و الانتقال وهذا مثال آخر للكود الأقصر طولا و أطول زمنا لكن له ميزة أخرى لا تقدر وهى أننا لو أردنا تغيير عدد دورات الشطف فكل ما نحتاجه هو أن نضع قيمة مختلفه (من المستخدم عبر لوحة مفاتيح مثلا) فى الخانة المسماة Rinse أو ذاكرة رقم 20 وهو سيكررها بالعدد آليا بدلا من تكرار الكود عدة مرات مستهلكا كم أكبر من ذاكرة البرنامج.
ألان نترجم هذا بلغة البيزك نضيف فى التعريفات Dim Rinse As Byte , cntr as byte و هنا تترجم التعليمات هكذا .

كود:
   For cntr = 1 To  Rinse
       Reset 	Drainon                                          	' Open Drain
       Bitwait 	Waterempty , Reset                             	' Wait Drain
       Set 	Drainon                                           	' Close Drain
       Reset 	Wateron                                          	' Fill again
       Bitwait 	Waterfull , Reset
       Set 	Wateron                                            	' Close Water
       Runtime = 300                                          		'  Rinse  Time
       Set 	Jobpending
       Reset 	Motoron                                         	 ' Start Rinse
       Start 	Timer0                                           	' Start Timer
       Bitwait 	Jobpending , Reset                            	 ' Wait to Finish
       Set 	Motoron                                            	' Stop Rinse	
    Next							' Loop Back
الخطأ هنا أننا لم نضع قيمة فى المتغير Rinse لذا يجب أن نكتب فى التهيئة مثلا Rinse=2 أو لاحقا يمكنك تطوير البرنامج ليعدل مرات الشطف حسب كمية الغسيل أو باختيار المستخدم من لوحة مفاتيح الخ. فهذا تعليمى على أى حال. الباقى هو دورة العصر وهى لا تختلف إلا فى تفعيل ريلاى العصر لدوران الموتور بسرعة عالية

كود:
CLR	DrainON			; Open Drain 
	JB	WaterEmpty,$	;Wait Drain
	MOV	Minutes,#3			; SPIN
	MOV	Seconds,#59
	SETB	JobPending
	CLR	MotorOn			; Start Rinse
	CLR	Run_Nspin			; SPIN
	SETB	TR0				; Start Timer/Counter
		JB	JobPending,$		; Wait to Finish
	MOV	Relays,#255			; ALL OFF, INITIAL State
	MOV	Controls,#255	
	jmp Loop
;====================================
      END
وتترجم هكذا
	 Reset 	 Drainon                                                ' Open Drain second cycle
              Bitwait Waterempty , Reset                            ' Wait Drain
 	 Runtime = 180                                                  ' SPIN
 	Set         Jobpending
 	Reset 	 Motoron                                                ' Start Rinse
 	Reset 	 Run_nspin                                             ' SPIN
 	Start 	 Timer0                                                  ' Start Timer/Counter
   	Bitwait Jobpending , Reset                                ' Wait to Finish
  	Relays = 255                                                        ' ALL OFF, INITIAL State
	 Controls = 255
 	Goto Loopِagain
لو استخدمتGoto Begin يمكنك الاستغناء عن الأمرين السابقين لها أيضا للتكرار . المرة القادمة إن شاء الله سنستخدم بيزك ميكروإلكترونيكا و بعدها C من ميكروإلكترونيكا
رد مع اقتباس
  #39  
قديم 07-10-2018, 10:14 AM
ماجد عباس محمد ماجد عباس محمد غير متواجد حالياً
استاذ
ومشرف الكترونيات
 
تاريخ التسجيل: Jun 2011
الدولة: القاهرة - مصر
المشاركات: 1,395
معدل تقييم المستوى: 26
ماجد عباس محمد has a brilliant futureماجد عباس محمد has a brilliant futureماجد عباس محمد has a brilliant futureماجد عباس محمد has a brilliant futureماجد عباس محمد has a brilliant futureماجد عباس محمد has a brilliant futureماجد عباس محمد has a brilliant futureماجد عباس محمد has a brilliant futureماجد عباس محمد has a brilliant futureماجد عباس محمد has a brilliant futureماجد عباس محمد has a brilliant future
افتراضي البرنامج بمترجم بيزك من ميكروإلكترونيكا

البرنامج بمترجم بيزك من ميكروإلكترونيكا
ها هو البرنامج كاملا لمترجم باسكوم و سنعدل ما نحتاج فقط

كود:
' 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
Dim Rinse As Byte , cntr as byte

Emergency:
      Goto Begin
Counttime:
     Decr Runtime
     If Runtime = 0 Then
        Reset Jobpending
         Stop Timer0
     End If
     Return
نظرا لعدم قبوله أكثر من أمر لكل سطر فسنضطر إلى التعريف هكذا
program WM
' Declarations section
symbol FullLED = LEDs.0
symbol HalfLED = LEDS.1
symbol SmallLED = LEDs.2 
symbol HOTLED = LEDs.3
symbol MildLED = LEDs.4
symbol ColdLED = LEDs.5 
symbol WaterOn = Relays.0
symbol DrainOn = Relays.1
symbol HeaterOn = Relays.2 
symbol MotorOn = Relays.3
symbol Run_Nspin = Relays.4
symbol WaterFull = Relays.5 
symbol WaterEmpty = Relays.6 
symbol DoorOpen = Relays.7
symbol MidTemp = Switches.0 
symbol HiTemp = Switches.1
symbol Cold = Switches.2
symbol Mild = Switches.3 
symbol Hot = Switches.4
symbol SmallLoad = Switches.5
symbol Half = Switches.6 
symbol Full = Switches.7 
symbol RUN = Controls.1
Dim Leds as byte at P0
dim Relays as byte at  P1
Dim Switches  as byte at P2
Dim Controls  as byte at  P3 

Dim JobPending as sbit at PSW.F0 
dim RunTime as word 
dim Rinse as byte
dim cntr as byte
sub procedure INT0_Interrupt() org IVT_ADDR_EX0
  asm
     sjmp 0
  end asm
end sub

sub procedure Timer0_Interrupt() org IVT_ADDR_ET0
    Dec (RunTime)
    If RunTime = 0 then 
       JobPending = 0 
       TR0_bit = 0       ' Stop Timer1
    end if
end sub
السطر الأول اسم البرنامج ثم التعريفات كما سبق الشرح و لكن هذا المترجم يتطلب إعلان الاسم بكلمه DIM قبل استخدامه أى Symbol لا تجدى فى تعريف ما يلى كما فى باسكوم لذا سنعرف المنافذ كلها
للمقاطعة يستخدم هذا المترجم تعريف مختلف
sub procedure INT0_Interrupt() org IVT_ADDR_EX0
حيث Sub كلمة يستخدمها دوما كما فى فكر لغة C وهى زائدة كما بينا فى باسكوم فهو يتبعها بكلمة procedure أو كلمة Function وواحدة تغنى ثم اسم المقاطعة وهو هنا INT0_Interrupt() ثم كلمة org أو IV لتخبره أنها مقاطعة Interrupt Vector و أخيرا العنوان IVT_ADDR_EX0
فى المقاطعة الخاصة بالطوارئ كنا سنستخدم انتقال للبداية GOTO Begin لكنها لا تقبل رقم و تطلب عنوان "سبق تعريفه" لذا إما ننقل كل الكود لآخر البرنامج أو لنتحايل و نبقى على التتابع استخدمنا الأسيمبلى بالتعريف asm ثم القفز ثم end asm. المقاطعة الثانية نستخدم نفس الأوامر.
يلى ذلك أوامر التهيئة ما بين Begin , LoopAgain
كود:
Begin:
    Config Timer0 = Counter , Mode = 2 , Gate = Exteral
    Th0 = 205                                                 ' Auto reload
    Tl0 = 205
    Tcon = 1
    Enable Interrupts
    Enable Int0
    Leds = &B11011011                                         ' Reset All PORTS! select Small cold cycle
    Relays = 255
    Switches = 255
    Controls = 255
    Rinse = 2
    On Int0 Emergency , Nosave
    On Timer0 Counttime
الأسطر الحمراء لا يدعمها هذا المترجم ولذلك سنضطر لتهيئة التايمر يدويا كما سبق فى الأسيمبلى كما أن نتيح المقاطعة و نبدأ و نوقف العداد بالأمر النصى بدلا من Enable فتصبح
     IE=%10000011 		' Enable T0 & INT0 external
     TH0 = 205     		' Auto reload
     TL0 = 205     		' Start Value
     TMOD = %00000110
     TCON = 1    		' Clear All interrupts, Set INT0 Edge trigger
     SP = 70    			' Move stack away
     Leds = %11011011   	' Reset All PORTS! select Small cold cycle
     Relays = 255
     Switches = 255
     Controls = 255
     Rinse = 2
الآن أول أمر كان انتظار عودة زر RUN لحالة عدم الضغط و لكن الأسف الأمر Bitwait غير مدعوم ولا بديل له فالمكتبة تتيح أمر sub function Button(dim time_ms as byte, dim active_state as byte) as byte حيث يجب أن تعرف قبل استخدامه متغير باسم Button_PIN ثم تحدد الزمن و تحدد 1 أم صفر فتعيد لك 255 لو حدث أو صفر لو لم يحدث و من ملف المساعدة نجد أنها تختبر الطرف ثم بعد الزمن تعيد اختباره وهذا يحتاج لمكافئ بالأسيمبلى كبير لا حاجة له فضلا عن أننا يجب أن نعيد التعريف عند كل تغيير للطرف وهذا عبئ لا معنى له ، لذا سنستغل الكود ألعادى Do loop
الشرط لو Full=0 سيتطلب الأمرين التاليين و نظرا لحدود المترجم سنحتاج سطرين منفصلين الأول كالسابق مع تغيير &B واستخدام الحرف % ثم السطر الثانى لا يدعم المترجم الأمر Reset و لكنه يوفر أمر SetBit(P0, 2) ' Set P0.2 و الأمر ClearBit(P0, 7) ' Clear P0.7 والمشكلة هنا أنهما لا يقبلا سوى الأمر الصريح كما بالمثالين السابقين أى لا نستطيع الاستفادة بالتسميات ولو أردنا التعديل لاحقا سنفحص كل سطر بحثا عنها لذا سنستخدم الأمر الصريح أيضا .
أيضا يجب ملاحظة أن هذا المترجم لا يدعم الأمر Elseif لذا يجب أن نكتب Else و فى داخلها نضع If جديدة لها Else وهكذا و نضع End If بعدد If المستخدمة عكس باسكوم End If واحدة للدورة كلها مما يجعل باسكوم أكثر وضوحا.
الكود يصبح

كود:
    do				' Wait Run =1 unpressed
    loop until  Run = 1                 '  Run button release
Loopagain:
    If Full = 0 Then
         Leds = Leds Or %00000111
         FullLED = 0
    Else
         if Half = 0 Then
            Leds = Leds Or %00000111 
            Halfled = 0
         Else
           if SmallLoad = 0 Then
              Leds = Leds Or %00000111
              Smallled = 0
           end if
         end if
    End If

    If Hot = 0 Then
       Leds = Leds Or %00111000 
       Hotled  = 0
    Else
       if Mild = 0 Then
          Leds = Leds Or %00111000
          Mildled = 0
       Else
          if Cold = 0 Then
             Leds = Leds Or %00111000 
             Coldled = 0
          end if
       end if
    End If
 If Run = 1 Then Goto LoopAgain                                    ' Wait Run Press
أخيرا سنجد أمر If Run = 1 Then Goto LoopAgain وسيخطر على بالك أنه من الممكن استبداله مع العنوان LoopAgain بدورة DO Loop until أو دورة While-WEND ، وهو ممكن فى الأمثلة السابقة لكن لم أريد تعقيد الأمور حتى لا تتساءل كيف فكر فى هذا ، ربما الأمر يصعب على الاستمرار فيه، المسألة ببساطة كلما وجدت وسيلة لاختصار بعض الخطوات فلم لا ، لكن الأفضل أن تبدأ بالبسيط السهل المتيسر تتبع أخطاؤه ثم بعد التأكد من نجاحه ، اختصر شيء و جرب فعندها ستحصر الخطأ فيما غيرت ولا بأس من حفظ القديم كاملا مادام قد نجح حتى يسهل عليك العودة له دوما.
كود:
    do
    loop until  Run = 1          '  Run button release
  do
    If Full = 0 Then
         Leds = Leds Or %00000111
         FullLED = 0
    Else
         if Half = 0 Then
            Leds = Leds Or %00000111 
            Halfled = 0
         Else
           if SmallLoad = 0 Then
              Leds = Leds Or %00000111
              Smallled = 0
           end if
         end if
    End If

    If Hot = 0 Then
       Leds = Leds Or %00111000 
       Hotled  = 0
    Else
       if Mild = 0 Then
          Leds = Leds Or %00111000
          Mildled = 0
       Else
          if Cold = 0 Then
             Leds = Leds Or %00111000 
             Coldled = 0
          end if
       end if
    End If
   loop until RUN =0
بعد ذلك غلق الباب و تحديد الفترة الزمنية حسب الخيارات و هذا موضوعنا القادم بإذن الله
رد مع اقتباس
  #40  
قديم 07-11-2018, 09:23 AM
ماجد عباس محمد ماجد عباس محمد غير متواجد حالياً
استاذ
ومشرف الكترونيات
 
تاريخ التسجيل: Jun 2011
الدولة: القاهرة - مصر
المشاركات: 1,395
معدل تقييم المستوى: 26
ماجد عباس محمد has a brilliant futureماجد عباس محمد has a brilliant futureماجد عباس محمد has a brilliant futureماجد عباس محمد has a brilliant futureماجد عباس محمد has a brilliant futureماجد عباس محمد has a brilliant futureماجد عباس محمد has a brilliant futureماجد عباس محمد has a brilliant futureماجد عباس محمد has a brilliant futureماجد عباس محمد has a brilliant futureماجد عباس محمد has a brilliant future
افتراضي رد: الميكرو كونترولر انواعه و برمجته و استخداماته

تكملة البرنامج

بعد ذلك غلق الباب و تحديد الفترة الزمنية حسب الخيارات و كانت
كود:
Bitwait Dooropen , Reset                                ' Wait Door to close
 Reset Wateron                                                ' Fill with water
 Bitwait Waterfull , Reset                               ' Wait full Tank
 Set Wateron                                                   ' Close water Valve

 If Coldled = 1 Then                                          ' not Cold then
    Reset Heateron                                            ' Heater on
    If Mildled = 0 Then Bitwait Midtemp , Reset Else Bitwait Hitemp , Reset
    Set Heateron                                              ' Turn off heater
 End If                                                       ' Now Start Washing

 If Fullled = 0 Then
     Runtime = 20 * 60
   Elseif Halfled = 0 Then
     Runtime = 480
   Else
     Runtime = 300
 End If

و كما سبق التعديل ستصبح بعد استبدال Waitbit و Elseif
   do                                                               ' Wait Door to close
   loop until Dooropen = 1
   Wateron  = 0                                              ' Fill with water
   do 
   loop until Waterfull = 1                             ' Wait full Tank
   Wateron = 1                                               ' Close water Valve

  If Coldled = 1 Then                                      ' not Cold then
     Heateron = 0                                              ' Heater on
     If Mildled = 0 Then
         do
         loop until Midtemp = 0
     Else
         do
         loop until Hitemp = 0
     end if
     Heateron =  1                                             ' Turn off heater
  End If                                                            ' Now Start Washing

  If Fullled = 0 Then
      Runtime = 20 * 60
  Else 
     if Halfled = 0 Then
         Runtime = 480
     Else
         Runtime = 300
     end if
  End If
'  Runmotor:
ثم تشغيل الموتور دورة غسيل ثم شطف و عصر و كانت
كود:
Runmotor:
    Set Jobpending                                            ' Timing flag
    Reset Motoron                                             ' Start Motor
    Start Timer0                                              ' Start Timer/Counter
    Bitwait Jobpending , Reset                                ' Wait to Finish
    Set Motoron                                               ' stop motor
    For cntr = 1 To rinse
       Reset Drainon                                          ' Open Drain
       Bitwait Waterempty , Reset                             ' Wait Drain
       Set Drainon                                            ' Close Drain
       Reset Wateron                                          ' Fill again
       Bitwait Waterfull , Reset
       Set Wateron                                            ' Close Water
       Runtime = 300                                          ' 1St Rinse
       Set Jobpending
       Reset Motoron                                          ' Start Rinse
       Start Timer0                                           ' Start Timer
       Bitwait Jobpending , Reset                             ' Wait to Finish
       Set Motoron                                            ' Stop Rinse
    Next

 Reset Drainon                                                ' Open Drain second cycle
 Bitwait Waterempty , Reset                                   ' Wait Drain
 Runtime = 180                                                ' SPIN
 Set Jobpending
 Reset Motoron                                                ' Start Rinse
 Reset Run_nspin                                              ' SPIN
 Start Timer0                                                 ' Start Timer/Counter
   Bitwait Jobpending , Reset                                 ' Wait to Finish

  Relays = 255                                                ' ALL OFF, INITIAL State
  Controls = 255

 Goto Loopagain

      End
بعد استبدال ألدوال السابقة و استبدال Start Timer0 بالمكافئ لها وهو TR0_bit = 1 ستصبح

كود:
'  Runmotor:
     Jobpending = 1                                 ' Timing flag
     Motoron  = 0                                   ' Start Motor
     TR0_bit  = 1                                   ' Start Timer/Counter
     do
     loop until Jobpending =0                       ' Wait to Finish
     Motoron     = 1                                ' stop motor
    For cntr = 0 To Rinse
       Drainon = 0                                  ' Open Drain
       do
       loop until Waterempty = 0                    ' Wait Drain
       Drainon = 1                                  ' Close Drain
       Wateron  = 0                                 ' Fill again
       do
       loop until Waterfull = 0
       Wateron  =  1                                ' Close Water
       Runtime = 300                                ' 1St Rinse
       Jobpending  = 1
       Motoron  = 1                                 ' Start Rinse
       TR0_bit  = 1                                 ' Start Timer
       do
       loop until Jobpending = 0                    ' Wait to Finish
       Motoron     = 1                              ' Stop Rinse
    Next cntr

  Drainon = 0                                       ' Open Drain second cycle
  do
  loop until Waterempty = 0                 ' Wait Drain
  Runtime = 180                                     ' SPIN
  Jobpending = 1
  Motoron = 0                                       ' Start Rinse
   Run_nspin  = 0                                   ' SPIN
   TR0_bit  = 1                                     ' Start Timer/Counter
   do
   loop until  Jobpending = 0                       ' Wait to Finish

  Relays = 255                                                ' ALL OFF, INITIAL State
  Controls = 255

 Goto Loopagain

end.
بقى الأمر الأخير Goto Loopagain مع العنوان Loopagain: يمكن استبدالهما بدورة أخرى مثلا تستبدل العنوان
While TRUE
ثم تستبدل Goto Loopagain
WEND
و استبقيتهم للآخر حتى لا يبدو البرنامج معقد و به كثير من التنبؤات ولكن يمكن استبدال شيء بأخر
المرة القادمة إن شاء الله سنستخدم ذات البرنامج بلغة C
رد مع اقتباس
إضافة رد

مواقع النشر (المفضلة)

أدوات الموضوع
انواع عرض الموضوع

تعليمات المشاركة
لا تستطيع إضافة مواضيع جديدة
لا تستطيع الرد على المواضيع
لا تستطيع إرفاق ملفات
لا تستطيع تعديل مشاركاتك

BB code is متاحة
كود [IMG] متاحة
كود HTML معطلة



الساعة الآن 08:44 PM.


Powered by vBulletin® Version 3.8.7
Copyright ©2000 - 2018, Jelsoft Enterprises Ltd.
الحقوق محفوظة لمنتديات الاليكترونيات العصرية

Security team

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77