![]() |
#91
|
|||
|
|||
![]()
شكرا اخي
|
#92
|
|||
|
|||
![]()
ضبط السرعة:
الآن لنضبط السرعة لو كانت بالزيادة سنبطئ الاستجابة و إن كانت بالنقصان سنجعلها فورية، وهذا باستخدام المتغير السابق ذكره وهو Sscntr أو Slow Start Counter و فرضنا له قيمة 5 لكنها يمكن أن تكون متغيرة برغبة المستخدم و تحتاج أزرار. أو تجعل أى زر من المستخدم يعرض المهام و 2 للزيادة و النقصان. هنا سننقص Sscntr بواحد فإن لم يكن = صفرا سنترك الدورة ولا نعدل شيئا و إلا سنضع 5 من المتغير SlowStart فى العداد Sscntr و نزود السرعة الحالية CurrSpeed بواحد ثم نذهب لضبط السرعة. كود:
SpeedUP: DJNZ SScntr,AdjSpeed MOV SScntr,#SlowStart INC CurrSpeed AdjSpeed: JNB OutLo,ShowValues ; update only when OutLo = 1 i.e motor stop MOV TH0,CurrSpeed ; The motor in off time, the next update is on time SETB TR0 ; Startt Timer0 ; Add here Current check if you like, then stop or decrease output. ShowValues: MOV A,CurrSpeed ; Hi=1 and low = 254 ACALL Bi2BCD_Ascii هنا نقطة لم نذكر عنها شيئا وهى قياس التيار و كتابته على الشاشة، حسنا فى الجزء الخاص بين SpeedUP و ShowValues يمكنك اختبار قيمة التيار و تقلل الخرج أو توقفة لو زاد عن حد معين أو ما شئت. التالى هو الكود مجمع كود:
; This program Controls A DC motor according to a Volume setting. $NOMOD51 $INCLUDE (89S8253.MCU) ADC equ P0 LEDS EQU P1 LCD Equ P2 Cmnds Equ P3 AutoLED Equ LEDS.0 ManLED Equ LEDS.1 SaveLed Equ LEDS.2 StopLed equ LEDS.3 RUNLed Equ LEDS.4 ADCStrt EQU LEDS.5 InotV EQU LEDS.6 PWMout EqU LEDs.7 RunSW EQU P3.0 SaveSW Equ P3.1 StopSW Equ P3.2 ManAuto Equ P3.3 EOC EQU P3.5 LCD_RS Equ P3.6 LCD_Ena EQU P3.7 Man_Nauto EQU 10h ; FF Manual, 0 Auto SavedSpeed EQU 11h ReqSpeed EQU 12H CurrSpeed EQU 13h ; Duity Ratio SScntr EQU 14H ; Slow Start Counter Del1 EQU 15h Del2 EQU 16h Disp00 EQU 20h Disp01 Equ 21h Disp02 Equ 22h Disp03 Equ 23h Disp04 Equ 24h Disp05 Equ 25h Disp06 Equ 26h Disp07 Equ 27h Disp08 Equ 28h Disp09 Equ 29h Disp10 Equ 2Ah Disp11 Equ 2Bh Disp12 Equ 2Ch Disp13 Equ 2Dh Disp14 Equ 2Eh Disp15 Equ 2Fh SlowStart Equ 5 Line1 EQU 0 ; 00h :0fh Line2 EQU 40H ; 40H :4FH Line3 EQU 10H ; 10H :1FH Line4 EQU 50H ; 50H :5FH OutLo EQU F0 org 000 AJMP BeginP org 003h ; Adress of INT0 (IE0)Emergency SETB PWMout ; Hi = STOP CLR TR0 ; Stop counter SJMP Emrgncy org 00Bh ; Adress of Interrupt Timer 0 (TF0) XRL TH0,#255 ; Complement Timer Hi CPL OutLo MOV C,OutLo MOV PWMout,C RETI BeginP: CLR LCD_Ena ; Clear LCD ENA bit Init_LCD MOV IE,#10000011b ; Enable T0 & INT0 external MOV TMOD,#00000110b ; T0 8bit counter auto reload MOV TCON,#1 ; Clr All interrupts, Set INT0 Edge trigger #5 for INT0,INT1 mov Del1,#20 ; call del with 20 ms ACALL wait_n_ms ; Wait LCD MOV LCD,#00111000b ; 8bit, 2line, 5X8 display LCALL Do_LCD ; Execute: WAIT IS ADDED TO STORE_CMD INSTEAD MOV LCD,#00001100b ; Set display on,cursor off, blinking off LCALL Do_LCD MOV LCD,#00000110b ; Set Increment +1 mode, move screen off LCALL Do_LCD MOV LCD,#00010100b ; Shift Cursor, dcn=right LCALL Do_LCD MOV LCD,#1 ; clear entire display LCALL Do_LCD ORL EECON,#00010000b ; XX,EELD Page/nbyte, mem Write ena,MOVX w dptr to eeMem,DPS=0 Bank1 or 1 bank2 ; 1 = ready 0 busy, if VDD << it is ZERO (Read only) Write_Inh MOV DPTR,#Testing ACALL WriteMsg ; write testing pls wait ACALL GetADC ; if error will ret to ADC Fault SJMP OKey ADCFault: Setb PWMout MOV DPTR,#ADCErr ACALL WriteMsg SJMP $ OKey: Emrgncy: MOV Cmnds,#00111111b ; All Off RS,E low MOV ADC,#255 MOV LEDs,#11110101b ; PWM off,InV=I,ADC start,RUN off,Stop On,Save off,Manual On,Auto Off MOV SP,#70 ; Move stack away MOV WDTCON,#01101010b ; 7,6,5 time,WDTidle=0,DISRTO(dis Rst out)=no out,HWDT Hard wdt=no ; WSWRST soft reset ,WDTEN read only disabled low power MOV DPTR,#0 ; Read Mem 00 MOVX A,@DPTR MOV MAN_Nauto,A ; MAN_Nauto JZ Auto CLR MANLED SETB AutoLED SJMP GoOn Auto: CLR AutoLED SETB ManLED GoOn: INC DPTR MOVX A,@DPTR MOV SavedSpeed,A ; Value MOV SScntr,#SlowStart MOV TL0,#254 ; Hi=1 and low = 254 MOV TH0,#1 SETB OutLo ; Zero =Motor Run, 1= Motor Off. OutLo = PWMout MOV CurrSpeed,#0 ; Start from zero JNB STOPsw,$ ; Wait while sw pressed MOV A,MAN_NAuto SUBB A,#1Fh ; C if zero or 0f, otherwise defective JC Looping MOV DPTR,#MemFlt ACALL WriteMsg Looping: ORL WDTCON,#2 ; clear WDT JNB MANAuto,Save CPL MANLED ; Switch AutuMan CPL AutoLED JNB MANAuto,$ ; Wait Sw released JB MANLED,SetMan ; MAN off, set man on CLR AutoLED ; Auto On MOV MAN_Nauto,#0 ; MAN_Nauto =0 MOV DPTR,#Auto4 SJMP WriteIT SetMan: CLR MANLED ; Man On Setb AutoLED ; Auto Off MOV MAN_Nauto,#0Fh ; MAN_Nauto = 0F mem default MOV DPTR,#Man4 WriteIt: ACALL LCD4 Save: JB SaveSw,RUN ; Save Not Pressed ACALL WriteEEPROM Run: JNB RUNSW,GoNow ; RUN pressed JNB STOPled,ShowValues ; Stop Mode do nothing SJMP Running GoNow: JNB RUNSW,$ ; Wait release CLR RUNLed SETB STOPLed Running: ; Runing ORL WDTCON,#3 ; Start and clear WDT MOV A,Man_Nauto JNZ ManualControl MOV ReqSpeed,SavedSpeed ; Set required Speed as saved SJMP SetMotor ManualControl: CLR InotV ACall GetADC MOV ReqSpeed,A ; Set required speed as ADC SetMotor: ; set pwm MOV A,ReqSpeed SUBB A,CurrSpeed ; If Curr > Req in A then carry=1 and needs to slow down JNC SpeedUP MOV CurrSpeed,ReqSpeed ; Slow Down at once SJMP AdjSpeed SpeedUP: DJNZ SScntr,AdjSpeed MOV SScntr,#SlowStart INC CurrSpeed AdjSpeed: JNB OutLo,ShowValues ; update only when OutLo = 1 i.e motor stop MOV TH0,CurrSpeed ; The motor in off time, the next update is on time SETB TR0 ; Startt Timer0 ShowValues: MOV A,CurrSpeed ACALL Bi2BCD_Ascii MOV Disp00,R7 MOV Disp01,R6 MOV Disp02,R5 MOV Disp03,#"0" MOV Disp05,#" " MOV Disp06,#"R" MOV Disp07,#"P" MOV Disp08,#"M" MOV Disp09,#"." MOV Disp10,#26h ; Type "&" MOV LCD,#2 ; Goto HOME ACALL WriteLine ; Line no 1 = 00, it has goto line nu ORL WDTCON,#2 ; clear WDT SETB InotV ; Get Current Reading ACALL GetADC ACALL Bi2BCD_ASCII MOV Disp00,R7 MOV Disp01,R6 MOV Disp02,#"." MOV Disp03,R5 MOV Disp05,#"A" MOV Disp06,#"m" MOV Disp07,#"p" MOV Disp08,#"s" MOV Disp09,#" " MOV Disp10,#" " MOV LCD,Line2+080H ; 80H to create Goto Location in LCD memory ACALL WriteLine ; Line no 1 = 00 AJMP Looping Bi2BCD_Ascii: ; converts data in Acc to 3 digits Ascii in R5(units) and R6(tens),R7(Hundred) MOV B,#100 DIV AB ; Devide A/100, Hunderds in A, remainder in B ORL A,#30h ; Convert to ascii MOV R7,A ; save 100's MOV A,B ; Get remainder MOV B,#10d ; DIV AB ; Devide A/10, Tens in A, remainder in B ORL A,#30h ; Convert to ascii MOV R6,A ; save Units ORL B,#30h MOV R5,B ; put result RET WriteEEPROM: ; Address in A reply in A CLR SaveLED ORL EECON,#00111000b ; set page write mode MOV DPTR,#0 MOV A,MAN_Nauto MOVX @DPTR,A INC DPTR ANL EECON,#11011111b ; End page write MOV A,ReqSpeed MOVX @DPTR,A MOV Del1,#5 acall Wait_n_ms ANL EECON,#11000111b ; End write cycle SETB SaveLED RET GetADC: ; Set ADC adress, reply in A SetB ADCStrt nop Clr ADCStrt MOV Del1,#20 DJNZ DEL1,$ ; Now EOC should be zero JB EOC,Fault ; if still one it is a defective chip MOV DEL1,#100 ADCloopChk: JB EOC,ADCOK ; if EOC = Hi again it is ok DJNZ DEL1,ADCloopChk ; did not responde Fault: AJMP ADCFault ADCOK: MOV A,ADC RET Do_LCD: CLR LCD_RS ; Command Reg SJMP LCD_CLK Writ_LCD: SETB LCD_RS ; Data Reg NOP LCD_CLK: SETB LCD_Ena ; NOP ; DELAY > 175 ns CLR LCD_Ena ACALL wait_120 ; Wait Execution CurTime RET WriteLine: ; Put Line number on buss then call acall Do_Lcd ; MOV R0,#Disp00 LineLoop: Mov LCD,@R0 ACALL Writ_LCD INC R0 CJNE R0,#Disp11,LineLoop RET ClrTxt: MOV R0,#Disp00 TTT: Mov @R0,#20h Inc R0 cjne R0,#30h,TTT Ret LCD4: MOV LCD,#13+80H ; 80H is Goto Command + address 13 ACALL Do_LCD MOV R7,#4 ; write 4 chrs SJMP NextC RET WriteMsg: ; Writes a message on LCD, start in DPTR ANL EECON,#11111011b ; Clear DPS bit in EECOM to selecl DPTR0 MOV R7,#16 ; 16 character NextC: CLR A MOVC A,@A+DPTR ; Read 1st byte MOV LCD,A ; put on lcd data ACALL Writ_LCD INC DPTR DJNZ R7,NextC RET Wait_n_ms: ; 333 instruction / ms ; Time in ms saved in Del1 MOV Del2,#165 _wait_n: nop DJNZ Del2,_Wait_n DJNZ Del1,Wait_n_ms RET wait_120: ; 3usec per inst MOV Del2,#38 RET Testing: DB "Testing Pls Wait" ADCErr: DB "ADC: No Responce" MemFlt: DB "Mem Err,MAN Def " Auto4: DB "Auto" Man4: DB "Manu" end |
#93
|
|||
|
|||
![]()
الدائرة بمتحكم AVR و لغة البيزك
يمكن استخدام ATMega16A وهو سيكون أسهل لكن فضلت استخدام ATMega8A الأصغر حجما ، و لم لا؟ هنا سنستخدم طرف Aref كمرجع للمحول و من ثم يمكنك قياس أى فولت ليطابق أى قيمة و لا حاجة للمعادلات المعقدة. ما زلت حقا ستضرب و تقسم و لكنك ستقول بدلا من 5 / 1024 = 0.0048828125 فولت أو 4.8828125 مللى فولت لكل عد ستقول Vref مقسومة على 1024 أى لو ضبطه على قيمة أقل مثلا 4.096 فولت سيكون كل عد = 4 مللى فولت صحيحة ولو 4.608 فولت ستصبح 4.5 مللى فولت لكل عد. طبعا ستقول معك حق لكنه غير قابل للتنفيذ فكيف أحصل على هذه القيم الصعبة؟ حسنا كما سبق أن ذكرنا المقاومة ذات 10 لفات و يكفى أن تضع قيمة معلومة على الدخول فتجد قراءة خاطئة و عندها قم بتغيير ضبط المقاومة ستجد القراءة تغيرت حتى تصل لما تريد. نظرا لقلة عدد الأطراف فقد استخدمنا الدائرة الداخلية لتوليد النبضات حتى نستخدم أطراف الكريستال كدخول/خروج أيضا زر التوقف أضفناه على دائرة RESET وهى أدق على أى حال ففى المقاطعة لو لم تكن متاحة لن يتوقف الموتور. أيضا وصلنا مفتاح السرعة على ADC0 و حساس التيار على ADC1 و استخدمنا باقى الأطراف بما يوفر افضل التوصيلات فيما عدا مخرج PWM و ألذى تقيده الشركة OC1A أو OC1B . الدائرة سهلة و بسيطة ولا يوجد بها كثير من التعقيدات و هكذا يمكن تصورها أيضا استخدمنا الطريقة التقليدية حيث 1 يعنى الموتور يعمل و ألليد يضيء و الصفر يعنى توقف الموتور و إطغاء ألليد. المرة القادمة إن شاء الله نبدأ البرمجة |
#94
|
|||
|
|||
![]()
المؤقتات و تفعيل PWM
للمتحكم ثلاث مؤقتات صفر وواحد و إثنين ، لذا سنأخذ فكرة عن كل منهم قبل البدء، ليس بهدف البرمجة بلغة الأسيمبلى ، لكن لسبب أهم وهو عندما تتعامل مع اللغة العالية قد تفهم توجيهاتها بصورة و المقصود بها أمر آخر لذا لو علمت ماذا يمكن له أن يفعل ستدرك هل هذا هو القصد أم لا. و أيضا يمكنك تخطى تهيئة اللغة المستخدمة و توفر أنت تهيئتك المناسبة ثم تكمل باقى البرمجة. لاحظ هنا أن اللغات العالية تعتمد أساسا على المكتبات و التى هى أبعد ما تكون عن الكمال لذا تتبنى نسق واحد لكل عداد تضع فيه خياراتها، و علمنا بما هو متاح يعطى لنا رؤية أوسع. المؤقت Tomer0 يعمل كالسابق كعداد من 8 بت و يمكننا استخدامه بنفس الأسلوب و يتشارك مع Timer1 ذات المقسم السابق Prescaler عندما يعمل كمؤقت لكنه يمكن أن يأخذ نسبة تقسيم مختلفة عن الآخر و كل منهما يتعامل مع المذبذب الرئيسى بنسبة خاصة به إما 1 أو 8 أو 64 أو 256 أو 1024 و حتى إيقاف و تشغيل أى منهما لا يؤثر على الآخر. أيضا يمكنه العمل كعداد بدون تقسيم سابق و يأخذ من الطرف الخارجى و يمكنه أيضا أن يستشعر الحافة الصاعدة أو الهابطة . محتوى العداد فى مسجل باسم TCNT0 وهى اختصار مباشر لاسمه و نسبة التقسيم و مصدر النبضات و تشغيله فى مسجل باسم TCCR0 حيث الثلاثة بت الصغرى تحدد كل شيء وهى باسم CS00,CS01,CS01 اختصار لاسم Clock Select ثم رقم التايمر وهو صفر ثم رقم البت 0,1,2 وهم معا بالطبع يعطوا من صفر إلى 7 لو بقيمة صفر فلا مصدر للنبضات و العداد متوقف لو = 1 متصل بالنبضات أى مؤقت و بدون تقسيم لو =2 بنسبة تقسيم 8 لو = 3 فبنسبة تقسيم 64 لو =4 فبنسبة تقسيم 256 لو = 5 فبنسبة تقسيم1024 لو = 6 فمتصل بالطرف الخارجى أى عداد و يستشعر القمة الهابطة. لو = 7 فمتصل بالطرف الخارجى أى عداد و يستشعر القمة الصاعدة. الموقت Timer1 و المؤقت Timer2 يمكن أن يعمل أى منهما كمؤقت أو عداد و له ضبط لخيارات تعديل عرض النبضة PWM إتاحة المقاطعات مشتركة للمؤقتات الثلاث فى مسجل باسم TIMSK و البت صفر له تخص هذا التايمر. المؤقت 2 موضوعنا القادم بإذن الله |
#95
|
|||
|
|||
![]()
جزاك الله خير مهندس ماجد عباس
|
![]() |
مواقع النشر (المفضلة) |
أدوات الموضوع | |
انواع عرض الموضوع | |
|
|