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

   

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




أول البرنامج
بعد التهيئة السابقة وصلنا لأول البرنامج حيث العنوان التكرارى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 ثانية. الآن نشغل الموتور دورة الغسيل

باقى الدورات موضوعنا القادم بإذن الله

اعلانات

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



باقى الدورات
ألان ندير الموتور الفترة الزمنية المحددة ، ولكى نعرف الزمن يجب أن نقيم 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 من ميكروإلكترونيكا

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

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



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

كود:
' 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

بعد ذلك غلق الباب و تحديد الفترة الزمنية حسب الخيارات و هذا موضوعنا القادم بإذن الله


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



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

بعد ذلك غلق الباب و تحديد الفترة الزمنية حسب الخيارات و كانت

كود:
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


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



الغسالة باستخدام C51 و لغة C:
للأسف لا يوجد مصدر آخر سهل سوى ميكروإلكترونيكا لذا لا مقارنة سوى بين اللغتين و أتميل لها أتميل استوديو لكنه كبير جدا و ثقيل على الحاسب و سنبدأ بالبيزك و نحوله إلى C
سنبدأ بالتعريفات وكانت
كود:
' 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
قد تظن أنك تستطيع أن تعرف المنافذ أولا ثم تستخدمها فى تعريف الأطراف بعد ذلك كما فعلنا فى البيزك لكن لا ليس هنا، ستحصل على رسالة غريبة جدا أن المتوقع هو متغير عام Global Variable و لكنه وجد "مثلا" Leds ولا تسألنى لماذا لا يعتبر التعريف السابق للمنفذ Leds من النوع Global بينما هو يستخدمه استخدام عام و شامل فى كل البرنامج أى Global ولذا سنستخدم دوما اسم المنفذ و أصبحت بعد تعريف كل منها كمتغير
كود:
// DEFINITIONS char Leds at P0 ; char Relays at P1 ; char Switches at P2 ; char Controls at P3 ; sbit Fullled at P0_0_bit ; sbit Halfled at P0_1_bit ; sbit Smallled at P0_2_bit ; sbit Hotled at P0_3_bit ; sbit Mildled at P0_4_bit ; sbit Coldled at P0_5_bit ; sbit Wateron at P1_0_bit ; sbit Drainon at P1_1_bit ; sbit Heateron at P1_2_bit ; sbit Motoron at P1_3_bit ; sbit Run_nspin at P1_4_bit ; sbit Waterfull at P1_5_bit ; sbit Waterempty at P1_6_bit ; sbit Dooropen at P1_7_bit ; sbit Midtemp at P2_0_bit ; sbit Hitemp at P2_1_bit ; sbit Cold at P2_2_bit ; sbit Mild at P2_3_bit ; sbit Hot at P2_4_bit ; sbit Small at P2_5_bit ; sbit Half at P2_6_bit ; sbit Full at P2_7_bit ; sbit Run at P3_1_bit ; sbit Jobpending at F0_bit ; unsigned short Rinse ; unsigned short Cntr ; unsigned Runtime ; void External_Interrupt() org IVT_ADDR_EX0 { asm ajmp 0 ; } void Timer0_Interrupt() org IVT_ADDR_ET0 { if ( --Runtime = 0 ){ // End of time Jobpending = 0 ; // Clear Flag TR0_bit = 0 ; // stop timer 0 } } void main() { Begin:
بعد التعريفات تأتى تسمية المقاطعة بطريقة ميكروإلكترونيكا و أضاف لها لغة السى عدم التعرف على العنوان Begin لكونه لاحقا لذا اضطررت لاستخدام الأسيمبلى.
فى كود المقاطعة الثانى الخاص بالطوارئ أى المقاطعة الخارجية نجد ألتعليمه
كود:
 if ( --Runtime = 0 ){ 
وهى للمبتدئ تعنى ما يلى على خطوتين
Runtime = --Runtime 
if (Runtime = 0) {
و السطر الأول علامتى السالب يعنى انقص من المتغير التالى وهو هنا Runtime واحد أما لو كانا على يمين المتغير سيكون معناها انقص واحد لكن ليس الآن أى بمعنى لو كان بها 5 مثلا فكلمة IF سيكون على الخمسة و بعد القرار ستصبح 4 و الفرق لو بها 1 لو العلامات سابقة، سيصبح صفر ثم نسأل هل = صفر أم لا لكن لو على اليمين سنسأل أولا و الإجابة لا فننقص و ننفذ . لاحظ أيضا أن IF غير معروفة بينما if معروفة و كل الأوامر بالأحرف الصغيرة.
يلى ذلك جزء التعريفات و كما سبق مع ميكروإلكترونيكا سنحتاج تهيئة العدادات يدويا فالتعليمة Config غير مدعومة
أى أن هذا الكود التالى سيصبح كما سيلى بعد التعديل
كود:
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 On Int0 Emergency , Nosave On Timer0 Counttime Loopagain: Do Bitwait Run , Set ' Run button release If Full = 0 Then Leds = Leds Or &B00000111 : Reset Fullled 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 until Run = 0 ' Wait Run Press
الكود السابق أصبح بعد تغيير Enable,Config,Bitwait , Elseif لاحظ أيضا أن كلمة OR و التى تعنى وظيفة "أو" المنطقية ستستبدل بالرمز "|” و الوظيفة "مع" AND تستبدل بالرمز & أما العكس NOT فأصبح " ~ “ أجل هذه العلامة التى نستخدمها لتعنى "تقريبا يساوى أو يساوى بالتقريب" و ما يزيد الأمور إرباكا أنها على مستوى البت فقط أما XOR فتصبح ^ و هنا أحذر من أن هذه العلامة تعنى فى كثير من الحالات رفع للأس حيث 10^2 = 100 و فى حساب Boolean تزاوج العلامات فمثلا AND boolean تصبح && و "أو" OR تصبح || و العكس NOT تصبح" !” علامة التعجب أما XOR فبحثت على النت ولم أجد لها جواب – أعانك الله على الحفظ
فى البيزك عموما هى غير مدعومة لكن فى المترجمات الخاصة الوحدات المتقدمة مثل AVR فالكل يقول مدعومة ولا يذكر كيف، و الأفضل عملها يدويا
كود:
void main() { Begin: IE = 0B10000011 ; //Enable T0 & INT0 external TH0 = 205 ; //Auto reload TL0 = 205 ; // Start Value TMOD = 0b00000110 ; TCON = 1 ; // Clear All interrupts, Set INT0 Edge trigger SP = 70 ; // Move stack away Leds = 0b11011011 ; //Reset All PORTS! select Small cold cycle Relays = 255 ; Switches = 255 ; Controls = 255 ; EA_bit = 1 ; // Enable Interrupts do { } while (Run = 0) ; // Run button release Loopagain: do { if (Full = 0) { Leds = Leds | 0B00000111 ; Fullled = 0 ; } else if (Half = 0) { Leds = Leds | 0B00000111 ; Halfled = 0 ; } else if (Small = 0) { Leds = Leds | 0B00000111 ; Smallled =0 ; } if (Hot = 0) { Leds = Leds | 0B00111000 ; Hotled = 0 ; } else if (Mild = 0) { Leds = Leds | 0B00111000 ; Mildled = 0 ; } else if (Cold = 0 ) { Leds = Leds | 0B00111000 ; Coldled = 0 ; } } while ( Run = 1 ) ; // 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 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 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 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 سيصبح هكذا ، نلاحظ هنا أن دورة do-while يمكن اختصارها لأمر while فقط كما سيلى بعد Runmotor do{ } while (Dooropen = 1 ) ; // Wait Door to close Wateron = 0 ; // Fill with water do{ } while ( Waterfull = 1 ); // Wait full Tank Wateron = 1 ; // Close water Valve if (Coldled = 1) { // not Cold then Heateron = 0 ; } // Heater on if (Mildled = 0) { do { } while ( Midtemp = 1 ) ; } else { do { } while ( Hitemp = 1 ) ; } Heateron = 1 ; // Now Start Washing if ( Fullled = 0 ) { Runtime = 20 * 60 ; } else { if ( Halfled = 0 ) { Runtime = 480 ; } else { Runtime = 300 ; } } // Runmotor: Jobpending = 1 ; // Timing flag Motoron = 0 ; // Start Motor TR0_bit = 1 ; // start timer 0 while ( Jobpending = 1 ) ; // Wait to Finish Motoron = 0 ; // stop motor for ( Cntr = 0 ; Cntr < Rinse ; Cntr++ ) { Drainon = 0 ; // Open Drain while ( Waterempty = 0 ) ; // Wait Drain Drainon = 1 ; // Close Drain Wateron = 0 ; // Fill again while ( Waterfull = 0 ) ; // Wait fill up Wateron = 1 ; // close water valve Runtime = 300 ; // Rinse time Jobpending = 1 ; // timer flag Motoron = 0 ; // Start Rinse TR0_bit = 1 ; // start timer 0 while ( Jobpending = 0 ) ; // Wait to finish Motoron = 1 ; // Stop Rinse } Drainon = 0 ; // Open Drain second cycle while ( Waterempty = 0 ) ; // Wait Drain Runtime = 180 ; // SPIN time Jobpending = 1 ; // timer flag Run_nspin = 0 ; // high speed Motoron = 0 ; // Start SPIN TR0_bit = 1 ; // start timer 0 while ( Jobpending = 1 ) ; // wait end of time Relays = 255 ; // ALL OFF, INITIAL State Controls = 255 ; goto Loopagain ; }
المرة القادمة إن شاء الله سنكررها باستخدام AVR و لغة البيزك



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



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

أولا سنحاول الحفاظ على الهيكل العام للدائرة و نستبدل المتحكم و أول ما نلاحظه أننا استخدمنا الترانزستورات NPN مع الريلايات 12 فولت لا لسبب سوى شيوع هذه الطريقة و خشيت أن أبقى على الطريقة القديمة مخافة الظن أن هذا ما يجب أن يكون بينما لك مطلق الحرية فى تبنى أى من الحلين ، و إثباتا لذلك سأبقيه مع الليدات.
لهذا فكل ما نحتاجه هو تعديل أوامر التحكم فى الريلايات من Set إلى RESET و العكس بالعكس. و ستجد ذلك فى الكود مشروحا للتذكرة .
ثانيا لم أوصل دائرة الريسيت و دائرة الكريستال لآن المتحكم يدعم الريسيت الداخلى و مذبذب م س داخلى و لك الحرية فى استخدامهما بدلا من المكونات الخارجية لتحقيق الوفر ، فقط من خيارات المبرمجة يجب أن تختار هذه الخيارات في مجموعة تسمى فيوزات من المبرمجة وليست فى البرنامج.
وجب هنا إيضاح نقطة أن هناك أشياء تبرمج بالكود و أشياء تبرمج أثناء عملية البرمجة و من خلال المبرمجة ذاتها و تسمى فيوزات لآنها تبرمج مع الكود لكن فى كثير من الأحوال ستحتاج لمبرمجة توازى لإلغاء وضع هذه الفيوزات و تغييرها أما المبرمجة التوالى و التى تناسب البرمجة فى البوردة فيمكنها عادة أن تفعل هذه الفيوزات لكنها أحيانا تكون غير قادرة على إعادته هذه الفيوزات لأصلها باعتبار أنها خيارات المصمم ولا يجوز تغييرها بواسطة المستخدم.
استخدام الفيوزات فى العائلتين لكن الفرق الوحيد أن وضع هذه الفيوزات فى ميكروتشيب تضبطه من المترجم وهو يتولى إنشاء ما يلزم لذلك أما فى أتميل فيجب اختيار الفيوزات من واجهة المبرمجة ذاتها و ليس من المترجم.
و أخيرا المقاطعات حيث يجب توصيل التايمر الخارجى للطرف المناسب وهو هنا المنفذ B الطرف صفر و كان عليه أحد الريلايات WaterOn أى فتح صمام المياه للملو و سنضطر لتوصيله لمكان آخر و نختار مثلا PORTA.6 (أو اختار ما يناسبك)
الآن سننقل كود بيزك باسكوم C51 إلى باسكوم AVR و نرى ما يحدث ، نفتح صفحة جديدة ثم من قائمة options نختار Compiler ثم Chip. يفتح لنا عدة خيارات تحدد منها نوع المتحكم و تردد الكريستال و بعض الأمور الأخرى مثل لو تستخدم شاشة LCD أو المنفذ التسلسلى الخ ثم اضغط على زر ADD TO CODE فسيضيف مجموعة التعليمات السابق الحديث عنها ثم ننسخ النص السابق.
أسماء المنافذ تغيرت من صفر -1-2 الخ إلى أحرف لذا سنغيرها إلى PORTA,PORTB الخ. أيضا كما شرحنا عن وجود PINA لقراءة الطرف و أخيرا DDRA لتحديد اتجاه المنفذ A و مثله لباقى المنافذ

مقاومة الانحياز لأعلى أو التعليق لأعلى PULLUP هنا عامة لكل طرف و ليست لمنفذ واحد كما فى ميكروتشيب و تصبح فاعلة بجعل الطرف (أو المنفذ) دخول ثم تكتب فيه 1 . لاحظ أنه كدخول تقرأ منه لا أن تكتب فيه لذا هذه الكتابة تذهب لمقاومة Pullup و متاحة لكل الأطراف فى كل المنافذ و كل طرف يتحكم فيه على حده بهذه الطريقة.
لكن ماذا لو تحسبا لظرف ما يجب ألا تتاح هذه المقاومات؟ هل سنعدل كافة المنافذ أم ماذا؟ كلا فهناك بت واحدة اسمها PUD اختصار Pull Up Disable فى مسجل اسمه SFIOR وهى غالبا معروفة دون الحاجة لاسم المسجل. وهذه البت عادة = صفر و عند تغييرها إلى 1 توقف عمل كافة المقاومات فى كل المنافذ.

عندما تضغط على زرار "صح" سيعترض على التعليمات الخاصة بالتايمر صفر فالقيم TH,TL,TCON لم تعد موجودة و تغيرت لتوسعة عمليات هذا المؤقت فقد شمل العد التصاعدى أو التنازلى و المقارنة بالصفر أو 255 أو قيمة أخرى فى مسجل آخر باسم OCR0 و هذه يمكن توجيهها لتوليد موجة بتعديل عرض PWM .
بيزك باسكوم لا يدعم خاصية PWM لتايمر صفر ذو 8 بت لكنه يدعمها لتايمر 1 ذو 16 بت بصورة أشمل، لذا لو شئت فيمكنك استخدام مجموعة أوامر لتهيئه تايمر صفر لهذا الغرض . عموما فى هذا التطبيق سنحتاج فقط عد النبضات لذا يكفينا التنسيق الذاتى المدعم من المترجم. قد تكون النسخة المسجلة عدلت هذه السمة ولكنى لم اشتريها بعد.
سنحذف الثلاث أسطر الخاصين بالتعليمات TH,TL,TCON و نستبدلها بالأمر TIMER0=205
وهكذا سيصبح البرنامج
كود:
$regfile = "m16adef.dat" $crystal = 4000000 $hwstack = 40 $swstack = 16 $framesize = 32 ' DEFINITIONS Leds Alias Porta : Relays Alias Portb : Switches Alias Portc : Controls Alias Portd Fullled Alias Pina.0 : Halfled Alias Pina.1 : Smallled Alias Pina.2 Hotled Alias Pina.3 : Mildled Alias Pina.4 : Coldled Alias Pina.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 , Rinse As Byte , Cntr As Byte , Jobpending As Bit Emergency: Goto Begin Counttime: Decr Runtime Timer0 = 205 If Runtime = 0 Then Reset Jobpending Stop Timer0 End If Return Begin: Config Leds = Input : Config Switches = Input : Config Controls = Input Ddrb = &B00011110 Config Timer0 = Counter , Edge = Falling Timer0 = 205 ' Was Th0 = 205 ' Tl0 = 205 ' Tcon = 1 Enable Interrupts Enable Int0 Leds = &B11011000 ' Reset All PORTS! select Small cold cycle Relays = &B11100000 ' Set Pullups for pins5,6,7 Switches = 255 ' Writing ones to input activates Pullup resistors Controls = 255 ' " " " On Int0 Emergency , Nosave On Timer0 Counttime Bitwait Run , Set ' Run button release Loopagain: Do Do If Full = 0 Then Leds = Leds Or &B00000111 : Reset Fullled 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 Loop Until Run = 0 ' was If Run = 1 Then Goto Loopagain ' 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 If Coldled = 1 Then ' not Cold then Set Heateron ' was Reset Heateron 'Heater on If Mildled = 0 Then Bitwait Midtemp , Reset Else Bitwait Hitemp , Reset Reset Heateron ' was 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 ' Runmotor: Set Jobpending ' Timing flag Set Motoron ' was Reset Motoron' Start Motor Start Timer0 ' Start Timer/Counter Bitwait Jobpending , Reset ' Wait to Finish Reset Motoron ' was Set Motoron ' stop motor For Cntr = 1 To Rinse Set Drainon ' was Reset Drainon ' Open Drain Bitwait Waterempty , Reset ' Wait Drain Reset Drainon ' was Set Drainon ' Close Drain Set Wateron ' was Reset Wateron ' Fill again Bitwait Waterfull , Reset Reset Wateron ' was Set Wateron' Close Water Runtime = 300 ' 1St Rinse Set Jobpending Set Motoron ' was Reset Motoron' Start Rinse Start Timer0 ' Start Timer Bitwait Jobpending , Reset ' Wait to Finish Reset Motoron ' was Set Motoron ' Stop Rinse Next Set Drainon ' was Reset Drainon ' Open Drain second cycle Bitwait Waterempty , Reset ' Wait Drain Runtime = 180 ' SPIN Set Jobpending Set Motoron 'was Reset Motoron ' Start Rinse Set Run_nspin ' was Reset Run_nspin ' SPIN Start Timer0 ' Start Timer/Counter Bitwait Jobpending , Reset ' Wait to Finish Relays = &B11100000 ' ALL OFF, INITIAL State Loop ' was Goto Loopagain End
نلاحظ أيضا أننا استخدمنا Do – Loop و while-wend و لم يعد لدينا أوامر GOTO لكنها لن تختفى فهناك حالات مثل التى فى المقاطعة صريحة ولا يحل مكانها أى أمر آخر

المرة القادمة إن شاء الله سنشرح الدائرة بالميكرو C



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



الدائرة بلغة C
كما فعلنا سننسخ البرنامج بلغة C لمتحكم c51 و نضعها فى ميكروإلكترونيكا مترجم AVR و نحاول الترجمة ، طبعا المشاكل و الاعتراضات أغلبها تعود لمترجمات ميكروإلكترونيكا عوضا عن اللغة فاختلافات C سبق تحديدها. سنجد اعتراضات أسماء المنافذ يلى ذلك اعتراضات تغيير التعريفات فقد كانت
كود:
sbit Fullled at P0_0_bit ;
و أصبحت 
sbit Fullled at PortA.b0 ;
لذا سنضطر لتغيير كل التعريفات السابقة
سيعترض أيضا على تعريف المقاطعة و لن تجد شرحا للمتوافر فى ملف المساعدة و لكنه فقط يقول لك تجد المتاح فى مساعد التحرير حيث تكتب IVT ثم تضغط CNTRL+Space تظهر لك نافذة تختار منها أنواع المقاطعة المتاحة لذلك سنختار مرة مقاطعة Timer0 و مرة المقاطعة الخارجية.
أيضا أمر ajmp أصبح Jmp فقط من تغيرات لغة الأسيمبلى كما أن أسماء المسجلات للعدادات قد اختلفت لذا سنستبدل تعليماتها بالأمر TCNT0 = 205. الآن لم يعد لدينا Start timer, Stop Timer , Config Timer كما فى باسكوم لذا سنضطر لفهم المتحكم أكثر لكى نعيد تهيئته
العداد تايمر صفر يعتمد على المسجل TCCR0 و ألذى يحتوى على 4 مجموعات لمهام عدة لذا قمت بتلوين كل مجموعة لتسهيل التتبع. أيضا تحت الخانة نجد W=Write أى كتابة فقط R=Read أى قراءة فقط R/W=Read Write قراءة و كتابة ثم تحتها نجد قيمة البدء إما 0 أو 1 أو X أى غير محددة

البت رقم 7 و اسمها FOC0 اختصار Force Out Compare تجعل نتيجة المقارنة تحدث فورا و هى لا تعمل فى حال نظام PWM
البت 6 و 3 باسم WGM00,WGM02 لاحظ عدم التجاور وهما بمعنى Waveform Generator Mode يحددان النسق ألذى يعمل به فلو 00 أى صفر يكون النسق العادى ولو ثنائى 01 أى = 1 يكون النسق تعديل عرض النبضة مع تصحيح الوجه PWM phase correct ولو 10 أى =2 تعمل بنظام CTC أى Clear Timer on Compare Match أى يصفر العدان عند تطابق العد، أما لو ثنائى 11 أى = 3 يكون النسق Fast PWM أى تعديل عرض النبضة السريع.
البت رقم 4 و رقم 5 باسم COM00,COM01 أى Compare Output Match Mode فلو يساويان صفر تكون الأداء العادى للعداد أما الحالات الثلاث الباقية فلها وظائف تتغير بحسب ما إن كان WGM السابقة قد حددتPWM أو CTC أو Fast PWM
الثلاثة بت CS00,CS01,CS02 تحدد مصدر القدح
000 تعنى بدون مصدر وبذلك يوقف المؤقت ، لو 001 أى = واحد تأخذ من النبضات الداخلية لوحدة I/O بدون تقسيم ، ولو 010 أى 2 تقسم على 8 ولو 011 أى ثلاثة تقسم على 64 ولو 100 أى 4 تقسم على 256 ولو 101 أى حمسة تقسم على 1024 ولو 110 أى سته تأخذ من الخارج أى الطرف T0 الحافة هابطة ولو 7 أى 111 يأخذ من الخارج ذات الطرف T0 الحافة الصاعدة. و بذلك نوقف التايمر بجعلها صفر
المطلوب الآن أن نضع فيه صفر ليتوقف ثم نضع فيه 111 أى 7 ليعمل فى النسق العادى بحافة صاعدة أو 6 لحافة هابطة

رجاء لا تسألنى لماذا أفضل باسكوم عن ميكروإلكترونيكا !!!

المقاطعة :
كان فى C51 عدد 8 خانات لكل مقاطعة تنفذ فيها شيئ ما أو تنتقل أما هنا فلكل واحد 2 بايت فقط ولا تسأل لماذا فقد أصبح لديك 21 مصدر للمقاطعات المختلفة منها مثلا لكل تايمر عدد من المقاطعات واحد عند بلوغ العد الأقصى وواحد عند تساوى العد العلوى وآخر للعد السفلى الخ لذا فليس أمامك سوى الانتقال ما لم تكن المصادر المجاورة غير مستخدمة
أيضا كنتيجة لذلك لم يعد هناك مسجل واحد يكقى هذا العدد لذا تمت إضافة المقاطعة العامة فى مسجل الحالة Status register اختصارا SREG وهى البت رقم 7 ولها أمرين بالأسيمبلى هما SEI بمعنى Set Interrupts و الأمر CLI بمعنى Clear Interrupts وهى تعطل مع المقاطعة و فى نهاية كود الخدمة و بسبب تعليمه RETI تعود للإتاحة مرة أخرى – أو ما كانت عليه قبل المقاطعة ، كما يمكنك إتاحة المقاطعة داخل كود الخدمة بالأمر السابق لو شئت . هناك أيضا بت لكل من باقى المقاطعات ولكنها موزعة على مسجلات عدة مرتبطة بالوظيفة فستجد مع المؤقت إتاحة مقاطعته و هكذا. أعلم أنك تقول هذا أمر شاق ولا أستطيع مجادلتك فى هذا لكن هذا ما يجعل باسكوم أسهل باستخدام أمر Config ما لم تريد معرفة كافة التفاصيل و تتحكم به لأقصى حد و تتعمق فى الاحتراف فلا بأس يمكنك فعل ذلك باستخدام أى مترجم.
بالنسبة للمقاطعة الخارجية نجد المسجل MCUCR أى MCU Control Register حيث MCU = Micro Control Unit يختص الجزء الأيمن منه بهذه المقاطعة و الأيسر فى وضع الكمون Sleep حيث عندما لا نحتاج نشاطه يدخل فى مرحلة كمون لتوفير الطاقة لحين حدوث مقاطعة أو ريست ، و له 7 أوضاع تحددها SM0,SM1,SM2 أما SE فهى عامة بمعنى تنفيذ الخيار أو تعطيله للتأكد من أن الدخول فى هذا النمط بأمر المبرمج فقط و الأنماط هى، لو صفر يكون نمط Idle و لو ثنائى 001 أى 1 نمط تقليل ضوضاء للمحول ألتماثلى رقمى ولو 010 أى 2 يكون نمط Power Down و لو 011 أى 3 نمط توفير الطاقة و لو 4 أو 5 فغير موظفه ولو 110 أى 6 يكون وضع Standby ,ولو 111 أى 7 يكون extended standby وكلها تفرق فى أى الوظائف متاحة و ما يمكنه إيقاظ المتحكم.

الجزء الأيمن للمقاطعة الخارجية رقم 1 و البت3 و البت 2 باسم ISC11,ISC10 بمعنى Interrupt Sense يحددان كيفية الاستجابة فلو كانا صفر فالطرف INT1 يستجيب للمستوى صفر ولو كانا ثنائى 01 أى = 1 فيستجيب لأى تغيير و إن كانا ثنائى 10 أى = 2 فالاستجابة للحافة الهابطة و إن كانا ثنائى 11 أى 3 تكون للحافة الصاعدة
البت صفر و البت 1 باسم ISC01,ISC00 يعنيان نفس السلوك لمدخل INT0
عرفنا كيف نهيئ تايمر صفر و الدخول INT0 بقى أن نفعل المقاطعات

لدينا مسجل باسم General Interrupt Control Register أو مسجل التحكم العام فى المقاطعة و اختصارا GICR فيه البت 6 للمقاطعة INT0 و البت 7 للمقاطعة INT1 و البت 5 للمقاطعة INT2 و وضع 1 فى أى منها يفعل المقاطعة طبقا للضبط السابق. نلاحظ هنا أن المقاطعة ستحدث حتى لو كان الطرف خرج و ذلك إتاحة مقاطعة بالكود أى Software interrupt
و لدينا المسجل TIMSK-Timer-Counter Interrupt Mask Register وهو يتيح المقاطعة

فالبت صفر باسم TOIE0 تتيح المقاطعة OV أى عندما يصل العد إلى 255 ثم يقلب لصفر أما البت رقم 1 باسم OCIE0 فهى تتيح المقاطعة عندما يساوى العد تلك القيمة السابق حفظها فى مسجل باسم OCR0 أى Output Compare Register للتايمر صفر

و بهذا يمكننا أن نستخدم الخاصية الأولى و نعيد العد مرة أخرى فى العداد كما كان أو نضع فى OCR0 قيمة ما و لتكن 50 و نعد صعودا حتى تحدث المقاطعة لتساوى العد فنصفر العداد مرة أخرى
باقى المسجل لإتاحة مقاطعات مختلفة للتايمر 1 و التايمر 2 فى المتحكم
المرة القادمة إن شاء الله نكمل البرنامج


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



كود البرنامج
مما سبق سنستبدل تشغيل تايمر صفر بالكود TCCR0=6 أو 7 حسب الخافة هابطة أم صاعدة (هنا لا فرق) و إيقافه TCCR0=0
لإتاحة المقاطعة الخارجية GICR.6=1 أو INT0 = 1 وللأسف ميكروإلكترونيكا لا يقبل INT0 = 1 لذا سنستخدم GICR.6=1 و للتهيئه MCUCR=2 للحافة الهابطة و لإتاحة تايمر صفر نستخدم TOIE0 = 1 فى المسجل TIMSK و ميكروإلكترونيكا لا يقبل اسم البت ولذا نستخدم TIMSK=1 اسم المسجل و بالصدفة لا نحتاج لتفعيل أى بت أخرى فيه.
سيصبح الكود
كود:
// DEFINITIONS char Leds at PortA ; char Relays at PortB ; char Switches at Portc ; char Controls at Portd ; sbit Fullled at PortA.b0 ; sbit Halfled at PortA.b1 ; sbit Smallled at PortA.B2 ; sbit Hotled at PortA.b3 ; sbit Mildled at PortA.b4 ; sbit Coldled at PortA.b5 ; sbit Wateron at PortA.b6 ; sbit Drainon at Portb.b1 ; sbit Heateron at Portb.b2 ; sbit Motoron at Portb.b3 ; sbit Run_nspin at Portb.b4 ; sbit Waterfull at Portb.b5 ; sbit Waterempty at Portb.b6 ; sbit Dooropen at Portb.b7 ; sbit Midtemp at PortC.b0 ; sbit Hitemp at PortC.b1 ; sbit Cold at PortC.b2 ; sbit Mild at PortC.b3 ; sbit Hot at PortC.b4 ; sbit Small at PortC.b5 ; sbit Half at PortC.b6 ; sbit Full at PortC.b7 ; sbit Run at PortD.b1 ; bit Jobpending ; unsigned short Rinse ; unsigned short Cntr ; unsigned Runtime ; void External_Interrupt() org IVT_ADDR_INT0 { asm jmp 0 ; } void Timer0_Interrupt() org IVT_ADDR_TIMER0_OVF { TCNT0 = 205 ; if ( --Runtime = 0 ){ // end of time Jobpending = 0 ; // set flag TCCR0 = 0 ; // TR0_bit = 0 ; // stop timer 0 } } void main() { Begin: Sreg.b7 = 1 ; // was EA_bit = 1 ; // Enable Interrupts gicr.b6 = 1 ; // was IE = 0B10000011 ; //Enable T0 & INT0 external mcucr = 2 ; // Falling Edge trigger TIMSK = 1 ; // enable Timer0 over flow interrupt TCNT0 = 205; // TH0 = 205 ; //Auto reload TL0 = 205 ; // Start Value // TMOD = 0b00000110 ; TCON = 1 ; // Clr All interrupts, Set INT0 Edge trigger // SP = 70 ; //Move stack away ddra = 255 ; DDRB = 0b11111000 ; DDRC = 255 ; ddrd = 0b00000011 ; Leds = 0b11011000 ; //Reset All PORTS! select Small cold cycle Relays = 0B11100000 ; Switches = 255 ; // pullup enable Controls = 255 ; do { } while (Run = 0) ; // Run button release Loopagain: do { do { if (Full = 0) { Leds = Leds | 0B00000111 ; Fullled = 0 ; } else if (Half = 0) { Leds = Leds | 0B00000111 ; Halfled = 0 ; } else if (Small = 0) { Leds = Leds | 0B00000111 ; Smallled =0 ; } if (Hot = 0) { Leds = Leds | 0B00111000 ; Hotled = 0 ; } else if (Mild = 0) { Leds = Leds | 0B00111000 ; Mildled = 0 ; } else if (Cold = 0 ) { Leds = Leds | 0B00111000 ; Coldled = 0 ; } } while ( Run = 1 ) ; // Wait Run Press do{ } while (Dooropen = 1 ) ; // Wait Door to close Wateron = 0 ; // Fill with water do{ } while ( Waterfull = 1 ); // Wait full Tank Wateron = 1 ; // Close water Valve if (Coldled = 1) { // not Cold then Heateron = 0 ; } // Heater on if (Mildled = 0) { do { } while ( Midtemp = 1 ) ; } else { do { } while ( Hitemp = 1 ) ; } Heateron = 1 ; // Now Start Washing if ( Fullled = 0 ) { Runtime = 20 * 60 ; } else { if ( Halfled = 0 ) { Runtime = 480 ; } else { Runtime = 300 ; } } // Runmotor: Jobpending = 1 ; // Timing flag Motoron = 0 ; // Start Motor TCCR0 = 6 ; // was TR0_bit = 1 ; // start timer 0 falling edge while ( Jobpending = 1 ) ; // Wait to Finish Motoron = 0 ; // stop motor for ( Cntr = 0 ; Cntr < Rinse ; Cntr++ ) { Drainon = 0 ; // Open Drain while ( Waterempty = 0 ) ; // Wait Drain Drainon = 1 ; // Close Drain Wateron = 0 ; // Fill again while ( Waterfull = 0 ) ; // Wait fill up Wateron = 1 ; // close water valve Runtime = 300 ; // Rinse time Jobpending = 1 ; // timer flag Motoron = 0 ; // Start Rinse TCCR0 = 6 ; // was TR0_bit = 1 ; // start timer 0 while ( Jobpending = 0 ) ; // Wait to finish Motoron = 1 ; // Stop Rinse } Drainon = 0 ; // Open Drain second cycle while ( Waterempty = 0 ) ; // Wait Drain Runtime = 180 ; // SPIN time Jobpending = 1 ; // timer flag Run_nspin = 0 ; // high speed Motoron = 0 ; // Start SPIN TCCR0 = 6 ; // was TR0_bit = 1 ; // start timer 0 while ( Jobpending = 1 ) ; // wait end of time Relays = 0B11100000 ; // ALL OFF, INITIAL State Controls = 255 ; } while (1) ; // was goto Loopagain ; }
و أيضا استخدمنا DO لتحل محل goto و الكود أعتقد لا مشكلة فيه

المرة القادمة إن شاء الله سنكررها بالميكروتشيب PIC16C877A و اللغتان أيضا




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